about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-05-02 10:04:13 +0000
committerbors <bors@rust-lang.org>2024-05-02 10:04:13 +0000
commitc5eaf59e43da63e047c4d155528aced804804ac0 (patch)
tree5328c3c455c8fd83a08192a5fbe1ec542004f39a
parent675197ab064507090ba18357b2e78f53fc732610 (diff)
parentf190ce61b70883c3681b88773978fe539885f637 (diff)
downloadrust-c5eaf59e43da63e047c4d155528aced804804ac0.tar.gz
rust-c5eaf59e43da63e047c4d155528aced804804ac0.zip
Auto merge of #17175 - Veykril:fix-implicit-ty-args, r=Veykril
fix: Fix implicit ty args being lowered where they shouldn't

Fixes https://github.com/rust-lang/rust-analyzer/issues/17173
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/generics.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs211
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs21
4 files changed, 116 insertions, 120 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
index 3a277ecb90b..10a1d65bb93 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
@@ -377,7 +377,7 @@ impl GenericParamsCollector {
         }
     }
 
-    pub(crate) fn fill_implicit_impl_trait_args(
+    fn fill_implicit_impl_trait_args(
         &mut self,
         db: &dyn DefDatabase,
         exp: &mut Lazy<(Arc<DefMap>, Expander), impl FnOnce() -> (Arc<DefMap>, Expander)>,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
index 6aa5a63d628..199b8daa37e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
@@ -662,7 +662,7 @@ impl<'a> Ctx<'a> {
             let attrs = RawAttrs::new(self.db.upcast(), &param, self.body_ctx.span_map());
             debug_assert!(self.generic_param_attr_buffer.insert(item, attrs).is_none());
         };
-
+        self.body_ctx.take_impl_traits_bounds();
         let mut generics = GenericParamsCollector::default();
 
         if let HasImplicitSelf::Yes(bounds) = has_implicit_self {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index 706b034821e..04e2ded05a5 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -345,51 +345,43 @@ impl<'a> TyLoweringContext<'a> {
                     }
                     ImplTraitLoweringState::Param(counter) => {
                         let idx = counter.get();
-                        // FIXME we're probably doing something wrong here
-                        counter.set(idx + count_impl_traits(type_ref) as u16);
-                        if let Some(generics) = self.generics() {
-                            let param = generics
-                                .iter()
-                                .filter(|(_, data)| {
-                                    matches!(
-                                        data,
-                                        GenericParamDataRef::TypeParamData(data)
-                                        if data.provenance == TypeParamProvenance::ArgumentImplTrait
-                                    )
-                                })
-                                .nth(idx as usize)
-                                .map_or(TyKind::Error, |(id, _)| {
-                                    if let GenericParamId::TypeParamId(id) = id {
-                                        TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
-                                    } else {
-                                        // we just filtered them out
-                                        unreachable!("Unexpected lifetime or const argument");
-                                    }
-                                });
-                            param.intern(Interner)
-                        } else {
-                            TyKind::Error.intern(Interner)
-                        }
+                        counter.set(idx + 1);
+                        let kind = self
+                            .generics()
+                            .expect("param impl trait lowering must be in a generic def")
+                            .iter()
+                            .filter_map(|(id, data)| match (id, data) {
+                                (
+                                    GenericParamId::TypeParamId(id),
+                                    GenericParamDataRef::TypeParamData(data),
+                                ) if data.provenance == TypeParamProvenance::ArgumentImplTrait => {
+                                    Some(id)
+                                }
+                                _ => None,
+                            })
+                            .nth(idx as usize)
+                            .map_or(TyKind::Error, |id| {
+                                TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
+                            });
+                        kind.intern(Interner)
                     }
                     ImplTraitLoweringState::Variable(counter) => {
                         let idx = counter.get();
-                        // FIXME we're probably doing something wrong here
-                        counter.set(idx + count_impl_traits(type_ref) as u16);
+                        counter.set(idx + 1);
                         let (
                             _parent_params,
                             self_params,
-                            list_params,
+                            type_params,
                             const_params,
                             _impl_trait_params,
                             _lifetime_params,
-                        ) = if let Some(generics) = self.generics() {
-                            generics.provenance_split()
-                        } else {
-                            (0, 0, 0, 0, 0, 0)
-                        };
+                        ) = 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_params + list_params + const_params,
+                            idx as usize + self_params + type_params + const_params,
                         ))
                         .intern(Interner)
                     }
@@ -1150,84 +1142,77 @@ impl<'a> TyLoweringContext<'a> {
                     binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
                 );
                 if let Some(type_ref) = &binding.type_ref {
-                    if let (
-                        TypeRef::ImplTrait(bounds),
-                        ImplTraitLoweringState::Param(_)
-                        | ImplTraitLoweringState::Variable(_)
-                        | ImplTraitLoweringState::Disallowed,
-                    ) = (type_ref, &self.impl_trait_mode)
-                    {
-                        for bound in bounds {
-                            predicates.extend(
-                                self.lower_type_bound(
-                                    bound,
-                                    TyKind::Alias(AliasTy::Projection(projection_ty.clone()))
-                                        .intern(Interner),
-                                    false,
-                                ),
-                            );
+                    match (type_ref, &self.impl_trait_mode) {
+                        (TypeRef::ImplTrait(_), ImplTraitLoweringState::Disallowed) => (),
+                        (
+                            _,
+                            ImplTraitLoweringState::Disallowed | ImplTraitLoweringState::Opaque(_),
+                        ) => {
+                            let ty = self.lower_ty(type_ref);
+                            let alias_eq =
+                                AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
+                            predicates
+                                .push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
                         }
-                    } else {
-                        let ty = 'ty: {
-                            if matches!(
-                                self.impl_trait_mode,
-                                ImplTraitLoweringState::Param(_)
-                                    | ImplTraitLoweringState::Variable(_)
-                            ) {
-                                // Find the generic index for the target of our `bound`
-                                let target_param_idx = self
-                                    .resolver
-                                    .where_predicates_in_scope()
-                                    .find_map(|(p, _)| match p {
-                                        WherePredicate::TypeBound {
-                                            target: WherePredicateTypeTarget::TypeOrConstParam(idx),
-                                            bound: b,
-                                        } if b == bound => Some(idx),
-                                        _ => None,
-                                    });
-                                if let Some(target_param_idx) = target_param_idx {
-                                    let mut counter = 0;
-                                    let generics = self.generics().expect("generics in scope");
-                                    for (idx, data) in generics.params.type_or_consts.iter() {
-                                        // Count the number of `impl Trait` things that appear before
-                                        // the target of our `bound`.
-                                        // Our counter within `impl_trait_mode` should be that number
-                                        // to properly lower each types within `type_ref`
-                                        if data.type_param().is_some_and(|p| {
-                                            p.provenance == TypeParamProvenance::ArgumentImplTrait
-                                        }) {
-                                            counter += 1;
-                                        }
-                                        if idx == *target_param_idx {
-                                            break;
-                                        }
+                        (
+                            _,
+                            ImplTraitLoweringState::Param(_) | ImplTraitLoweringState::Variable(_),
+                        ) => {
+                            // Find the generic index for the target of our `bound`
+                            let target_param_idx = self
+                                .resolver
+                                .where_predicates_in_scope()
+                                .find_map(|(p, _)| match p {
+                                    WherePredicate::TypeBound {
+                                        target: WherePredicateTypeTarget::TypeOrConstParam(idx),
+                                        bound: b,
+                                    } if b == bound => Some(idx),
+                                    _ => None,
+                                });
+                            let ty = if let Some(target_param_idx) = target_param_idx {
+                                let mut counter = 0;
+                                let generics = self.generics().expect("generics in scope");
+                                for (idx, data) in generics.params.type_or_consts.iter() {
+                                    // Count the number of `impl Trait` things that appear before
+                                    // the target of our `bound`.
+                                    // Our counter within `impl_trait_mode` should be that number
+                                    // to properly lower each types within `type_ref`
+                                    if data.type_param().is_some_and(|p| {
+                                        p.provenance == TypeParamProvenance::ArgumentImplTrait
+                                    }) {
+                                        counter += 1;
                                     }
-                                    let mut ext = TyLoweringContext::new_maybe_unowned(
-                                        self.db,
-                                        self.resolver,
-                                        self.owner,
-                                    )
-                                    .with_type_param_mode(self.type_param_mode);
-                                    match &self.impl_trait_mode {
-                                        ImplTraitLoweringState::Param(_) => {
-                                            ext.impl_trait_mode =
-                                                ImplTraitLoweringState::Param(Cell::new(counter));
-                                        }
-                                        ImplTraitLoweringState::Variable(_) => {
-                                            ext.impl_trait_mode = ImplTraitLoweringState::Variable(
-                                                Cell::new(counter),
-                                            );
-                                        }
-                                        _ => unreachable!(),
+                                    if idx == *target_param_idx {
+                                        break;
                                     }
-                                    break 'ty ext.lower_ty(type_ref);
                                 }
-                            }
-                            self.lower_ty(type_ref)
-                        };
-                        let alias_eq =
-                            AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
-                        predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
+                                let mut ext = TyLoweringContext::new_maybe_unowned(
+                                    self.db,
+                                    self.resolver,
+                                    self.owner,
+                                )
+                                .with_type_param_mode(self.type_param_mode);
+                                match &self.impl_trait_mode {
+                                    ImplTraitLoweringState::Param(_) => {
+                                        ext.impl_trait_mode =
+                                            ImplTraitLoweringState::Param(Cell::new(counter));
+                                    }
+                                    ImplTraitLoweringState::Variable(_) => {
+                                        ext.impl_trait_mode =
+                                            ImplTraitLoweringState::Variable(Cell::new(counter));
+                                    }
+                                    _ => unreachable!(),
+                                }
+                                ext.lower_ty(type_ref)
+                            } else {
+                                self.lower_ty(type_ref)
+                            };
+
+                            let alias_eq =
+                                AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
+                            predicates
+                                .push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
+                        }
                     }
                 }
                 for bound in binding.bounds.iter() {
@@ -1394,16 +1379,6 @@ impl<'a> TyLoweringContext<'a> {
     }
 }
 
-fn count_impl_traits(type_ref: &TypeRef) -> usize {
-    let mut count = 0;
-    type_ref.walk(&mut |type_ref| {
-        if matches!(type_ref, TypeRef::ImplTrait(_)) {
-            count += 1;
-        }
-    });
-    count
-}
-
 /// Build the signature of a callable item (function, struct or enum variant).
 pub(crate) fn callable_item_sig(db: &dyn HirDatabase, def: CallableDefId) -> PolyFnSig {
     match def {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
index 69c7a815488..f80d5394985 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
@@ -1975,3 +1975,24 @@ impl<#[cfg(feature = "a-feature")] A> Bar for (){}
 "#,
     )
 }
+
+#[test]
+fn nested_anon_generics_and_where_bounds_17173() {
+    check_types(
+        r#"
+//- minicore: sized
+pub trait Lookup {
+    type Data;
+    fn lookup(&self) -> Self::Data;
+}
+pub trait ItemTreeLoc {
+    type Id;
+}
+fn id_to_generics(id: impl Lookup<Data = impl ItemTreeLoc<Id = ()>>)
+                //^^ impl Lookup<Data = impl ItemTreeLoc<Id = ()>>
+where
+    (): Sized,
+{}
+"#,
+    );
+}