Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #17916 - ShoyuVanilla:issue-17711, r=Veykril
fix: Wrong BoundVar index when lowering impl trait parameter of parent generics Fixes #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
bors 2024-08-18
parent e4edf6c · parent d7431ec · commit 469b062
-rw-r--r--crates/hir-ty/src/lower.rs35
-rw-r--r--crates/hir-ty/src/tests/regression.rs33
2 files changed, 50 insertions, 18 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 446f1853c8..79b096068d 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -377,26 +377,25 @@ impl<'a> TyLoweringContext<'a> {
// Count the number of `impl Trait` things that appear within our bounds.
// Since t hose have been emitted as implicit type args already.
counter.set(idx + count_impl_traits(type_ref) as u16);
- let (
- _parent_params,
- self_param,
- type_params,
- const_params,
- _impl_trait_params,
- lifetime_params,
- ) = self
+ let kind = self
.generics()
.expect("variable impl trait lowering must be in a generic def")
- .provenance_split();
- TyKind::BoundVar(BoundVar::new(
- self.in_binders,
- idx as usize
- + self_param as usize
- + type_params
- + const_params
- + lifetime_params,
- ))
- .intern(Interner)
+ .iter()
+ .enumerate()
+ .filter_map(|(i, (id, data))| match (id, data) {
+ (
+ GenericParamId::TypeParamId(_),
+ GenericParamDataRef::TypeParamData(data),
+ ) if data.provenance == TypeParamProvenance::ArgumentImplTrait => {
+ Some(i)
+ }
+ _ => None,
+ })
+ .nth(idx as usize)
+ .map_or(TyKind::Error, |id| {
+ TyKind::BoundVar(BoundVar { debruijn: self.in_binders, index: id })
+ });
+ kind.intern(Interner)
}
ImplTraitLoweringState::Disallowed => {
// FIXME: report error
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 26e9243e73..01862aa2a3 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -2162,3 +2162,36 @@ fn main() {
"#]],
);
}
+
+#[test]
+fn issue_17711() {
+ check_infer(
+ r#"
+//- 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();
+ }
+
+}
+"#,
+ expect![[r#"
+ 137..141 'self': &'? Struct<'a, T>
+ 152..160 '{ self }': &'? Struct<'a, T>
+ 154..158 'self': &'? Struct<'a, T>
+ 174..178 'self': &'? Struct<'a, T>
+ 180..215 '{ ... }': ()
+ 194..195 '_': &'? Struct<'?, T>
+ 198..202 'self': &'? Struct<'a, T>
+ 198..208 'self.foo()': &'? Struct<'?, T>
+ "#]],
+ );
+}