Skip to content

Commit 48e863a

Browse files
committed
Properly handle ambiguous assoc const
1 parent 0b7ef36 commit 48e863a

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
@@ -468,11 +468,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
468468

469469
// Good error for `where Trait::method(..): Send`.
470470
let Some(self_ty) = opt_self_ty else {
471-
return self.error_missing_qpath_self_ty(
471+
let guar = self.error_missing_qpath_self_ty(
472472
trait_def_id,
473473
hir_ty.span,
474474
item_segment,
475+
ty::AssocKind::Type,
475476
);
477+
return Ty::new_error(tcx, guar);
476478
};
477479
let self_ty = self.lower_ty(self_ty);
478480

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

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

388-
pub(super) fn report_ambiguous_assoc_ty(
388+
pub(super) fn report_ambiguous_assoc(
389389
&self,
390390
span: Span,
391391
types: &[String],
392392
traits: &[String],
393393
name: Symbol,
394+
kind: ty::AssocKind,
394395
) -> ErrorGuaranteed {
395-
let mut err = struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated type");
396+
let kind_str = assoc_kind_str(kind);
397+
let mut err =
398+
struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated {kind_str}");
396399
if self
397400
.tcx()
398401
.resolutions(())
@@ -417,7 +420,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
417420
span,
418421
format!(
419422
"if there were a type named `Type` that implements a trait named \
420-
`Trait` with associated type `{name}`, you could use the \
423+
`Trait` with associated {kind_str} `{name}`, you could use the \
421424
fully-qualified path",
422425
),
423426
format!("<Type as Trait>::{name}"),
@@ -440,7 +443,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
440443
span,
441444
format!(
442445
"if there were a type named `Example` that implemented one of the \
443-
traits with associated type `{name}`, you could use the \
446+
traits with associated {kind_str} `{name}`, you could use the \
444447
fully-qualified path",
445448
),
446449
traits.iter().map(|trait_str| format!("<Example as {trait_str}>::{name}")),
@@ -451,7 +454,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
451454
err.span_suggestion_verbose(
452455
span,
453456
format!(
454-
"if there were a trait named `Example` with associated type `{name}` \
457+
"if there were a trait named `Example` with associated {kind_str} `{name}` \
455458
implemented for `{type_str}`, you could use the fully-qualified path",
456459
),
457460
format!("<{type_str} as Example>::{name}"),
@@ -462,7 +465,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
462465
err.span_suggestions(
463466
span,
464467
format!(
465-
"if there were a trait named `Example` with associated type `{name}` \
468+
"if there were a trait named `Example` with associated {kind_str} `{name}` \
466469
implemented for one of the types, you could use the fully-qualified \
467470
path",
468471
),

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

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

13321332
// Don't print `ty::Error` to the user.
1333-
self.report_ambiguous_assoc_ty(
1333+
self.report_ambiguous_assoc(
13341334
span,
13351335
&[qself_ty.to_string()],
13361336
&traits,
13371337
assoc_ident.name,
1338+
ty::AssocKind::Type,
13381339
)
13391340
};
13401341
return Err(reported);
@@ -1415,13 +1416,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
14151416

14161417
// In contexts that have no inference context, just make a new one.
14171418
// We do need a local variable to store it, though.
1418-
let infcx_;
14191419
let infcx = match self.infcx() {
14201420
Some(infcx) => infcx,
14211421
None => {
14221422
assert!(!self_ty.has_infer());
1423-
infcx_ = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
1424-
&infcx_
1423+
&tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis())
14251424
}
14261425
};
14271426

@@ -1672,7 +1671,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
16721671
debug!(?trait_def_id);
16731672

16741673
let Some(self_ty) = opt_self_ty else {
1675-
return self.error_missing_qpath_self_ty(trait_def_id, span, item_segment);
1674+
let guar = self.error_missing_qpath_self_ty(
1675+
trait_def_id,
1676+
span,
1677+
item_segment,
1678+
ty::AssocKind::Type,
1679+
);
1680+
return Ty::new_error(tcx, guar);
16761681
};
16771682
debug!(?self_ty);
16781683

@@ -1692,7 +1697,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
16921697
fn lower_qpath_const(
16931698
&self,
16941699
span: Span,
1695-
self_ty: Ty<'tcx>,
1700+
opt_self_ty: Option<Ty<'tcx>>,
16961701
item_def_id: DefId,
16971702
trait_segment: &hir::PathSegment<'tcx>,
16981703
item_segment: &hir::PathSegment<'tcx>,
@@ -1702,6 +1707,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
17021707
let trait_def_id = tcx.parent(item_def_id);
17031708
debug!(?trait_def_id);
17041709

1710+
let Some(self_ty) = opt_self_ty else {
1711+
let guar = self.error_missing_qpath_self_ty(
1712+
trait_def_id,
1713+
span,
1714+
item_segment,
1715+
ty::AssocKind::Const,
1716+
);
1717+
return Const::new_error(tcx, guar);
1718+
};
17051719
debug!(?self_ty);
17061720

17071721
let (item_def_id, item_args) = self.lower_qpath_shared(
@@ -1741,7 +1755,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
17411755
trait_def_id: DefId,
17421756
span: Span,
17431757
item_segment: &hir::PathSegment<'tcx>,
1744-
) -> Ty<'tcx> {
1758+
kind: ty::AssocKind,
1759+
) -> ErrorGuaranteed {
17451760
let tcx = self.tcx();
17461761
let path_str = tcx.def_path_str(trait_def_id);
17471762

@@ -1777,9 +1792,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
17771792
// FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
17781793
// references the trait. Relevant for the first case in
17791794
// `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
1780-
let reported =
1781-
self.report_ambiguous_assoc_ty(span, &type_names, &[path_str], item_segment.ident.name);
1782-
Ty::new_error(tcx, reported)
1795+
self.report_ambiguous_assoc(span, &type_names, &[path_str], item_segment.ident.name, kind)
17831796
}
17841797

17851798
pub fn prohibit_generic_args<'a>(
@@ -2290,11 +2303,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22902303
path.segments[..path.segments.len() - 2].iter(),
22912304
GenericsArgsErrExtend::None,
22922305
);
2293-
// FIXME(mgca): maybe needs proper error reported
2294-
let Some(self_ty) = opt_self_ty else { span_bug!(span, "{path:?}") };
22952306
self.lower_qpath_const(
22962307
span,
2297-
self_ty,
2308+
opt_self_ty,
22982309
did,
22992310
&path.segments[path.segments.len() - 2],
23002311
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)