Skip to content

Commit 76d3584

Browse files
committed
Factor out shared code for probing inherent assoc items
1 parent 38e69c6 commit 76d3584

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
@@ -493,7 +493,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
493493
err.emit()
494494
}
495495

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

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

571572
let tcx = self.tcx();
572573

574+
let kind_str = assoc_kind_str(kind);
573575
let adt_did = self_ty.ty_adt_def().map(|def| def.did());
574576
let add_def_label = |err: &mut Diag<'_>| {
575577
if let Some(did) = adt_did {
576578
err.span_label(
577579
tcx.def_span(did),
578-
format!("associated item `{name}` not found for this {}", tcx.def_descr(did)),
580+
format!(
581+
"associated {kind_str} `{name}` not found for this {}",
582+
tcx.def_descr(did)
583+
),
579584
);
580585
}
581586
};
@@ -602,11 +607,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
602607
self.dcx(),
603608
name.span,
604609
E0220,
605-
"associated type `{name}` not found for `{self_ty}` in the current scope"
610+
"associated {kind_str} `{name}` not found for `{self_ty}` in the current scope"
606611
);
607612
err.span_label(name.span, format!("associated item not found in `{self_ty}`"));
608613
err.note(format!(
609-
"the associated type was found for\n{type_candidates}{additional_types}",
614+
"the associated {kind_str} was found for\n{type_candidates}{additional_types}",
610615
));
611616
add_def_label(&mut err);
612617
return err.emit();
@@ -687,7 +692,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
687692

688693
let mut err = self.dcx().struct_span_err(
689694
name.span,
690-
format!("the associated type `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
695+
format!("the associated {kind_str} `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
691696
);
692697
if !bounds.is_empty() {
693698
err.note(format!(
@@ -697,7 +702,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
697702
}
698703
err.span_label(
699704
name.span,
700-
format!("associated type cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
705+
format!("associated {kind_str} cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
701706
);
702707

703708
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
@@ -1149,7 +1149,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11491149

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

13551354
fn probe_inherent_assoc_ty(
13561355
&self,
1357-
name: Ident,
13581356
segment: &hir::PathSegment<'tcx>,
13591357
adt_did: DefId,
13601358
self_ty: Ty<'tcx>,
@@ -1373,6 +1371,60 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13731371
return Ok(None);
13741372
}
13751373

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

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

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

14941544
match &applicable_candidates[..] {
1495-
&[] => Err(self.complain_about_inherent_assoc_ty_not_found(
1545+
&[] => Err(self.complain_about_inherent_assoc_not_found(
14961546
name,
14971547
self_ty,
14981548
candidates,
14991549
fulfillment_errors,
15001550
span,
1551+
kind,
15011552
)),
15021553

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

1505-
&[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc_ty(
1556+
&[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc(
15061557
name,
15071558
applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
15081559
span,
@@ -2196,6 +2247,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21962247
debug!(?qself, ?segment);
21972248
let ty = self.lower_ty(qself);
21982249
self.lower_const_assoc_path(hir_id, const_arg.span(), ty, qself, segment)
2250+
.unwrap_or_else(|guar| Const::new_error(tcx, guar))
21992251
}
22002252
hir::ConstArgKind::Path(qpath @ hir::QPath::LangItem(..)) => {
22012253
ty::Const::new_error_with_message(
@@ -2317,7 +2369,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23172369
qself_ty: Ty<'tcx>,
23182370
qself: &'tcx hir::Ty<'tcx>,
23192371
assoc_segment: &'tcx hir::PathSegment<'tcx>,
2320-
) -> Const<'tcx> {
2372+
) -> Result<Const<'tcx>, ErrorGuaranteed> {
23212373
debug!(%qself_ty, ?assoc_segment.ident);
23222374
let tcx = self.tcx();
23232375

@@ -2338,42 +2390,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23382390
GenericsArgsErrExtend::EnumVariant { qself, assoc_segment, adt_def },
23392391
);
23402392
let uv = ty::UnevaluatedConst::new(variant_def.def_id, ty::List::empty());
2341-
return Const::new_unevaluated(tcx, uv);
2393+
return Ok(Const::new_unevaluated(tcx, uv));
23422394
}
23432395
}
23442396

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

@@ -2422,21 +2451,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24222451
};
24232452
let bound = match bound_result {
24242453
Ok(b) => b,
2425-
Err(reported) => return Const::new_error(tcx, reported),
2454+
Err(reported) => return Err(reported),
24262455
};
24272456

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

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)