Skip to content

Commit e984081

Browse files
committed
Properly handle ambiguous assoc const
1 parent 3e6de40 commit e984081

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
@@ -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
@@ -1308,11 +1308,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13081308
self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);
13091309

13101310
// Don't print `ty::Error` to the user.
1311-
self.report_ambiguous_assoc_ty(
1311+
self.report_ambiguous_assoc(
13121312
span,
13131313
&[qself_ty.to_string()],
13141314
&traits,
13151315
assoc_ident.name,
1316+
ty::AssocKind::Type,
13161317
)
13171318
};
13181319
return Err(reported);
@@ -1393,13 +1394,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13931394

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

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

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

@@ -1670,7 +1675,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
16701675
fn lower_qpath_const(
16711676
&self,
16721677
span: Span,
1673-
self_ty: Ty<'tcx>,
1678+
opt_self_ty: Option<Ty<'tcx>>,
16741679
item_def_id: DefId,
16751680
trait_segment: &hir::PathSegment<'tcx>,
16761681
item_segment: &hir::PathSegment<'tcx>,
@@ -1680,6 +1685,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
16801685
let trait_def_id = tcx.parent(item_def_id);
16811686
debug!(?trait_def_id);
16821687

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

16851699
let (item_def_id, item_args) = self.lower_qpath_shared(
@@ -1719,7 +1733,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
17191733
trait_def_id: DefId,
17201734
span: Span,
17211735
item_segment: &hir::PathSegment<'tcx>,
1722-
) -> Ty<'tcx> {
1736+
kind: ty::AssocKind,
1737+
) -> ErrorGuaranteed {
17231738
let tcx = self.tcx();
17241739
let path_str = tcx.def_path_str(trait_def_id);
17251740

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

17641777
pub fn prohibit_generic_args<'a>(
@@ -2233,11 +2246,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22332246
path.segments[..path.segments.len() - 2].iter(),
22342247
GenericsArgsErrExtend::None,
22352248
);
2236-
// FIXME(mgca): maybe needs proper error reported
2237-
let Some(self_ty) = opt_self_ty else { span_bug!(span, "{path:?}") };
22382249
self.lower_qpath_const(
22392250
span,
2240-
self_ty,
2251+
opt_self_ty,
22412252
did,
22422253
&path.segments[path.segments.len() - 2],
22432254
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)