Skip to content

Commit eb12861

Browse files
committed
Auto merge of rust-lang#17916 - ShoyuVanilla:issue-17711, r=Veykril
fix: Wrong BoundVar index when lowering impl trait parameter of parent generics Fixes rust-lang#17711 From the following test code; ```rust //- minicore: deref use core::ops::Deref; struct Struct<'a, T>(&'a T); trait Trait {} impl<'a, T: Deref<Target = impl Trait>> Struct<'a, T> { fn foo(&self) -> &Self { self } fn bar(&self) { let _ = self.foo(); } } ``` when we call `register_obligations_for_call` for `let _ = self.foo();`, https://github.com/rust-lang/rust-analyzer/blob/07659783fdfd4ec0a0bffa93017e33e31e567e42/crates/hir-ty/src/infer/expr.rs#L1939-L1952 we are querying `generic_predicates` and it has `T: Deref<Target = impl Trait>` predicate from the parent `impl Struct`; https://github.com/rust-lang/rust-analyzer/blob/07659783fdfd4ec0a0bffa93017e33e31e567e42/crates/hir-ty/src/lower.rs#L375-L399 but as we can see above, lowering `TypeRef = impl Trait` doesn't take into account the parent generic parameters, so the `BoundVar` index here is `0`, as `fn foo` has no generic args other than parent's, But this `BoundVar` is pointing at `'a` in `<'a, T: Deref<Target = impl Trait>>`. So, in the first code reference `register_obligations_for_call`'s L:1948 - `.substitute(Interner, parameters)`, we are substituting `'a` with `Ty`, not `Lifetime` and this makes panic inside the chalk. This PR fixes this wrong `BoundVar` index in such cases
2 parents d2d41b4 + c4b8c65 commit eb12861

File tree

2 files changed

+50
-18
lines changed

2 files changed

+50
-18
lines changed

src/tools/rust-analyzer/crates/hir-ty/src/lower.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -377,26 +377,25 @@ impl<'a> TyLoweringContext<'a> {
377377
// Count the number of `impl Trait` things that appear within our bounds.
378378
// Since t hose have been emitted as implicit type args already.
379379
counter.set(idx + count_impl_traits(type_ref) as u16);
380-
let (
381-
_parent_params,
382-
self_param,
383-
type_params,
384-
const_params,
385-
_impl_trait_params,
386-
lifetime_params,
387-
) = self
380+
let kind = self
388381
.generics()
389382
.expect("variable impl trait lowering must be in a generic def")
390-
.provenance_split();
391-
TyKind::BoundVar(BoundVar::new(
392-
self.in_binders,
393-
idx as usize
394-
+ self_param as usize
395-
+ type_params
396-
+ const_params
397-
+ lifetime_params,
398-
))
399-
.intern(Interner)
383+
.iter()
384+
.enumerate()
385+
.filter_map(|(i, (id, data))| match (id, data) {
386+
(
387+
GenericParamId::TypeParamId(_),
388+
GenericParamDataRef::TypeParamData(data),
389+
) if data.provenance == TypeParamProvenance::ArgumentImplTrait => {
390+
Some(i)
391+
}
392+
_ => None,
393+
})
394+
.nth(idx as usize)
395+
.map_or(TyKind::Error, |id| {
396+
TyKind::BoundVar(BoundVar { debruijn: self.in_binders, index: id })
397+
});
398+
kind.intern(Interner)
400399
}
401400
ImplTraitLoweringState::Disallowed => {
402401
// FIXME: report error

src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2162,3 +2162,36 @@ fn main() {
21622162
"#]],
21632163
);
21642164
}
2165+
2166+
#[test]
2167+
fn issue_17711() {
2168+
check_infer(
2169+
r#"
2170+
//- minicore: deref
2171+
use core::ops::Deref;
2172+
2173+
struct Struct<'a, T>(&'a T);
2174+
2175+
trait Trait {}
2176+
2177+
impl<'a, T: Deref<Target = impl Trait>> Struct<'a, T> {
2178+
fn foo(&self) -> &Self { self }
2179+
2180+
fn bar(&self) {
2181+
let _ = self.foo();
2182+
}
2183+
2184+
}
2185+
"#,
2186+
expect![[r#"
2187+
137..141 'self': &'? Struct<'a, T>
2188+
152..160 '{ self }': &'? Struct<'a, T>
2189+
154..158 'self': &'? Struct<'a, T>
2190+
174..178 'self': &'? Struct<'a, T>
2191+
180..215 '{ ... }': ()
2192+
194..195 '_': &'? Struct<'?, T>
2193+
198..202 'self': &'? Struct<'a, T>
2194+
198..208 'self.foo()': &'? Struct<'?, T>
2195+
"#]],
2196+
);
2197+
}

0 commit comments

Comments
 (0)