about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-04-30 12:23:23 +0000
committerbors <bors@rust-lang.org>2024-04-30 12:23:23 +0000
commitb5a0f7e9eaa570b7a1f1e63f3215903192d5bf19 (patch)
tree16161074692e1e236ec2a4b75a852977ecd2615e
parent4ce1c6cb97f31f8b527a11e5b0d206319c599490 (diff)
parentb1ed49208eab2e7fb159294c842b1f8c5f714e95 (diff)
downloadrust-b5a0f7e9eaa570b7a1f1e63f3215903192d5bf19.tar.gz
rust-b5a0f7e9eaa570b7a1f1e63f3215903192d5bf19.zip
Auto merge of #17160 - dfireBird:fix_impl_trait, r=Veykril
Implement creating generics for impl traits in associated types

Hopefully fix #17017
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/generics.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lower.rs30
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/resolver.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs38
6 files changed, 102 insertions, 17 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 7a701a48bf7..3a277ecb90b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
@@ -339,6 +339,7 @@ impl GenericParamsCollector {
         target: Either<TypeRef, LifetimeRef>,
     ) {
         let bound = TypeBound::from_ast(lower_ctx, bound);
+        self.fill_impl_trait_bounds(lower_ctx.take_impl_traits_bounds());
         let predicate = match (target, bound) {
             (Either::Left(type_ref), bound) => match hrtb_lifetimes {
                 Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
@@ -359,6 +360,23 @@ impl GenericParamsCollector {
         self.where_predicates.push(predicate);
     }
 
+    fn fill_impl_trait_bounds(&mut self, impl_bounds: Vec<Vec<Interned<TypeBound>>>) {
+        for bounds in impl_bounds {
+            let param = TypeParamData {
+                name: None,
+                default: None,
+                provenance: TypeParamProvenance::ArgumentImplTrait,
+            };
+            let param_id = self.type_or_consts.alloc(param.into());
+            for bound in bounds {
+                self.where_predicates.push(WherePredicate::TypeBound {
+                    target: WherePredicateTypeTarget::TypeOrConstParam(param_id),
+                    bound,
+                });
+            }
+        }
+    }
+
     pub(crate) fn fill_implicit_impl_trait_args(
         &mut self,
         db: &dyn DefDatabase,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
index d574d80a8e0..ecd8d79f20b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
@@ -1,26 +1,34 @@
 //! Context for lowering paths.
-use std::cell::OnceCell;
+use std::cell::{OnceCell, RefCell};
 
 use hir_expand::{
     span_map::{SpanMap, SpanMapRef},
     AstId, HirFileId, InFile,
 };
+use intern::Interned;
 use span::{AstIdMap, AstIdNode};
 use syntax::ast;
 use triomphe::Arc;
 
-use crate::{db::DefDatabase, path::Path};
+use crate::{db::DefDatabase, path::Path, type_ref::TypeBound};
 
 pub struct LowerCtx<'a> {
     pub db: &'a dyn DefDatabase,
     file_id: HirFileId,
     span_map: OnceCell<SpanMap>,
     ast_id_map: OnceCell<Arc<AstIdMap>>,
+    impl_trait_bounds: RefCell<Vec<Vec<Interned<TypeBound>>>>,
 }
 
 impl<'a> LowerCtx<'a> {
     pub fn new(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
-        LowerCtx { db, file_id, span_map: OnceCell::new(), ast_id_map: OnceCell::new() }
+        LowerCtx {
+            db,
+            file_id,
+            span_map: OnceCell::new(),
+            ast_id_map: OnceCell::new(),
+            impl_trait_bounds: RefCell::new(Vec::new()),
+        }
     }
 
     pub fn with_span_map_cell(
@@ -28,7 +36,13 @@ impl<'a> LowerCtx<'a> {
         file_id: HirFileId,
         span_map: OnceCell<SpanMap>,
     ) -> Self {
-        LowerCtx { db, file_id, span_map, ast_id_map: OnceCell::new() }
+        LowerCtx {
+            db,
+            file_id,
+            span_map,
+            ast_id_map: OnceCell::new(),
+            impl_trait_bounds: RefCell::new(Vec::new()),
+        }
     }
 
     pub(crate) fn span_map(&self) -> SpanMapRef<'_> {
@@ -45,4 +59,12 @@ impl<'a> LowerCtx<'a> {
             self.ast_id_map.get_or_init(|| self.db.ast_id_map(self.file_id)).ast_id(item),
         )
     }
+
+    pub fn update_impl_traits_bounds(&self, bounds: Vec<Interned<TypeBound>>) {
+        self.impl_trait_bounds.borrow_mut().push(bounds);
+    }
+
+    pub fn take_impl_traits_bounds(&self) -> Vec<Vec<Interned<TypeBound>>> {
+        self.impl_trait_bounds.take()
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
index b3c41a073c6..6af52614111 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
@@ -208,6 +208,13 @@ pub(super) fn lower_generic_args(
                         .and_then(|args| lower_generic_args(lower_ctx, args))
                         .map(Interned::new);
                     let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it));
+                    let type_ref = type_ref.inspect(|tr| {
+                        tr.walk(&mut |tr| {
+                            if let TypeRef::ImplTrait(bounds) = tr {
+                                lower_ctx.update_impl_traits_bounds(bounds.clone());
+                            }
+                        });
+                    });
                     let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
                         l.bounds()
                             .map(|it| Interned::new(TypeBound::from_ast(lower_ctx, it)))
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
index fadab858aa1..1602b173858 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -1,5 +1,5 @@
 //! Name resolution façade.
-use std::{fmt, hash::BuildHasherDefault, mem};
+use std::{fmt, hash::BuildHasherDefault, iter, mem};
 
 use base_db::CrateId;
 use hir_expand::{
@@ -591,13 +591,13 @@ impl Resolver {
 
     pub fn where_predicates_in_scope(
         &self,
-    ) -> impl Iterator<Item = &crate::generics::WherePredicate> {
+    ) -> impl Iterator<Item = (&crate::generics::WherePredicate, &GenericDefId)> {
         self.scopes()
             .filter_map(|scope| match scope {
-                Scope::GenericParams { params, .. } => Some(params),
+                Scope::GenericParams { params, def } => Some((params, def)),
                 _ => None,
             })
-            .flat_map(|params| params.where_predicates.iter())
+            .flat_map(|(params, def)| params.where_predicates.iter().zip(iter::repeat(def)))
     }
 
     pub fn generic_def(&self) -> Option<GenericDefId> {
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 7423c9ed327..706b034821e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -1010,6 +1010,7 @@ impl<'a> TyLoweringContext<'a> {
     pub(crate) fn lower_where_predicate<'b>(
         &'b self,
         where_predicate: &'b WherePredicate,
+        &def: &GenericDefId,
         ignore_bindings: bool,
     ) -> impl Iterator<Item = QuantifiedWhereClause> + 'b {
         match where_predicate {
@@ -1018,7 +1019,6 @@ impl<'a> TyLoweringContext<'a> {
                 let self_ty = match target {
                     WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(type_ref),
                     &WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
-                        let def = self.resolver.generic_def().expect("generics in scope");
                         let param_id = hir_def::TypeOrConstParamId { parent: def, local_id };
                         match self.type_param_mode {
                             ParamLoweringMode::Placeholder => {
@@ -1178,7 +1178,7 @@ impl<'a> TyLoweringContext<'a> {
                                 let target_param_idx = self
                                     .resolver
                                     .where_predicates_in_scope()
-                                    .find_map(|p| match p {
+                                    .find_map(|(p, _)| match p {
                                         WherePredicate::TypeBound {
                                             target: WherePredicateTypeTarget::TypeOrConstParam(idx),
                                             bound: b,
@@ -1559,7 +1559,7 @@ pub(crate) fn generic_predicates_for_param_query(
     let generics = generics(db.upcast(), def);
 
     // we have to filter out all other predicates *first*, before attempting to lower them
-    let predicate = |pred: &&_| match pred {
+    let predicate = |(pred, &def): &(&_, _)| match pred {
         WherePredicate::ForLifetime { target, bound, .. }
         | WherePredicate::TypeBound { target, bound, .. } => {
             let invalid_target = match target {
@@ -1601,8 +1601,8 @@ pub(crate) fn generic_predicates_for_param_query(
     let mut predicates: Vec<_> = resolver
         .where_predicates_in_scope()
         .filter(predicate)
-        .flat_map(|pred| {
-            ctx.lower_where_predicate(pred, true).map(|p| make_binders(db, &generics, p))
+        .flat_map(|(pred, def)| {
+            ctx.lower_where_predicate(pred, def, true).map(|p| make_binders(db, &generics, p))
         })
         .collect();
 
@@ -1655,8 +1655,8 @@ pub(crate) fn trait_environment_query(
     };
     let mut traits_in_scope = Vec::new();
     let mut clauses = Vec::new();
-    for pred in resolver.where_predicates_in_scope() {
-        for pred in ctx.lower_where_predicate(pred, false) {
+    for (pred, def) in resolver.where_predicates_in_scope() {
+        for pred in ctx.lower_where_predicate(pred, def, false) {
             if let WhereClause::Implemented(tr) = &pred.skip_binders() {
                 traits_in_scope.push((tr.self_type_parameter(Interner).clone(), tr.hir_trait_id()));
             }
@@ -1710,8 +1710,8 @@ pub(crate) fn generic_predicates_query(
 
     let mut predicates = resolver
         .where_predicates_in_scope()
-        .flat_map(|pred| {
-            ctx.lower_where_predicate(pred, false).map(|p| make_binders(db, &generics, p))
+        .flat_map(|(pred, def)| {
+            ctx.lower_where_predicate(pred, def, false).map(|p| make_binders(db, &generics, p))
         })
         .collect::<Vec<_>>();
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
index 4bc3e121ac1..7a318877b72 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
@@ -4765,3 +4765,41 @@ fn test() {
         "#,
     );
 }
+
+#[test]
+fn associated_type_with_impl_trait_in_tuple() {
+    check_no_mismatches(
+        r#"
+pub trait Iterator {
+    type Item;
+}
+
+pub trait Value {}
+
+fn bar<I: Iterator<Item = (usize, impl Value)>>() {}
+
+fn foo() {
+    bar();
+}
+"#,
+    );
+}
+
+#[test]
+fn associated_type_with_impl_trait_in_nested_tuple() {
+    check_no_mismatches(
+        r#"
+pub trait Iterator {
+    type Item;
+}
+
+pub trait Value {}
+
+fn bar<I: Iterator<Item = ((impl Value, usize), u32)>>() {}
+
+fn foo() {
+    bar();
+}
+"#,
+    );
+}