Improve local generic parameter suggestions.

This commit is contained in:
Camille GILLOT 2022-07-14 15:09:30 +02:00
parent d7d701a9dc
commit 613dc2204d
16 changed files with 90 additions and 81 deletions

View file

@ -511,7 +511,7 @@ impl<'a> Resolver<'a> {
err.span_label(span, "use of generic parameter from outer function");
let sm = self.session.source_map();
match outer_res {
let def_id = match outer_res {
Res::SelfTy { trait_: maybe_trait_defid, alias_to: maybe_impl_defid } => {
if let Some(impl_span) =
maybe_impl_defid.and_then(|(def_id, _)| self.opt_span(def_id))
@ -536,11 +536,13 @@ impl<'a> Resolver<'a> {
if let Some(span) = self.opt_span(def_id) {
err.span_label(span, "type parameter from outer function");
}
def_id
}
Res::Def(DefKind::ConstParam, def_id) => {
if let Some(span) = self.opt_span(def_id) {
err.span_label(span, "const parameter from outer function");
}
def_id
}
_ => {
bug!(
@ -548,28 +550,23 @@ impl<'a> Resolver<'a> {
DefKind::TyParam or DefKind::ConstParam"
);
}
}
};
if let HasGenericParams::Yes = has_generic_params {
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";
if let Some((sugg_span, snippet)) = sm.generate_local_type_param_snippet(span) {
// Suggest the modification to the user
err.span_suggestion(
sugg_span,
sugg_msg,
snippet,
Applicability::MachineApplicable,
);
} else if let Some(sp) = sm.generate_fn_name_span(span) {
err.span_label(
sp,
"try adding a local generic parameter in this method instead",
);
let name = self.opt_name(def_id).unwrap_or(sym::T);
let (span, snippet) = if span.is_empty() {
let snippet = format!("<{}>", name);
(span, snippet)
} else {
err.help("try using a local generic parameter instead");
}
let span = sm.span_through_char(span, '<').shrink_to_hi();
let snippet = format!("{}, ", name);
(span, snippet)
};
// Suggest the modification to the user
err.span_suggestion(span, sugg_msg, snippet, Applicability::MachineApplicable);
}
err

View file

@ -1170,10 +1170,11 @@ impl<'a> Resolver<'a> {
let has_generic_params: HasGenericParams = match rib.kind {
NormalRibKind
| ClosureOrAsyncRibKind
| AssocItemRibKind
| ModuleRibKind(..)
| MacroDefinition(..)
| InlineAsmSymRibKind
| FnItemRibKind
| AssocItemRibKind
| ForwardGenericParamBanRibKind => {
// Nothing to do. Continue.
continue;
@ -1211,7 +1212,6 @@ impl<'a> Resolver<'a> {
// This was an attempt to use a type parameter outside its scope.
ItemRibKind(has_generic_params) => has_generic_params,
FnItemRibKind => HasGenericParams::Yes,
ConstParamTyRibKind => {
if let Some(span) = finalize {
self.report_error(
@ -1248,10 +1248,11 @@ impl<'a> Resolver<'a> {
let has_generic_params = match rib.kind {
NormalRibKind
| ClosureOrAsyncRibKind
| AssocItemRibKind
| ModuleRibKind(..)
| MacroDefinition(..)
| InlineAsmSymRibKind
| FnItemRibKind
| AssocItemRibKind
| ForwardGenericParamBanRibKind => continue,
ConstantItemRibKind(trivial, _) => {
@ -1278,7 +1279,6 @@ impl<'a> Resolver<'a> {
}
ItemRibKind(has_generic_params) => has_generic_params,
FnItemRibKind => HasGenericParams::Yes,
ConstParamTyRibKind => {
if let Some(span) = finalize {
self.report_error(

View file

@ -93,7 +93,7 @@ enum PatBoundCtx {
/// Does this the item (from the item rib scope) allow generic parameters?
#[derive(Copy, Clone, Debug)]
pub(crate) enum HasGenericParams {
Yes,
Yes(Span),
No,
}
@ -758,7 +758,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
this.with_generic_param_rib(
&generics.params,
ItemRibKind(HasGenericParams::Yes),
ItemRibKind(HasGenericParams::Yes(generics.span)),
LifetimeRibKind::Generics {
binder: foreign_item.id,
kind: LifetimeBinderKind::Item,
@ -772,7 +772,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
this.with_generic_param_rib(
&generics.params,
ItemRibKind(HasGenericParams::Yes),
ItemRibKind(HasGenericParams::Yes(generics.span)),
LifetimeRibKind::Generics {
binder: foreign_item.id,
kind: LifetimeBinderKind::Function,
@ -2078,7 +2078,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.with_current_self_item(item, |this| {
this.with_generic_param_rib(
&generics.params,
ItemRibKind(HasGenericParams::Yes),
ItemRibKind(HasGenericParams::Yes(generics.span)),
LifetimeRibKind::Generics {
binder: item.id,
kind: LifetimeBinderKind::Item,
@ -2148,7 +2148,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
self.with_generic_param_rib(
&generics.params,
ItemRibKind(HasGenericParams::Yes),
ItemRibKind(HasGenericParams::Yes(generics.span)),
LifetimeRibKind::Generics {
binder: item.id,
kind: LifetimeBinderKind::Item,
@ -2161,7 +2161,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ItemKind::Fn(box Fn { ref generics, .. }) => {
self.with_generic_param_rib(
&generics.params,
ItemRibKind(HasGenericParams::Yes),
ItemRibKind(HasGenericParams::Yes(generics.span)),
LifetimeRibKind::Generics {
binder: item.id,
kind: LifetimeBinderKind::Function,
@ -2193,7 +2193,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// Create a new rib for the trait-wide type parameters.
self.with_generic_param_rib(
&generics.params,
ItemRibKind(HasGenericParams::Yes),
ItemRibKind(HasGenericParams::Yes(generics.span)),
LifetimeRibKind::Generics {
binder: item.id,
kind: LifetimeBinderKind::Item,
@ -2217,7 +2217,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// Create a new rib for the trait-wide type parameters.
self.with_generic_param_rib(
&generics.params,
ItemRibKind(HasGenericParams::Yes),
ItemRibKind(HasGenericParams::Yes(generics.span)),
LifetimeRibKind::Generics {
binder: item.id,
kind: LifetimeBinderKind::Item,
@ -2605,7 +2605,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// If applicable, create a rib for the type parameters.
self.with_generic_param_rib(
&generics.params,
ItemRibKind(HasGenericParams::Yes),
ItemRibKind(HasGenericParams::Yes(generics.span)),
LifetimeRibKind::Generics {
span: generics.span,
binder: item_id,

View file

@ -1945,6 +1945,16 @@ impl<'a> Resolver<'a> {
def_id.as_local().map(|def_id| self.source_span[def_id])
}
/// Retrieves the name of the given `DefId`.
#[inline]
pub fn opt_name(&self, def_id: DefId) -> Option<Symbol> {
let def_key = match def_id.as_local() {
Some(def_id) => self.definitions.def_key(def_id),
None => self.cstore().def_key(def_id),
};
def_key.get_opt_name()
}
/// Checks if an expression refers to a function marked with
/// `#[rustc_legacy_const_generics]` and returns the argument index list
/// from the attribute.