Skip to content

Commit fcfe5bd

Browse files
committed
Factor out shared code for probing inherent assoc items
1 parent e984081 commit fcfe5bd

8 files changed

+97
-63
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
494494
err.emit()
495495
}
496496

497-
pub(crate) fn complain_about_ambiguous_inherent_assoc_ty(
497+
pub(crate) fn complain_about_ambiguous_inherent_assoc(
498498
&self,
499499
name: Ident,
500500
candidates: Vec<DefId>,
@@ -555,13 +555,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
555555
}
556556

557557
// FIXME(inherent_associated_types): Find similarly named associated types and suggest them.
558-
pub(crate) fn complain_about_inherent_assoc_ty_not_found(
558+
pub(crate) fn complain_about_inherent_assoc_not_found(
559559
&self,
560560
name: Ident,
561561
self_ty: Ty<'tcx>,
562562
candidates: Vec<(DefId, (DefId, DefId))>,
563563
fulfillment_errors: Vec<FulfillmentError<'tcx>>,
564564
span: Span,
565+
kind: ty::AssocKind,
565566
) -> ErrorGuaranteed {
566567
// FIXME(fmease): This was copied in parts from an old version of `rustc_hir_typeck::method::suggest`.
567568
// Either
@@ -571,12 +572,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
571572

572573
let tcx = self.tcx();
573574

575+
let kind_str = assoc_kind_str(kind);
574576
let adt_did = self_ty.ty_adt_def().map(|def| def.did());
575577
let add_def_label = |err: &mut Diag<'_>| {
576578
if let Some(did) = adt_did {
577579
err.span_label(
578580
tcx.def_span(did),
579-
format!("associated item `{name}` not found for this {}", tcx.def_descr(did)),
581+
format!(
582+
"associated {kind_str} `{name}` not found for this {}",
583+
tcx.def_descr(did)
584+
),
580585
);
581586
}
582587
};
@@ -603,11 +608,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
603608
self.dcx(),
604609
name.span,
605610
E0220,
606-
"associated type `{name}` not found for `{self_ty}` in the current scope"
611+
"associated {kind_str} `{name}` not found for `{self_ty}` in the current scope"
607612
);
608613
err.span_label(name.span, format!("associated item not found in `{self_ty}`"));
609614
err.note(format!(
610-
"the associated type was found for\n{type_candidates}{additional_types}",
615+
"the associated {kind_str} was found for\n{type_candidates}{additional_types}",
611616
));
612617
add_def_label(&mut err);
613618
return err.emit();
@@ -688,7 +693,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
688693

689694
let mut err = self.dcx().struct_span_err(
690695
name.span,
691-
format!("the associated type `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
696+
format!("the associated {kind_str} `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
692697
);
693698
if !bounds.is_empty() {
694699
err.note(format!(
@@ -698,7 +703,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
698703
}
699704
err.span_label(
700705
name.span,
701-
format!("associated type cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
706+
format!("associated {kind_str} cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
702707
);
703708

704709
for (span, mut bounds) in bound_spans {

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 76 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11501150

11511151
// FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
11521152
if let Some((ty, did)) = self.probe_inherent_assoc_ty(
1153-
assoc_ident,
11541153
assoc_segment,
11551154
adt_def.did(),
11561155
qself_ty,
@@ -1355,7 +1354,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13551354

13561355
fn probe_inherent_assoc_ty(
13571356
&self,
1358-
name: Ident,
13591357
segment: &hir::PathSegment<'tcx>,
13601358
adt_did: DefId,
13611359
self_ty: Ty<'tcx>,
@@ -1374,6 +1372,60 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13741372
return Ok(None);
13751373
}
13761374

1375+
let Some((def_id, args)) = self.probe_inherent_assoc_shared(
1376+
segment,
1377+
adt_did,
1378+
self_ty,
1379+
block,
1380+
span,
1381+
ty::AssocKind::Type,
1382+
)?
1383+
else {
1384+
return Ok(None);
1385+
};
1386+
1387+
let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new_from_args(tcx, def_id, args));
1388+
Ok(Some((ty, def_id)))
1389+
}
1390+
1391+
fn probe_inherent_assoc_const(
1392+
&self,
1393+
segment: &hir::PathSegment<'tcx>,
1394+
adt_did: DefId,
1395+
self_ty: Ty<'tcx>,
1396+
block: HirId,
1397+
span: Span,
1398+
) -> Result<Option<(Const<'tcx>, DefId)>, ErrorGuaranteed> {
1399+
let tcx = self.tcx();
1400+
1401+
let Some((def_id, args)) = self.probe_inherent_assoc_shared(
1402+
segment,
1403+
adt_did,
1404+
self_ty,
1405+
block,
1406+
span,
1407+
ty::AssocKind::Const,
1408+
)?
1409+
else {
1410+
return Ok(None);
1411+
};
1412+
1413+
let ct = Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(def_id, args));
1414+
Ok(Some((ct, def_id)))
1415+
}
1416+
1417+
fn probe_inherent_assoc_shared(
1418+
&self,
1419+
segment: &hir::PathSegment<'tcx>,
1420+
adt_did: DefId,
1421+
self_ty: Ty<'tcx>,
1422+
block: HirId,
1423+
span: Span,
1424+
kind: ty::AssocKind,
1425+
) -> Result<Option<(DefId, GenericArgsRef<'tcx>)>, ErrorGuaranteed> {
1426+
let tcx = self.tcx();
1427+
1428+
let name = segment.ident;
13771429
let candidates: Vec<_> = tcx
13781430
.inherent_impls(adt_did)
13791431
.iter()
@@ -1417,8 +1469,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
14171469
&mut universes,
14181470
self_ty,
14191471
|self_ty| {
1420-
self.select_inherent_assoc_type_candidates(
1421-
infcx, name, span, self_ty, param_env, candidates,
1472+
self.select_inherent_assoc_candidates(
1473+
infcx, name, span, self_ty, param_env, candidates, kind,
14221474
)
14231475
},
14241476
)?;
@@ -1435,20 +1487,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
14351487
.chain(args.into_iter().skip(parent_args.len())),
14361488
);
14371489

1438-
let ty =
1439-
Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new_from_args(tcx, assoc_item, args));
1440-
1441-
Ok(Some((ty, assoc_item)))
1490+
Ok(Some((assoc_item, args)))
14421491
}
14431492

1444-
fn select_inherent_assoc_type_candidates(
1493+
fn select_inherent_assoc_candidates(
14451494
&self,
14461495
infcx: &InferCtxt<'tcx>,
14471496
name: Ident,
14481497
span: Span,
14491498
self_ty: Ty<'tcx>,
14501499
param_env: ParamEnv<'tcx>,
14511500
candidates: Vec<(DefId, (DefId, DefId))>,
1501+
kind: ty::AssocKind,
14521502
) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> {
14531503
let tcx = self.tcx();
14541504
let mut fulfillment_errors = Vec::new();
@@ -1493,17 +1543,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
14931543
.collect();
14941544

14951545
match &applicable_candidates[..] {
1496-
&[] => Err(self.complain_about_inherent_assoc_ty_not_found(
1546+
&[] => Err(self.complain_about_inherent_assoc_not_found(
14971547
name,
14981548
self_ty,
14991549
candidates,
15001550
fulfillment_errors,
15011551
span,
1552+
kind,
15021553
)),
15031554

15041555
&[applicable_candidate] => Ok(applicable_candidate),
15051556

1506-
&[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc_ty(
1557+
&[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc(
15071558
name,
15081559
applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
15091560
span,
@@ -2197,6 +2248,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21972248
debug!(?qself, ?segment);
21982249
let ty = self.lower_ty(qself);
21992250
self.lower_const_assoc_path(hir_id, const_arg.span(), ty, qself, segment)
2251+
.unwrap_or_else(|guar| Const::new_error(tcx, guar))
22002252
}
22012253
hir::ConstArgKind::Path(qpath @ hir::QPath::LangItem(..)) => {
22022254
ty::Const::new_error_with_message(
@@ -2318,7 +2370,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23182370
qself_ty: Ty<'tcx>,
23192371
qself: &'tcx hir::Ty<'tcx>,
23202372
assoc_segment: &'tcx hir::PathSegment<'tcx>,
2321-
) -> Const<'tcx> {
2373+
) -> Result<Const<'tcx>, ErrorGuaranteed> {
23222374
debug!(%qself_ty, ?assoc_segment.ident);
23232375
let tcx = self.tcx();
23242376

@@ -2339,42 +2391,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23392391
GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def },
23402392
);
23412393
let uv = ty::UnevaluatedConst::new(variant_def.def_id, ty::List::empty());
2342-
return Const::new_unevaluated(tcx, uv);
2394+
return Ok(Const::new_unevaluated(tcx, uv));
23432395
}
23442396
}
23452397

23462398
// FIXME(mgca): Support self types other than ADTs.
2347-
let candidates = tcx
2348-
.inherent_impls(adt_def.did())
2349-
.iter()
2350-
.filter_map(|&impl_| {
2351-
self.probe_assoc_item(
2352-
assoc_ident,
2353-
ty::AssocKind::Const,
2354-
hir_ref_id,
2355-
span,
2356-
impl_,
2357-
)
2358-
.map(|assoc| (impl_, assoc))
2359-
})
2360-
.collect::<Vec<_>>();
2361-
match &candidates[..] {
2362-
[] => {}
2363-
&[(impl_, assoc)] => {
2364-
// FIXME(mgca): adapted from temporary inherent assoc ty code that may be incorrect
2365-
let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
2366-
let args = self.lower_generic_args_of_assoc_item(
2367-
span,
2368-
assoc.def_id,
2369-
assoc_segment,
2370-
parent_args,
2371-
);
2372-
let uv = ty::UnevaluatedConst::new(assoc.def_id, args);
2373-
return Const::new_unevaluated(tcx, uv);
2374-
}
2375-
[..] => {
2376-
return Const::new_error_with_message(tcx, span, "ambiguous assoc const path");
2377-
}
2399+
if let Some((ct, _)) = self.probe_inherent_assoc_const(
2400+
assoc_segment,
2401+
adt_def.did(),
2402+
qself_ty,
2403+
hir_ref_id,
2404+
span,
2405+
)? {
2406+
return Ok(ct);
23782407
}
23792408
}
23802409

@@ -2423,21 +2452,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24232452
};
24242453
let bound = match bound_result {
24252454
Ok(b) => b,
2426-
Err(reported) => return Const::new_error(tcx, reported),
2455+
Err(reported) => return Err(reported),
24272456
};
24282457

24292458
let trait_did = bound.def_id();
24302459
let assoc_const = self
24312460
.probe_assoc_item(assoc_ident, ty::AssocKind::Const, hir_ref_id, span, trait_did)
24322461
.expect("failed to find associated const");
24332462
if assoc_const.has_type_const_attr(tcx) {
2434-
self.lower_assoc_const(span, assoc_const.def_id, assoc_segment, bound)
2463+
Ok(self.lower_assoc_const(span, assoc_const.def_id, assoc_segment, bound))
24352464
} else {
24362465
let mut err = tcx
24372466
.dcx()
24382467
.struct_span_err(span, "use of trait associated const without `#[type_const]`");
24392468
err.note("the declaration in the trait must be marked with `#[type_const]`");
2440-
Const::new_error(tcx, err.emit())
2469+
Err(err.emit())
24412470
}
24422471
}
24432472

tests/ui/associated-inherent-types/issue-109299-1.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0220]: associated type `Cursor` not found for `Lexer<T>` in the current s
22
--> $DIR/issue-109299-1.rs:10:40
33
|
44
LL | struct Lexer<T>(T);
5-
| --------------- associated item `Cursor` not found for this struct
5+
| --------------- associated type `Cursor` not found for this struct
66
...
77
LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
88
| ^^^^^^ associated item not found in `Lexer<T>`
@@ -14,7 +14,7 @@ error[E0220]: associated type `Cursor` not found for `Lexer<T>` in the current s
1414
--> $DIR/issue-109299-1.rs:10:40
1515
|
1616
LL | struct Lexer<T>(T);
17-
| --------------- associated item `Cursor` not found for this struct
17+
| --------------- associated type `Cursor` not found for this struct
1818
...
1919
LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
2020
| ^^^^^^ associated item not found in `Lexer<T>`

tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0220]: associated type `Pr` not found for `S<bool>` in the current scope
22
--> $DIR/not-found-self-type-differs-shadowing-trait-item.rs:28:23
33
|
44
LL | struct S<T>(T);
5-
| ----------- associated item `Pr` not found for this struct
5+
| ----------- associated type `Pr` not found for this struct
66
...
77
LL | let _: S::<bool>::Pr = ();
88
| ^^ associated item not found in `S<bool>`

tests/ui/associated-inherent-types/not-found-self-type-differs.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0220]: associated type `Proj` not found for `Family<Option<()>>` in the c
22
--> $DIR/not-found-self-type-differs.rs:15:32
33
|
44
LL | struct Family<T>(T);
5-
| ---------------- associated item `Proj` not found for this struct
5+
| ---------------- associated type `Proj` not found for this struct
66
...
77
LL | let _: Family<Option<()>>::Proj;
88
| ^^^^ associated item not found in `Family<Option<()>>`
@@ -15,7 +15,7 @@ error[E0220]: associated type `Proj` not found for `Family<PathBuf>` in the curr
1515
--> $DIR/not-found-self-type-differs.rs:16:40
1616
|
1717
LL | struct Family<T>(T);
18-
| ---------------- associated item `Proj` not found for this struct
18+
| ---------------- associated type `Proj` not found for this struct
1919
...
2020
LL | let _: Family<std::path::PathBuf>::Proj = ();
2121
| ^^^^ associated item not found in `Family<PathBuf>`

tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-0.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: the associated type `Yield` exists for `Container<[u8]>`, but its trait b
22
--> $DIR/not-found-unsatisfied-bounds-0.rs:19:29
33
|
44
LL | struct Container<T: ?Sized>(T);
5-
| --------------------------- associated item `Yield` not found for this struct
5+
| --------------------------- associated type `Yield` not found for this struct
66
...
77
LL | let _: Container<[u8]>::Yield = 1;
88
| ^^^^^ associated type cannot be referenced on `Container<[u8]>` due to unsatisfied trait bounds
@@ -14,7 +14,7 @@ error: the associated type `Combination` exists for `Duple<String, Rc<str>>`, bu
1414
--> $DIR/not-found-unsatisfied-bounds-0.rs:20:45
1515
|
1616
LL | struct Duple<T, U>(T, U);
17-
| ------------------ associated item `Combination` not found for this struct
17+
| ------------------ associated type `Combination` not found for this struct
1818
...
1919
LL | let _: Duple<String, std::rc::Rc<str>>::Combination;
2020
| ^^^^^^^^^^^ associated type cannot be referenced on `Duple<String, Rc<str>>` due to unsatisfied trait bounds

tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | let _: Container<T>::Proj = String::new();
55
| ^^^^ associated type cannot be referenced on `Container<T>` due to unsatisfied trait bounds
66
...
77
LL | struct Container<T>(T);
8-
| ------------------- associated item `Proj` not found for this struct
8+
| ------------------- associated type `Proj` not found for this struct
99
|
1010
= note: the following trait bounds were not satisfied:
1111
`T: Clone`

tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: the associated type `X` exists for `S<Featureless, Featureless>`, but its
22
--> $DIR/not-found-unsatisfied-bounds-in-multiple-impls.rs:19:43
33
|
44
LL | struct S<A, B>(A, B);
5-
| -------------- associated item `X` not found for this struct
5+
| -------------- associated type `X` not found for this struct
66
LL | struct Featureless;
77
| ------------------ doesn't satisfy `Featureless: One` or `Featureless: Two`
88
...

0 commit comments

Comments
 (0)