Rollup merge of #115744 - fmease:fix-e0401, r=compiler-errors
Improve diagnostic for generic params from outer items (E0401) Generalize the wording of E0401 to talk about *outer items* instead of *outer functions* since the current phrasing is outdated. The outer item can be a function, constant, trait, ADT or impl block (see the new UI test for the more exotic examples). Further, don't suggest introducing generic parameters to constant items unless the feature `generic_const_items` is enabled. Lastly, make E0401 translatable while we're at it. Fixes #115720.
This commit is contained in:
commit
8b49731211
41 changed files with 306 additions and 183 deletions
|
@ -553,43 +553,40 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
resolution_error: ResolutionError<'a>,
|
||||
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
match resolution_error {
|
||||
ResolutionError::GenericParamsFromOuterFunction(outer_res, has_generic_params) => {
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params) => {
|
||||
use errs::GenericParamsFromOuterItemLabel as Label;
|
||||
let mut err = errs::GenericParamsFromOuterItem {
|
||||
span,
|
||||
E0401,
|
||||
"can't use generic parameters from outer function",
|
||||
);
|
||||
err.span_label(span, "use of generic parameter from outer function");
|
||||
label: None,
|
||||
refer_to_type_directly: None,
|
||||
sugg: None,
|
||||
};
|
||||
|
||||
let sm = self.tcx.sess.source_map();
|
||||
let def_id = match outer_res {
|
||||
Res::SelfTyParam { .. } => {
|
||||
err.span_label(span, "can't use `Self` here");
|
||||
return err;
|
||||
err.label = Some(Label::SelfTyParam(span));
|
||||
return self.tcx.sess.create_err(err);
|
||||
}
|
||||
Res::SelfTyAlias { alias_to: def_id, .. } => {
|
||||
err.span_label(
|
||||
reduce_impl_span_to_impl_keyword(sm, self.def_span(def_id)),
|
||||
"`Self` type implicitly declared here, by this `impl`",
|
||||
);
|
||||
err.span_label(span, "use a type here instead");
|
||||
return err;
|
||||
err.label = Some(Label::SelfTyAlias(reduce_impl_span_to_impl_keyword(
|
||||
sm,
|
||||
self.def_span(def_id),
|
||||
)));
|
||||
err.refer_to_type_directly = Some(span);
|
||||
return self.tcx.sess.create_err(err);
|
||||
}
|
||||
Res::Def(DefKind::TyParam, def_id) => {
|
||||
err.span_label(self.def_span(def_id), "type parameter from outer function");
|
||||
err.label = Some(Label::TyParam(self.def_span(def_id)));
|
||||
def_id
|
||||
}
|
||||
Res::Def(DefKind::ConstParam, def_id) => {
|
||||
err.span_label(
|
||||
self.def_span(def_id),
|
||||
"const parameter from outer function",
|
||||
);
|
||||
err.label = Some(Label::ConstParam(self.def_span(def_id)));
|
||||
def_id
|
||||
}
|
||||
_ => {
|
||||
bug!(
|
||||
"GenericParamsFromOuterFunction should only be used with \
|
||||
"GenericParamsFromOuterItem should only be used with \
|
||||
Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or \
|
||||
DefKind::ConstParam"
|
||||
);
|
||||
|
@ -597,9 +594,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
};
|
||||
|
||||
if let HasGenericParams::Yes(span) = has_generic_params {
|
||||
// Try to retrieve the span of the function signature and generate a new
|
||||
// message with a local type or const parameter.
|
||||
let sugg_msg = "try using a local generic parameter instead";
|
||||
let name = self.tcx.item_name(def_id);
|
||||
let (span, snippet) = if span.is_empty() {
|
||||
let snippet = format!("<{name}>");
|
||||
|
@ -609,11 +603,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
let snippet = format!("{name}, ");
|
||||
(span, snippet)
|
||||
};
|
||||
// Suggest the modification to the user
|
||||
err.span_suggestion(span, sugg_msg, snippet, Applicability::MaybeIncorrect);
|
||||
err.sugg = Some(errs::GenericParamsFromOuterItemSugg { span, snippet });
|
||||
}
|
||||
|
||||
err
|
||||
self.tcx.sess.create_err(err)
|
||||
}
|
||||
ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => self
|
||||
.tcx
|
||||
|
|
|
@ -32,6 +32,40 @@ pub(crate) struct CrateRootNamesMustBeNamedExplicitly(#[primary_span] pub(crate)
|
|||
#[diag(resolve_crate_root_imports_must_be_named_explicitly)]
|
||||
pub(crate) struct ResolutionError(#[primary_span] pub(crate) Span);
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(resolve_generic_params_from_outer_item, code = "E0401")]
|
||||
pub(crate) struct GenericParamsFromOuterItem {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub(crate) span: Span,
|
||||
#[subdiagnostic]
|
||||
pub(crate) label: Option<GenericParamsFromOuterItemLabel>,
|
||||
#[label(resolve_refer_to_type_directly)]
|
||||
pub(crate) refer_to_type_directly: Option<Span>,
|
||||
#[subdiagnostic]
|
||||
pub(crate) sugg: Option<GenericParamsFromOuterItemSugg>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum GenericParamsFromOuterItemLabel {
|
||||
#[label(resolve_generic_params_from_outer_item_self_ty_param)]
|
||||
SelfTyParam(#[primary_span] Span),
|
||||
#[label(resolve_generic_params_from_outer_item_self_ty_alias)]
|
||||
SelfTyAlias(#[primary_span] Span),
|
||||
#[label(resolve_generic_params_from_outer_item_ty_param)]
|
||||
TyParam(#[primary_span] Span),
|
||||
#[label(resolve_generic_params_from_outer_item_const_param)]
|
||||
ConstParam(#[primary_span] Span),
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(resolve_suggestion, code = "{snippet}", applicability = "maybe-incorrect")]
|
||||
pub(crate) struct GenericParamsFromOuterItemSugg {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
pub(crate) snippet: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(resolve_name_is_already_used_as_generic_parameter, code = "E0403")]
|
||||
pub(crate) struct NameAlreadyUsedInParameterList {
|
||||
|
|
|
@ -1229,10 +1229,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
if let Some(span) = finalize {
|
||||
self.report_error(
|
||||
span,
|
||||
ResolutionError::GenericParamsFromOuterFunction(
|
||||
res,
|
||||
has_generic_params,
|
||||
),
|
||||
ResolutionError::GenericParamsFromOuterItem(res, has_generic_params),
|
||||
);
|
||||
}
|
||||
return Res::Err;
|
||||
|
@ -1296,10 +1293,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
if let Some(span) = finalize {
|
||||
self.report_error(
|
||||
span,
|
||||
ResolutionError::GenericParamsFromOuterFunction(
|
||||
res,
|
||||
has_generic_params,
|
||||
),
|
||||
ResolutionError::GenericParamsFromOuterItem(res, has_generic_params),
|
||||
);
|
||||
}
|
||||
return Res::Err;
|
||||
|
|
|
@ -2450,7 +2450,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => {
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::Item(HasGenericParams::Yes(generics.span)),
|
||||
RibKind::Item(if self.r.tcx.features().generic_const_items {
|
||||
HasGenericParams::Yes(generics.span)
|
||||
} else {
|
||||
HasGenericParams::No
|
||||
}),
|
||||
LifetimeRibKind::Generics {
|
||||
binder: item.id,
|
||||
kind: LifetimeBinderKind::ConstItem,
|
||||
|
|
|
@ -186,8 +186,8 @@ struct BindingError {
|
|||
|
||||
#[derive(Debug)]
|
||||
enum ResolutionError<'a> {
|
||||
/// Error E0401: can't use type or const parameters from outer function.
|
||||
GenericParamsFromOuterFunction(Res, HasGenericParams),
|
||||
/// Error E0401: can't use type or const parameters from outer item.
|
||||
GenericParamsFromOuterItem(Res, HasGenericParams),
|
||||
/// Error E0403: the name is already used for a type or const parameter in this generic
|
||||
/// parameter list.
|
||||
NameAlreadyUsedInParameterList(Symbol, Span),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue