Skip to content

Commit cf5e01e

Browse files
committed
Factor out shared code for probing inherent assoc items
1 parent 8f9b82a commit cf5e01e

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
@@ -1169,7 +1169,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11691169

11701170
// FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
11711171
if let Some((ty, did)) = self.probe_inherent_assoc_ty(
1172-
assoc_ident,
11731172
assoc_segment,
11741173
adt_def.did(),
11751174
qself_ty,
@@ -1371,7 +1370,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13711370

13721371
fn probe_inherent_assoc_ty(
13731372
&self,
1374-
name: Ident,
13751373
segment: &hir::PathSegment<'tcx>,
13761374
adt_did: DefId,
13771375
self_ty: Ty<'tcx>,
@@ -1390,6 +1388,60 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13901388
return Ok(None);
13911389
}
13921390

1391+
let Some((def_id, args)) = self.probe_inherent_assoc_shared(
1392+
segment,
1393+
adt_did,
1394+
self_ty,
1395+
block,
1396+
span,
1397+
ty::AssocKind::Type,
1398+
)?
1399+
else {
1400+
return Ok(None);
1401+
};
1402+
1403+
let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new_from_args(tcx, def_id, args));
1404+
Ok(Some((ty, def_id)))
1405+
}
1406+
1407+
fn probe_inherent_assoc_const(
1408+
&self,
1409+
segment: &hir::PathSegment<'tcx>,
1410+
adt_did: DefId,
1411+
self_ty: Ty<'tcx>,
1412+
block: HirId,
1413+
span: Span,
1414+
) -> Result<Option<(Const<'tcx>, DefId)>, ErrorGuaranteed> {
1415+
let tcx = self.tcx();
1416+
1417+
let Some((def_id, args)) = self.probe_inherent_assoc_shared(
1418+
segment,
1419+
adt_did,
1420+
self_ty,
1421+
block,
1422+
span,
1423+
ty::AssocKind::Const,
1424+
)?
1425+
else {
1426+
return Ok(None);
1427+
};
1428+
1429+
let ct = Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(def_id, args));
1430+
Ok(Some((ct, def_id)))
1431+
}
1432+
1433+
fn probe_inherent_assoc_shared(
1434+
&self,
1435+
segment: &hir::PathSegment<'tcx>,
1436+
adt_did: DefId,
1437+
self_ty: Ty<'tcx>,
1438+
block: HirId,
1439+
span: Span,
1440+
kind: ty::AssocKind,
1441+
) -> Result<Option<(DefId, GenericArgsRef<'tcx>)>, ErrorGuaranteed> {
1442+
let tcx = self.tcx();
1443+
1444+
let name = segment.ident;
13931445
let candidates: Vec<_> = tcx
13941446
.inherent_impls(adt_did)
13951447
.iter()
@@ -1433,8 +1485,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
14331485
&mut universes,
14341486
self_ty,
14351487
|self_ty| {
1436-
self.select_inherent_assoc_type_candidates(
1437-
infcx, name, span, self_ty, param_env, candidates,
1488+
self.select_inherent_assoc_candidates(
1489+
infcx, name, span, self_ty, param_env, candidates, kind,
14381490
)
14391491
},
14401492
)?;
@@ -1451,20 +1503,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
14511503
.chain(args.into_iter().skip(parent_args.len())),
14521504
);
14531505

1454-
let ty =
1455-
Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new_from_args(tcx, assoc_item, args));
1456-
1457-
Ok(Some((ty, assoc_item)))
1506+
Ok(Some((assoc_item, args)))
14581507
}
14591508

1460-
fn select_inherent_assoc_type_candidates(
1509+
fn select_inherent_assoc_candidates(
14611510
&self,
14621511
infcx: &InferCtxt<'tcx>,
14631512
name: Ident,
14641513
span: Span,
14651514
self_ty: Ty<'tcx>,
14661515
param_env: ParamEnv<'tcx>,
14671516
candidates: Vec<(DefId, (DefId, DefId))>,
1517+
kind: ty::AssocKind,
14681518
) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> {
14691519
let tcx = self.tcx();
14701520
let mut fulfillment_errors = Vec::new();
@@ -1509,17 +1559,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
15091559
.collect();
15101560

15111561
match &applicable_candidates[..] {
1512-
&[] => Err(self.complain_about_inherent_assoc_ty_not_found(
1562+
&[] => Err(self.complain_about_inherent_assoc_not_found(
15131563
name,
15141564
self_ty,
15151565
candidates,
15161566
fulfillment_errors,
15171567
span,
1568+
kind,
15181569
)),
15191570

15201571
&[applicable_candidate] => Ok(applicable_candidate),
15211572

1522-
&[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc_ty(
1573+
&[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc(
15231574
name,
15241575
applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
15251576
span,
@@ -2213,6 +2264,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22132264
debug!(?qself, ?segment);
22142265
let ty = self.lower_ty(qself);
22152266
self.lower_const_assoc_path(hir_id, const_arg.span(), ty, qself, segment)
2267+
.unwrap_or_else(|guar| Const::new_error(tcx, guar))
22162268
}
22172269
hir::ConstArgKind::Path(qpath @ hir::QPath::LangItem(..)) => {
22182270
ty::Const::new_error_with_message(
@@ -2338,7 +2390,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23382390
qself_ty: Ty<'tcx>,
23392391
qself: &'tcx hir::Ty<'tcx>,
23402392
assoc_segment: &'tcx hir::PathSegment<'tcx>,
2341-
) -> Const<'tcx> {
2393+
) -> Result<Const<'tcx>, ErrorGuaranteed> {
23422394
debug!(%qself_ty, ?assoc_segment.ident);
23432395
let tcx = self.tcx();
23442396

@@ -2359,42 +2411,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23592411
GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def },
23602412
);
23612413
let uv = ty::UnevaluatedConst::new(variant_def.def_id, ty::List::empty());
2362-
return Const::new_unevaluated(tcx, uv);
2414+
return Ok(Const::new_unevaluated(tcx, uv));
23632415
}
23642416
}
23652417

23662418
// FIXME(mgca): Support self types other than ADTs.
2367-
let candidates = tcx
2368-
.inherent_impls(adt_def.did())
2369-
.iter()
2370-
.filter_map(|&impl_| {
2371-
self.probe_assoc_item(
2372-
assoc_ident,
2373-
ty::AssocKind::Const,
2374-
hir_ref_id,
2375-
span,
2376-
impl_,
2377-
)
2378-
.map(|assoc| (impl_, assoc))
2379-
})
2380-
.collect::<Vec<_>>();
2381-
match &candidates[..] {
2382-
[] => {}
2383-
&[(impl_, assoc)] => {
2384-
// FIXME(mgca): adapted from temporary inherent assoc ty code that may be incorrect
2385-
let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
2386-
let args = self.lower_generic_args_of_assoc_item(
2387-
span,
2388-
assoc.def_id,
2389-
assoc_segment,
2390-
parent_args,
2391-
);
2392-
let uv = ty::UnevaluatedConst::new(assoc.def_id, args);
2393-
return Const::new_unevaluated(tcx, uv);
2394-
}
2395-
[..] => {
2396-
return Const::new_error_with_message(tcx, span, "ambiguous assoc const path");
2397-
}
2419+
if let Some((ct, _)) = self.probe_inherent_assoc_const(
2420+
assoc_segment,
2421+
adt_def.did(),
2422+
qself_ty,
2423+
hir_ref_id,
2424+
span,
2425+
)? {
2426+
return Ok(ct);
23982427
}
23992428
}
24002429

@@ -2443,21 +2472,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24432472
};
24442473
let bound = match bound_result {
24452474
Ok(b) => b,
2446-
Err(reported) => return Const::new_error(tcx, reported),
2475+
Err(reported) => return Err(reported),
24472476
};
24482477

24492478
let trait_did = bound.def_id();
24502479
let assoc_const = self
24512480
.probe_assoc_item(assoc_ident, ty::AssocKind::Const, hir_ref_id, span, trait_did)
24522481
.expect("failed to find associated const");
24532482
if assoc_const.has_type_const_attr(tcx) {
2454-
self.lower_assoc_const(span, assoc_const.def_id, assoc_segment, bound)
2483+
Ok(self.lower_assoc_const(span, assoc_const.def_id, assoc_segment, bound))
24552484
} else {
24562485
let mut err = tcx
24572486
.dcx()
24582487
.struct_span_err(span, "use of trait associated const without `#[type_const]`");
24592488
err.note("the declaration in the trait must be marked with `#[type_const]`");
2460-
Const::new_error(tcx, err.emit())
2489+
Err(err.emit())
24612490
}
24622491
}
24632492

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)