Skip to content

Commit b5a0f7e

Browse files
committed
Auto merge of #17160 - dfireBird:fix_impl_trait, r=Veykril
Implement creating generics for impl traits in associated types Hopefully fix #17017
2 parents 4ce1c6c + b1ed492 commit b5a0f7e

File tree

6 files changed

+102
-17
lines changed

6 files changed

+102
-17
lines changed

src/tools/rust-analyzer/crates/hir-def/src/generics.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ impl GenericParamsCollector {
339339
target: Either<TypeRef, LifetimeRef>,
340340
) {
341341
let bound = TypeBound::from_ast(lower_ctx, bound);
342+
self.fill_impl_trait_bounds(lower_ctx.take_impl_traits_bounds());
342343
let predicate = match (target, bound) {
343344
(Either::Left(type_ref), bound) => match hrtb_lifetimes {
344345
Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
@@ -359,6 +360,23 @@ impl GenericParamsCollector {
359360
self.where_predicates.push(predicate);
360361
}
361362

363+
fn fill_impl_trait_bounds(&mut self, impl_bounds: Vec<Vec<Interned<TypeBound>>>) {
364+
for bounds in impl_bounds {
365+
let param = TypeParamData {
366+
name: None,
367+
default: None,
368+
provenance: TypeParamProvenance::ArgumentImplTrait,
369+
};
370+
let param_id = self.type_or_consts.alloc(param.into());
371+
for bound in bounds {
372+
self.where_predicates.push(WherePredicate::TypeBound {
373+
target: WherePredicateTypeTarget::TypeOrConstParam(param_id),
374+
bound,
375+
});
376+
}
377+
}
378+
}
379+
362380
pub(crate) fn fill_implicit_impl_trait_args(
363381
&mut self,
364382
db: &dyn DefDatabase,

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

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,48 @@
11
//! Context for lowering paths.
2-
use std::cell::OnceCell;
2+
use std::cell::{OnceCell, RefCell};
33

44
use hir_expand::{
55
span_map::{SpanMap, SpanMapRef},
66
AstId, HirFileId, InFile,
77
};
8+
use intern::Interned;
89
use span::{AstIdMap, AstIdNode};
910
use syntax::ast;
1011
use triomphe::Arc;
1112

12-
use crate::{db::DefDatabase, path::Path};
13+
use crate::{db::DefDatabase, path::Path, type_ref::TypeBound};
1314

1415
pub struct LowerCtx<'a> {
1516
pub db: &'a dyn DefDatabase,
1617
file_id: HirFileId,
1718
span_map: OnceCell<SpanMap>,
1819
ast_id_map: OnceCell<Arc<AstIdMap>>,
20+
impl_trait_bounds: RefCell<Vec<Vec<Interned<TypeBound>>>>,
1921
}
2022

2123
impl<'a> LowerCtx<'a> {
2224
pub fn new(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
23-
LowerCtx { db, file_id, span_map: OnceCell::new(), ast_id_map: OnceCell::new() }
25+
LowerCtx {
26+
db,
27+
file_id,
28+
span_map: OnceCell::new(),
29+
ast_id_map: OnceCell::new(),
30+
impl_trait_bounds: RefCell::new(Vec::new()),
31+
}
2432
}
2533

2634
pub fn with_span_map_cell(
2735
db: &'a dyn DefDatabase,
2836
file_id: HirFileId,
2937
span_map: OnceCell<SpanMap>,
3038
) -> Self {
31-
LowerCtx { db, file_id, span_map, ast_id_map: OnceCell::new() }
39+
LowerCtx {
40+
db,
41+
file_id,
42+
span_map,
43+
ast_id_map: OnceCell::new(),
44+
impl_trait_bounds: RefCell::new(Vec::new()),
45+
}
3246
}
3347

3448
pub(crate) fn span_map(&self) -> SpanMapRef<'_> {
@@ -45,4 +59,12 @@ impl<'a> LowerCtx<'a> {
4559
self.ast_id_map.get_or_init(|| self.db.ast_id_map(self.file_id)).ast_id(item),
4660
)
4761
}
62+
63+
pub fn update_impl_traits_bounds(&self, bounds: Vec<Interned<TypeBound>>) {
64+
self.impl_trait_bounds.borrow_mut().push(bounds);
65+
}
66+
67+
pub fn take_impl_traits_bounds(&self) -> Vec<Vec<Interned<TypeBound>>> {
68+
self.impl_trait_bounds.take()
69+
}
4870
}

src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,13 @@ pub(super) fn lower_generic_args(
208208
.and_then(|args| lower_generic_args(lower_ctx, args))
209209
.map(Interned::new);
210210
let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it));
211+
let type_ref = type_ref.inspect(|tr| {
212+
tr.walk(&mut |tr| {
213+
if let TypeRef::ImplTrait(bounds) = tr {
214+
lower_ctx.update_impl_traits_bounds(bounds.clone());
215+
}
216+
});
217+
});
211218
let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
212219
l.bounds()
213220
.map(|it| Interned::new(TypeBound::from_ast(lower_ctx, it)))

src/tools/rust-analyzer/crates/hir-def/src/resolver.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Name resolution façade.
2-
use std::{fmt, hash::BuildHasherDefault, mem};
2+
use std::{fmt, hash::BuildHasherDefault, iter, mem};
33

44
use base_db::CrateId;
55
use hir_expand::{
@@ -591,13 +591,13 @@ impl Resolver {
591591

592592
pub fn where_predicates_in_scope(
593593
&self,
594-
) -> impl Iterator<Item = &crate::generics::WherePredicate> {
594+
) -> impl Iterator<Item = (&crate::generics::WherePredicate, &GenericDefId)> {
595595
self.scopes()
596596
.filter_map(|scope| match scope {
597-
Scope::GenericParams { params, .. } => Some(params),
597+
Scope::GenericParams { params, def } => Some((params, def)),
598598
_ => None,
599599
})
600-
.flat_map(|params| params.where_predicates.iter())
600+
.flat_map(|(params, def)| params.where_predicates.iter().zip(iter::repeat(def)))
601601
}
602602

603603
pub fn generic_def(&self) -> Option<GenericDefId> {

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,7 @@ impl<'a> TyLoweringContext<'a> {
10101010
pub(crate) fn lower_where_predicate<'b>(
10111011
&'b self,
10121012
where_predicate: &'b WherePredicate,
1013+
&def: &GenericDefId,
10131014
ignore_bindings: bool,
10141015
) -> impl Iterator<Item = QuantifiedWhereClause> + 'b {
10151016
match where_predicate {
@@ -1018,7 +1019,6 @@ impl<'a> TyLoweringContext<'a> {
10181019
let self_ty = match target {
10191020
WherePredicateTypeTarget::TypeRef(type_ref) => self.lower_ty(type_ref),
10201021
&WherePredicateTypeTarget::TypeOrConstParam(local_id) => {
1021-
let def = self.resolver.generic_def().expect("generics in scope");
10221022
let param_id = hir_def::TypeOrConstParamId { parent: def, local_id };
10231023
match self.type_param_mode {
10241024
ParamLoweringMode::Placeholder => {
@@ -1178,7 +1178,7 @@ impl<'a> TyLoweringContext<'a> {
11781178
let target_param_idx = self
11791179
.resolver
11801180
.where_predicates_in_scope()
1181-
.find_map(|p| match p {
1181+
.find_map(|(p, _)| match p {
11821182
WherePredicate::TypeBound {
11831183
target: WherePredicateTypeTarget::TypeOrConstParam(idx),
11841184
bound: b,
@@ -1559,7 +1559,7 @@ pub(crate) fn generic_predicates_for_param_query(
15591559
let generics = generics(db.upcast(), def);
15601560

15611561
// we have to filter out all other predicates *first*, before attempting to lower them
1562-
let predicate = |pred: &&_| match pred {
1562+
let predicate = |(pred, &def): &(&_, _)| match pred {
15631563
WherePredicate::ForLifetime { target, bound, .. }
15641564
| WherePredicate::TypeBound { target, bound, .. } => {
15651565
let invalid_target = match target {
@@ -1601,8 +1601,8 @@ pub(crate) fn generic_predicates_for_param_query(
16011601
let mut predicates: Vec<_> = resolver
16021602
.where_predicates_in_scope()
16031603
.filter(predicate)
1604-
.flat_map(|pred| {
1605-
ctx.lower_where_predicate(pred, true).map(|p| make_binders(db, &generics, p))
1604+
.flat_map(|(pred, def)| {
1605+
ctx.lower_where_predicate(pred, def, true).map(|p| make_binders(db, &generics, p))
16061606
})
16071607
.collect();
16081608

@@ -1655,8 +1655,8 @@ pub(crate) fn trait_environment_query(
16551655
};
16561656
let mut traits_in_scope = Vec::new();
16571657
let mut clauses = Vec::new();
1658-
for pred in resolver.where_predicates_in_scope() {
1659-
for pred in ctx.lower_where_predicate(pred, false) {
1658+
for (pred, def) in resolver.where_predicates_in_scope() {
1659+
for pred in ctx.lower_where_predicate(pred, def, false) {
16601660
if let WhereClause::Implemented(tr) = &pred.skip_binders() {
16611661
traits_in_scope.push((tr.self_type_parameter(Interner).clone(), tr.hir_trait_id()));
16621662
}
@@ -1710,8 +1710,8 @@ pub(crate) fn generic_predicates_query(
17101710

17111711
let mut predicates = resolver
17121712
.where_predicates_in_scope()
1713-
.flat_map(|pred| {
1714-
ctx.lower_where_predicate(pred, false).map(|p| make_binders(db, &generics, p))
1713+
.flat_map(|(pred, def)| {
1714+
ctx.lower_where_predicate(pred, def, false).map(|p| make_binders(db, &generics, p))
17151715
})
17161716
.collect::<Vec<_>>();
17171717

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4765,3 +4765,41 @@ fn test() {
47654765
"#,
47664766
);
47674767
}
4768+
4769+
#[test]
4770+
fn associated_type_with_impl_trait_in_tuple() {
4771+
check_no_mismatches(
4772+
r#"
4773+
pub trait Iterator {
4774+
type Item;
4775+
}
4776+
4777+
pub trait Value {}
4778+
4779+
fn bar<I: Iterator<Item = (usize, impl Value)>>() {}
4780+
4781+
fn foo() {
4782+
bar();
4783+
}
4784+
"#,
4785+
);
4786+
}
4787+
4788+
#[test]
4789+
fn associated_type_with_impl_trait_in_nested_tuple() {
4790+
check_no_mismatches(
4791+
r#"
4792+
pub trait Iterator {
4793+
type Item;
4794+
}
4795+
4796+
pub trait Value {}
4797+
4798+
fn bar<I: Iterator<Item = ((impl Value, usize), u32)>>() {}
4799+
4800+
fn foo() {
4801+
bar();
4802+
}
4803+
"#,
4804+
);
4805+
}

0 commit comments

Comments
 (0)