Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #17160 - dfireBird:fix_impl_trait, r=Veykril
Implement creating generics for impl traits in associated types Hopefully fix #17017
bors 2024-04-30
parent 84ef3cf · parent da0fb75 · commit 1bf1f6e
-rw-r--r--crates/hir-def/src/generics.rs18
-rw-r--r--crates/hir-def/src/lower.rs30
-rw-r--r--crates/hir-def/src/path/lower.rs7
-rw-r--r--crates/hir-def/src/resolver.rs8
-rw-r--r--crates/hir-ty/src/lower.rs18
-rw-r--r--crates/hir-ty/src/tests/traits.rs38
6 files changed, 102 insertions, 17 deletions
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index 7a701a48bf..3a277ecb90 100644
--- a/crates/hir-def/src/generics.rs
+++ b/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/crates/hir-def/src/lower.rs b/crates/hir-def/src/lower.rs
index d574d80a8e..ecd8d79f20 100644
--- a/crates/hir-def/src/lower.rs
+++ b/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/crates/hir-def/src/path/lower.rs b/crates/hir-def/src/path/lower.rs
index b3c41a073c..6af5261411 100644
--- a/crates/hir-def/src/path/lower.rs
+++ b/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/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index fadab858aa..1602b17385 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/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/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 7423c9ed32..706b034821 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/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/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index 4bc3e121ac..7a318877b7 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/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();
+}
+"#,
+ );
+}