Skip to content

Commit 38e69c6

Browse files
committed
Properly handle ambiguous assoc const
1 parent 030354f commit 38e69c6

File tree

5 files changed

+65
-20
lines changed

5 files changed

+65
-20
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,11 +471,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
471471

472472
// Good error for `where Trait::method(..): Send`.
473473
let Some(self_ty) = opt_self_ty else {
474-
return self.error_missing_qpath_self_ty(
474+
let guar = self.error_missing_qpath_self_ty(
475475
trait_def_id,
476476
hir_ty.span,
477477
item_segment,
478+
ty::AssocKind::Type,
478479
);
480+
return Ty::new_error(tcx, guar);
479481
};
480482
let self_ty = self.lower_ty(self_ty);
481483

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -384,14 +384,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
384384
})
385385
}
386386

387-
pub(super) fn report_ambiguous_assoc_ty(
387+
pub(super) fn report_ambiguous_assoc(
388388
&self,
389389
span: Span,
390390
types: &[String],
391391
traits: &[String],
392392
name: Symbol,
393+
kind: ty::AssocKind,
393394
) -> ErrorGuaranteed {
394-
let mut err = struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated type");
395+
let kind_str = assoc_kind_str(kind);
396+
let mut err =
397+
struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated {kind_str}");
395398
if self
396399
.tcx()
397400
.resolutions(())
@@ -416,7 +419,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
416419
span,
417420
format!(
418421
"if there were a type named `Type` that implements a trait named \
419-
`Trait` with associated type `{name}`, you could use the \
422+
`Trait` with associated {kind_str} `{name}`, you could use the \
420423
fully-qualified path",
421424
),
422425
format!("<Type as Trait>::{name}"),
@@ -439,7 +442,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
439442
span,
440443
format!(
441444
"if there were a type named `Example` that implemented one of the \
442-
traits with associated type `{name}`, you could use the \
445+
traits with associated {kind_str} `{name}`, you could use the \
443446
fully-qualified path",
444447
),
445448
traits.iter().map(|trait_str| format!("<Example as {trait_str}>::{name}")),
@@ -450,7 +453,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
450453
err.span_suggestion_verbose(
451454
span,
452455
format!(
453-
"if there were a trait named `Example` with associated type `{name}` \
456+
"if there were a trait named `Example` with associated {kind_str} `{name}` \
454457
implemented for `{type_str}`, you could use the fully-qualified path",
455458
),
456459
format!("<{type_str} as Example>::{name}"),
@@ -461,7 +464,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
461464
err.span_suggestions(
462465
span,
463466
format!(
464-
"if there were a trait named `Example` with associated type `{name}` \
467+
"if there were a trait named `Example` with associated {kind_str} `{name}` \
465468
implemented for one of the types, you could use the fully-qualified \
466469
path",
467470
),

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,11 +1307,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13071307
self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);
13081308

13091309
// Don't print `ty::Error` to the user.
1310-
self.report_ambiguous_assoc_ty(
1310+
self.report_ambiguous_assoc(
13111311
span,
13121312
&[qself_ty.to_string()],
13131313
&traits,
13141314
assoc_ident.name,
1315+
ty::AssocKind::Type,
13151316
)
13161317
};
13171318
return Err(reported);
@@ -1392,13 +1393,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13921393

13931394
// In contexts that have no inference context, just make a new one.
13941395
// We do need a local variable to store it, though.
1395-
let infcx_;
13961396
let infcx = match self.infcx() {
13971397
Some(infcx) => infcx,
13981398
None => {
13991399
assert!(!self_ty.has_infer());
1400-
infcx_ = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
1401-
&infcx_
1400+
&tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis())
14021401
}
14031402
};
14041403

@@ -1649,7 +1648,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
16491648
debug!(?trait_def_id);
16501649

16511650
let Some(self_ty) = opt_self_ty else {
1652-
return self.error_missing_qpath_self_ty(trait_def_id, span, item_segment);
1651+
let guar = self.error_missing_qpath_self_ty(
1652+
trait_def_id,
1653+
span,
1654+
item_segment,
1655+
ty::AssocKind::Type,
1656+
);
1657+
return Ty::new_error(tcx, guar);
16531658
};
16541659
debug!(?self_ty);
16551660

@@ -1669,7 +1674,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
16691674
fn lower_qpath_const(
16701675
&self,
16711676
span: Span,
1672-
self_ty: Ty<'tcx>,
1677+
opt_self_ty: Option<Ty<'tcx>>,
16731678
item_def_id: DefId,
16741679
trait_segment: &hir::PathSegment<'tcx>,
16751680
item_segment: &hir::PathSegment<'tcx>,
@@ -1679,6 +1684,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
16791684
let trait_def_id = tcx.parent(item_def_id);
16801685
debug!(?trait_def_id);
16811686

1687+
let Some(self_ty) = opt_self_ty else {
1688+
let guar = self.error_missing_qpath_self_ty(
1689+
trait_def_id,
1690+
span,
1691+
item_segment,
1692+
ty::AssocKind::Const,
1693+
);
1694+
return Const::new_error(tcx, guar);
1695+
};
16821696
debug!(?self_ty);
16831697

16841698
let (item_def_id, item_args) = self.lower_qpath_shared(
@@ -1718,7 +1732,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
17181732
trait_def_id: DefId,
17191733
span: Span,
17201734
item_segment: &hir::PathSegment<'tcx>,
1721-
) -> Ty<'tcx> {
1735+
kind: ty::AssocKind,
1736+
) -> ErrorGuaranteed {
17221737
let tcx = self.tcx();
17231738
let path_str = tcx.def_path_str(trait_def_id);
17241739

@@ -1755,9 +1770,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
17551770
// FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
17561771
// references the trait. Relevant for the first case in
17571772
// `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
1758-
let reported =
1759-
self.report_ambiguous_assoc_ty(span, &type_names, &[path_str], item_segment.ident.name);
1760-
Ty::new_error(tcx, reported)
1773+
self.report_ambiguous_assoc(span, &type_names, &[path_str], item_segment.ident.name, kind)
17611774
}
17621775

17631776
pub fn prohibit_generic_args<'a>(
@@ -2232,11 +2245,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22322245
path.segments[..path.segments.len() - 2].iter(),
22332246
GenericsArgsErrExtend::None,
22342247
);
2235-
// FIXME(mgca): maybe needs proper error reported
2236-
let Some(self_ty) = opt_self_ty else { span_bug!(span, "{path:?}") };
22372248
self.lower_qpath_const(
22382249
span,
2239-
self_ty,
2250+
opt_self_ty,
22402251
did,
22412252
&path.segments[path.segments.len() - 2],
22422253
path.segments.last().unwrap(),
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![feature(min_generic_const_args)]
2+
#![expect(incomplete_features)]
3+
4+
trait Tr {
5+
const N: usize;
6+
}
7+
8+
struct Blah<const N: usize>;
9+
10+
fn foo() -> Blah<{ Tr::N }> {
11+
//~^ ERROR ambiguous associated constant
12+
todo!()
13+
}
14+
15+
fn main() {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0223]: ambiguous associated constant
2+
--> $DIR/ambiguous-assoc-const.rs:10:20
3+
|
4+
LL | fn foo() -> Blah<{ Tr::N }> {
5+
| ^^^^^
6+
|
7+
help: if there were a type named `Example` that implemented `Tr`, you could use the fully-qualified path
8+
|
9+
LL | fn foo() -> Blah<{ <Example as Tr>::N }> {
10+
| ~~~~~~~~~~~~~~~~~~
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0223`.

0 commit comments

Comments
 (0)