Skip to content

Commit 9cfc352

Browse files
committed
Factor out shared code for probing inherent assoc items
1 parent 48e863a commit 9cfc352

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

11771177
// FIXME(inherent_associated_types, #106719): Support self types other than ADTs.
11781178
if let Some((ty, did)) = self.probe_inherent_assoc_ty(
1179-
assoc_ident,
11801179
assoc_segment,
11811180
adt_def.did(),
11821181
qself_ty,
@@ -1377,7 +1376,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13771376

13781377
fn probe_inherent_assoc_ty(
13791378
&self,
1380-
name: Ident,
13811379
segment: &hir::PathSegment<'tcx>,
13821380
adt_did: DefId,
13831381
self_ty: Ty<'tcx>,
@@ -1396,6 +1394,60 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13961394
return Ok(None);
13971395
}
13981396

1397+
let Some((def_id, args)) = self.probe_inherent_assoc_shared(
1398+
segment,
1399+
adt_did,
1400+
self_ty,
1401+
block,
1402+
span,
1403+
ty::AssocKind::Type,
1404+
)?
1405+
else {
1406+
return Ok(None);
1407+
};
1408+
1409+
let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new_from_args(tcx, def_id, args));
1410+
Ok(Some((ty, def_id)))
1411+
}
1412+
1413+
fn probe_inherent_assoc_const(
1414+
&self,
1415+
segment: &hir::PathSegment<'tcx>,
1416+
adt_did: DefId,
1417+
self_ty: Ty<'tcx>,
1418+
block: HirId,
1419+
span: Span,
1420+
) -> Result<Option<(Const<'tcx>, DefId)>, ErrorGuaranteed> {
1421+
let tcx = self.tcx();
1422+
1423+
let Some((def_id, args)) = self.probe_inherent_assoc_shared(
1424+
segment,
1425+
adt_did,
1426+
self_ty,
1427+
block,
1428+
span,
1429+
ty::AssocKind::Const,
1430+
)?
1431+
else {
1432+
return Ok(None);
1433+
};
1434+
1435+
let ct = Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(def_id, args));
1436+
Ok(Some((ct, def_id)))
1437+
}
1438+
1439+
fn probe_inherent_assoc_shared(
1440+
&self,
1441+
segment: &hir::PathSegment<'tcx>,
1442+
adt_did: DefId,
1443+
self_ty: Ty<'tcx>,
1444+
block: HirId,
1445+
span: Span,
1446+
kind: ty::AssocKind,
1447+
) -> Result<Option<(DefId, GenericArgsRef<'tcx>)>, ErrorGuaranteed> {
1448+
let tcx = self.tcx();
1449+
1450+
let name = segment.ident;
13991451
let candidates: Vec<_> = tcx
14001452
.inherent_impls(adt_did)
14011453
.iter()
@@ -1439,8 +1491,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
14391491
&mut universes,
14401492
self_ty,
14411493
|self_ty| {
1442-
self.select_inherent_assoc_type_candidates(
1443-
infcx, name, span, self_ty, param_env, candidates,
1494+
self.select_inherent_assoc_candidates(
1495+
infcx, name, span, self_ty, param_env, candidates, kind,
14441496
)
14451497
},
14461498
)?;
@@ -1457,20 +1509,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
14571509
.chain(args.into_iter().skip(parent_args.len())),
14581510
);
14591511

1460-
let ty =
1461-
Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new_from_args(tcx, assoc_item, args));
1462-
1463-
Ok(Some((ty, assoc_item)))
1512+
Ok(Some((assoc_item, args)))
14641513
}
14651514

1466-
fn select_inherent_assoc_type_candidates(
1515+
fn select_inherent_assoc_candidates(
14671516
&self,
14681517
infcx: &InferCtxt<'tcx>,
14691518
name: Ident,
14701519
span: Span,
14711520
self_ty: Ty<'tcx>,
14721521
param_env: ParamEnv<'tcx>,
14731522
candidates: Vec<(DefId, (DefId, DefId))>,
1523+
kind: ty::AssocKind,
14741524
) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> {
14751525
let tcx = self.tcx();
14761526
let mut fulfillment_errors = Vec::new();
@@ -1515,17 +1565,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
15151565
.collect();
15161566

15171567
match &applicable_candidates[..] {
1518-
&[] => Err(self.complain_about_inherent_assoc_ty_not_found(
1568+
&[] => Err(self.complain_about_inherent_assoc_not_found(
15191569
name,
15201570
self_ty,
15211571
candidates,
15221572
fulfillment_errors,
15231573
span,
1574+
kind,
15241575
)),
15251576

15261577
&[applicable_candidate] => Ok(applicable_candidate),
15271578

1528-
&[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc_ty(
1579+
&[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc(
15291580
name,
15301581
applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
15311582
span,
@@ -2254,6 +2305,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22542305
debug!(?qself, ?segment);
22552306
let ty = self.lower_ty(qself);
22562307
self.lower_const_assoc_path(hir_id, const_arg.span(), ty, qself, segment)
2308+
.unwrap_or_else(|guar| Const::new_error(tcx, guar))
22572309
}
22582310
hir::ConstArgKind::Path(qpath @ hir::QPath::LangItem(..)) => {
22592311
ty::Const::new_error_with_message(
@@ -2379,7 +2431,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23792431
qself_ty: Ty<'tcx>,
23802432
qself: &'tcx hir::Ty<'tcx>,
23812433
assoc_segment: &'tcx hir::PathSegment<'tcx>,
2382-
) -> Const<'tcx> {
2434+
) -> Result<Const<'tcx>, ErrorGuaranteed> {
23832435
debug!(%qself_ty, ?assoc_segment.ident);
23842436
let tcx = self.tcx();
23852437

@@ -2400,42 +2452,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24002452
GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def },
24012453
);
24022454
let uv = ty::UnevaluatedConst::new(variant_def.def_id, ty::List::empty());
2403-
return Const::new_unevaluated(tcx, uv);
2455+
return Ok(Const::new_unevaluated(tcx, uv));
24042456
}
24052457
}
24062458

24072459
// FIXME(mgca): Support self types other than ADTs.
2408-
let candidates = tcx
2409-
.inherent_impls(adt_def.did())
2410-
.iter()
2411-
.filter_map(|&impl_| {
2412-
self.probe_assoc_item(
2413-
assoc_ident,
2414-
ty::AssocKind::Const,
2415-
hir_ref_id,
2416-
span,
2417-
impl_,
2418-
)
2419-
.map(|assoc| (impl_, assoc))
2420-
})
2421-
.collect::<Vec<_>>();
2422-
match &candidates[..] {
2423-
[] => {}
2424-
&[(impl_, assoc)] => {
2425-
// FIXME(mgca): adapted from temporary inherent assoc ty code that may be incorrect
2426-
let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
2427-
let args = self.lower_generic_args_of_assoc_item(
2428-
span,
2429-
assoc.def_id,
2430-
assoc_segment,
2431-
parent_args,
2432-
);
2433-
let uv = ty::UnevaluatedConst::new(assoc.def_id, args);
2434-
return Const::new_unevaluated(tcx, uv);
2435-
}
2436-
[..] => {
2437-
return Const::new_error_with_message(tcx, span, "ambiguous assoc const path");
2438-
}
2460+
if let Some((ct, _)) = self.probe_inherent_assoc_const(
2461+
assoc_segment,
2462+
adt_def.did(),
2463+
qself_ty,
2464+
hir_ref_id,
2465+
span,
2466+
)? {
2467+
return Ok(ct);
24392468
}
24402469
}
24412470

@@ -2484,21 +2513,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24842513
};
24852514
let bound = match bound_result {
24862515
Ok(b) => b,
2487-
Err(reported) => return Const::new_error(tcx, reported),
2516+
Err(reported) => return Err(reported),
24882517
};
24892518

24902519
let trait_did = bound.def_id();
24912520
let assoc_const = self
24922521
.probe_assoc_item(assoc_ident, ty::AssocKind::Const, hir_ref_id, span, trait_did)
24932522
.expect("failed to find associated const");
24942523
if assoc_const.has_type_const_attr(tcx) {
2495-
self.lower_assoc_const(span, assoc_const.def_id, assoc_segment, bound)
2524+
Ok(self.lower_assoc_const(span, assoc_const.def_id, assoc_segment, bound))
24962525
} else {
24972526
let mut err = tcx
24982527
.dcx()
24992528
.struct_span_err(span, "use of trait associated const without `#[type_const]`");
25002529
err.note("the declaration in the trait must be marked with `#[type_const]`");
2501-
Const::new_error(tcx, err.emit())
2530+
Err(err.emit())
25022531
}
25032532
}
25042533

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)