Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ fn generic_arg_mismatch_err(
) => match path.res {
Res::Err => {
add_braces_suggestion(arg, &mut err);
return err
.with_primary_message("unresolved item provided when a constant was expected")
.emit();
err.primary_message("unresolved item provided when a constant was expected");
// A resolve error will already have been emitted pointing at this.
return err.delay_as_bug();
}
Res::Def(DefKind::TyParam, src_def_id) => {
if let Some(param_local_id) = param.def_id.as_local() {
Expand Down
32 changes: 30 additions & 2 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,8 @@ impl IntoDiagArg for ResolvingRestrictionKind {
pub(crate) enum PathSource<'a, 'ast, 'ra> {
/// Type paths `Path`.
Type,
/// Type or constant in a `PathSegment` argument.
TypeParam,
/// Trait paths in bounds or impls.
Trait(AliasPossibility),
/// Expression paths `path`, with optional parent context.
Expand Down Expand Up @@ -482,6 +484,7 @@ impl PathSource<'_, '_, '_> {
fn namespace(self) -> Namespace {
match self {
PathSource::Type
| PathSource::TypeParam
| PathSource::Trait(_)
| PathSource::Struct(_)
| PathSource::DefineOpaques
Expand All @@ -501,6 +504,7 @@ impl PathSource<'_, '_, '_> {
fn defer_to_typeck(self) -> bool {
match self {
PathSource::Type
| PathSource::TypeParam
| PathSource::Expr(..)
| PathSource::Pat
| PathSource::Struct(_)
Expand All @@ -521,6 +525,7 @@ impl PathSource<'_, '_, '_> {
match &self {
PathSource::DefineOpaques => "type alias or associated type with opaqaue types",
PathSource::Type => "type",
PathSource::TypeParam => "type or constant",
PathSource::Trait(_) => "trait",
PathSource::Pat => "unit struct, unit variant or constant",
PathSource::Struct(_) => "struct, variant or union type",
Expand Down Expand Up @@ -598,6 +603,28 @@ impl PathSource<'_, '_, '_> {
| Res::SelfTyParam { .. }
| Res::SelfTyAlias { .. }
),
PathSource::TypeParam => matches!(
res,
Res::Def(
DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::Trait
| DefKind::TraitAlias
| DefKind::TyAlias
| DefKind::AssocTy
| DefKind::TyParam
| DefKind::OpaqueTy
| DefKind::AnonConst
| DefKind::AssocConst { is_type_const: _ }
| DefKind::Const { is_type_const: _ }
| DefKind::ConstParam
| DefKind::ForeignTy,
_,
) | Res::PrimTy(..)
| Res::SelfTyParam { .. }
| Res::SelfTyAlias { .. }
),
PathSource::Trait(AliasPossibility::No) => matches!(res, Res::Def(DefKind::Trait, _)),
PathSource::Trait(AliasPossibility::Maybe) => {
matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _))
Expand Down Expand Up @@ -673,8 +700,8 @@ impl PathSource<'_, '_, '_> {
match (self, has_unexpected_resolution) {
(PathSource::Trait(_), true) => E0404,
(PathSource::Trait(_), false) => E0405,
(PathSource::Type | PathSource::DefineOpaques, true) => E0573,
(PathSource::Type | PathSource::DefineOpaques, false) => E0425,
(PathSource::Type | PathSource::DefineOpaques | PathSource::TypeParam, true) => E0573,
(PathSource::Type | PathSource::DefineOpaques | PathSource::TypeParam, false) => E0425,
(PathSource::Struct(_), true) => E0574,
(PathSource::Struct(_), false) => E0422,
(PathSource::Expr(..), true)
Expand Down Expand Up @@ -2233,6 +2260,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
PathSource::Trait(..)
| PathSource::TraitItem(..)
| PathSource::Type
| PathSource::TypeParam
| PathSource::PreciseCapturingArg(..)
| PathSource::ReturnTypeNotation
| PathSource::Macro
Expand Down
19 changes: 14 additions & 5 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -669,11 +669,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
path: &[Segment],
following_seg: Option<&Segment>,
span: Span,
source: PathSource<'_, 'ast, 'ra>,
mut source: PathSource<'_, 'ast, 'ra>,
res: Option<Res>,
qself: Option<&QSelf>,
) -> (Diag<'tcx>, Vec<ImportSuggestion>) {
debug!(?res, ?source);
let cross_namespace_res = res.filter(|res| !res.matches_ns(source.namespace()));
let could_be_expr = res.is_some_and(|res| self.could_be_expr(res, span));
let base_error = self.make_base_error(
Expand All @@ -688,6 +687,14 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
let mut err = self.r.dcx().struct_span_err(base_error.span, base_error.msg.clone());
err.code(code);

if self.diag_metadata.currently_processing_generic_args
&& let PathSource::Type = source
&& let [segment] = path
&& !segment.has_generic_args
{
source = PathSource::TypeParam;
}

if let Some(res) = cross_namespace_res {
err.note(format!(
"{} {} named `{}` exists in another namespace",
Expand Down Expand Up @@ -1043,9 +1050,11 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
})
.unwrap_or(false);
if field_is_format_named_arg {
err.help(
format!("you might have meant to use the available field in a format string: `\"{{}}\", self.{}`", segment.ident.name),
);
err.help(format!(
"you might have meant to use the available field in a format \
string: `\"{{}}\", self.{}`",
segment.ident.name,
));
} else {
err.span_suggestion_verbose(
span.shrink_to_lo(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
typeck_results,
span,
);
let delay_as_bug = match kind {
InferSourceKind::ClosureArg { kind, .. } if let PatKind::Err(_) = kind => {
// We will have already emitted an error about this pattern.
true
}
InferSourceKind::GenericArg { hir_id, argument_index, .. }
if let hir::Node::PathSegment(segment) = self.tcx.hir_node(hir_id)
&& let Some(args) = segment.args
&& let Some(hir::GenericArg::Type(ty)) = args.args.get(argument_index)
&& let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
&& let Res::Err = path.res =>
{
// We have already emitted a name resolution error.
true
}
_ => false,
};

let mut err = match error_code {
TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired {
Expand Down Expand Up @@ -595,8 +612,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}),
};
*err.long_ty_path() = long_ty_path;
if let InferSourceKind::ClosureArg { kind: PatKind::Err(_), .. } = kind {
// We will have already emitted an error about this pattern.
if delay_as_bug {
// We have already emitted an earlier more relevant error.
err.downgrade_to_delayed_bug();
}
err
Expand Down Expand Up @@ -886,6 +903,7 @@ struct InsertableGenericArgs<'tcx> {
generics_def_id: DefId,
def_id: DefId,
have_turbofish: bool,
hir_id: HirId,
}

/// A visitor which searches for the "best" spot to use in the inference error.
Expand Down Expand Up @@ -1154,6 +1172,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
generics_def_id: def_id,
def_id,
have_turbofish,
hir_id: expr.hir_id,
}
};
return Box::new(insertable.into_iter());
Expand Down Expand Up @@ -1193,6 +1212,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
generics_def_id,
def_id: path.res.def_id(),
have_turbofish,
hir_id: path.segments.last().unwrap().hir_id,
}
};

Expand All @@ -1213,6 +1233,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
generics_def_id,
def_id: res.def_id(),
have_turbofish,
hir_id: segment.hir_id,
})
})
.chain(last_segment_using_path_data)
Expand Down Expand Up @@ -1246,6 +1267,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
generics_def_id: def_id,
def_id,
have_turbofish: false,
hir_id: segment.hir_id,
})
};

Expand Down Expand Up @@ -1404,6 +1426,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
generics_def_id,
def_id,
have_turbofish,
hir_id,
} = args;
let generics = tcx.generics_of(generics_def_id);
if let Some(argument_index) = generics
Expand Down Expand Up @@ -1442,7 +1465,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
def_id,
generic_args,
have_turbofish,
hir_id: expr.hir_id,
hir_id,
},
});
}
Expand Down
1 change: 0 additions & 1 deletion tests/ui/const-generics/assoc_const_as_type_argument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ fn bar<const N: usize>() {}
fn foo<T: Trait>() {
bar::<<T as Trait>::ASSOC>();
//~^ ERROR: cannot find associated type `ASSOC` in trait `Trait`
//~| ERROR: unresolved item provided when a constant was expected
}

fn main() {}
16 changes: 2 additions & 14 deletions tests/ui/const-generics/assoc_const_as_type_argument.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,6 @@ LL | bar::<<T as Trait>::ASSOC>();
|
= note: an associated constant named `Trait::ASSOC` exists in another namespace

error[E0747]: unresolved item provided when a constant was expected
--> $DIR/assoc_const_as_type_argument.rs:8:11
|
LL | bar::<<T as Trait>::ASSOC>();
| ^^^^^^^^^^^^^^^^^^^
|
help: if this generic argument was intended as a const parameter, surround it with braces
|
LL | bar::<{ <T as Trait>::ASSOC }>();
| + +

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

Some errors have detailed explanations: E0575, E0747.
For more information about an error, try `rustc --explain E0575`.
For more information about this error, try `rustc --explain E0575`.
Loading
Loading