diff --git a/single-use-lifetime-on-debug-struct b/single-use-lifetime-on-debug-struct new file mode 100755 index 0000000000000..9f7f9b559ad15 Binary files /dev/null and b/single-use-lifetime-on-debug-struct differ diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index e93a2315ca321..4bfd196a66e7f 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -18,6 +18,39 @@ use crate::{import_candidate_to_enum_paths, is_self_type, is_self_value, path_na use crate::{AssocSuggestion, CrateLint, ImportSuggestion, ModuleOrUniformRoot, PathResult, PathSource, Resolver, Segment, Suggestion}; +#[derive(Clone, Copy)] +crate enum CurrentScope { + Const, + Static, + Type, + Other, +} + +impl CurrentScope { + crate fn is_other(&self) -> bool { + match self { + CurrentScope::Other => true, + _ => false, + } + } + + crate fn description(&self) -> &'static str { + match self { + Self::Const => "a `const`", + Self::Static => "a `static`", + Self::Type => "associated type", + Self::Other => "outer function", + } + } + + crate fn generic_param_resolution_error_message(&self) -> String { + match self { + Self::Other => format!("from {}", self.description()), + _ => format!("in {}", self.description()), + } + } +} + impl<'a> Resolver<'a> { /// Handles error reporting for `smart_resolve_path_fragment` function. /// Creates base error and amends it with one short label and possibly some longer helps/notes. diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index f4c23a023b104..fc2f160dd5981 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -70,7 +70,9 @@ use rustc_data_structures::ptr_key::PtrKey; use rustc_data_structures::sync::Lrc; use smallvec::SmallVec; -use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding}; +use diagnostics::{ + find_span_of_binding_until_next_binding, extend_span_to_previous_binding, CurrentScope, +}; use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver}; use macros::{InvocationData, LegacyBinding, ParentScope}; @@ -210,14 +212,21 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>, -> DiagnosticBuilder<'sess> { match resolution_error { ResolutionError::GenericParamsFromOuterFunction(outer_res) => { + let msg = resolver.scope.generic_param_resolution_error_message(); let mut err = struct_span_err!(resolver.session, span, E0401, - "can't use generic parameters from outer function", + "can't use generic parameters {}", + msg, ); - err.span_label(span, format!("use of generic parameter from outer function")); + err.span_label(span, &format!("use of generic parameter {}", msg)); let cm = resolver.session.source_map(); + let type_param_extra_msg = if resolver.scope.is_other() { + "from outer function " + } else { + "" + }; match outer_res { Res::SelfTy(maybe_trait_defid, maybe_impl_defid) => { if let Some(impl_span) = maybe_impl_defid.and_then(|def_id| { @@ -241,12 +250,18 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>, }, Res::Def(DefKind::TyParam, def_id) => { if let Some(span) = resolver.definitions.opt_span(def_id) { - err.span_label(span, "type parameter from outer function"); + err.span_label(span, format!( + "type parameter {}being used", + type_param_extra_msg, + )); } } Res::Def(DefKind::ConstParam, def_id) => { if let Some(span) = resolver.definitions.opt_span(def_id) { - err.span_label(span, "const parameter from outer function"); + err.span_label(span, format!( + "const parameter {}being used", + type_param_extra_msg, + )); } } _ => { @@ -258,7 +273,14 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>, // Try to retrieve the span of the function signature and generate a new message with // a local type or const parameter. let sugg_msg = &format!("try using a local generic parameter instead"); - if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) { + if !resolver.scope.is_other() { + err.help(&format!( + "{} need a type instead of a generic parameter", + resolver.scope.description(), + )); + } else if let Some( + (sugg_span, new_snippet), + ) = cm.generate_local_type_param_snippet(span) { // Suggest the modification to the user err.span_suggestion( sugg_span, @@ -267,6 +289,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>, Applicability::MachineApplicable, ); } else if let Some(sp) = cm.generate_fn_name_span(span) { + // FIXME: needs to use proper scope navigation to avoid errors like #45447 err.span_label(sp, format!("try adding a local generic parameter in this method instead")); } else { @@ -1688,6 +1711,9 @@ pub struct Resolver<'a> { current_type_ascription: Vec, injected_crate: Option>, + + /// Used for more accurate error when using type parameters in a associated items. + scope: CurrentScope, } /// Nothing really interesting here; it just provides memory for the rest of the crate. @@ -2013,6 +2039,7 @@ impl<'a> Resolver<'a> { unused_macros: FxHashSet::default(), current_type_ascription: Vec::new(), injected_crate: None, + scope: CurrentScope::Other, } } @@ -2520,6 +2547,8 @@ impl<'a> Resolver<'a> { match item.node { ItemKind::Ty(_, ref generics) => { + let scope = self.scope; + self.scope = CurrentScope::Type; self.with_current_self_item(item, |this| { this.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| { let item_def_id = this.definitions.local_def_id(item.id); @@ -2528,6 +2557,7 @@ impl<'a> Resolver<'a> { }) }) }); + self.scope = scope; } ItemKind::Existential(_, ref generics) | @@ -2611,6 +2641,12 @@ impl<'a> Resolver<'a> { ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(ref ty, ref expr) => { + let scope = self.scope; + self.scope = match item.node { + ItemKind::Static(..) => CurrentScope::Static, + ItemKind::Const(..) => CurrentScope::Const, + _ => unreachable!(), + }; debug!("resolve_item ItemKind::Const"); self.with_item_rib(|this| { this.visit_ty(ty); @@ -2618,6 +2654,7 @@ impl<'a> Resolver<'a> { this.visit_expr(expr); }); }); + self.scope = scope; } ItemKind::Use(ref use_tree) => { diff --git a/src/test/ui/bad/bad-type-env-capture.stderr b/src/test/ui/bad/bad-type-env-capture.stderr index 6f24c0d86997e..f22b5a93194bc 100644 --- a/src/test/ui/bad/bad-type-env-capture.stderr +++ b/src/test/ui/bad/bad-type-env-capture.stderr @@ -2,7 +2,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/bad-type-env-capture.rs:2:15 | LL | fn foo() { - | - type parameter from outer function + | - type parameter from outer function being used LL | fn bar(b: T) { } | --- ^ use of generic parameter from outer function | | diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.stderr b/src/test/ui/const-generics/const-param-from-outer-fn.stderr index f0b7562f62196..bd2483bba078b 100644 --- a/src/test/ui/const-generics/const-param-from-outer-fn.stderr +++ b/src/test/ui/const-generics/const-param-from-outer-fn.stderr @@ -8,7 +8,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/const-param-from-outer-fn.rs:6:9 | LL | fn foo() { - | - const parameter from outer function + | - const parameter from outer function being used LL | fn bar() -> u32 { | --- try adding a local generic parameter in this method instead LL | X diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr index 1d9dfe46722ec..53506fb587a42 100644 --- a/src/test/ui/error-codes/E0401.stderr +++ b/src/test/ui/error-codes/E0401.stderr @@ -2,7 +2,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/E0401.rs:4:39 | LL | fn foo(x: T) { - | - type parameter from outer function + | - type parameter from outer function being used LL | fn bfnr, W: Fn()>(y: T) { | --------------------------- ^ use of generic parameter from outer function | | @@ -12,7 +12,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/E0401.rs:9:16 | LL | fn foo(x: T) { - | - type parameter from outer function + | - type parameter from outer function being used ... LL | fn baz { What } //~ ERROR parameter `T` is never used fn foo() { static a: Bar = Bar::What; -//~^ ERROR can't use generic parameters from outer function + //~^ ERROR can't use generic parameters in a `static` } fn main() { diff --git a/src/test/ui/inner-static-type-parameter.stderr b/src/test/ui/inner-static-type-parameter.stderr index 083b4b67eb459..0cd0d471037ae 100644 --- a/src/test/ui/inner-static-type-parameter.stderr +++ b/src/test/ui/inner-static-type-parameter.stderr @@ -1,12 +1,12 @@ -error[E0401]: can't use generic parameters from outer function +error[E0401]: can't use generic parameters in a `static` --> $DIR/inner-static-type-parameter.rs:6:19 | LL | fn foo() { - | --- - type parameter from outer function - | | - | try adding a local generic parameter in this method instead + | - type parameter being used LL | static a: Bar = Bar::What; - | ^ use of generic parameter from outer function + | ^ use of generic parameter in a `static` + | + = help: a `static` need a type instead of a generic parameter error[E0392]: parameter `T` is never used --> $DIR/inner-static-type-parameter.rs:3:10 diff --git a/src/test/ui/issues/issue-3021-c.stderr b/src/test/ui/issues/issue-3021-c.stderr index 8764ac8a8563c..1078d80f8615e 100644 --- a/src/test/ui/issues/issue-3021-c.stderr +++ b/src/test/ui/issues/issue-3021-c.stderr @@ -2,7 +2,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/issue-3021-c.rs:4:24 | LL | fn siphash() { - | - type parameter from outer function + | - type parameter from outer function being used ... LL | fn g(&self, x: T) -> T; | - ^ use of generic parameter from outer function @@ -13,7 +13,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/issue-3021-c.rs:4:30 | LL | fn siphash() { - | - type parameter from outer function + | - type parameter from outer function being used ... LL | fn g(&self, x: T) -> T; | - ^ use of generic parameter from outer function diff --git a/src/test/ui/issues/issue-3214.stderr b/src/test/ui/issues/issue-3214.stderr index 02c8da10bb4a3..c6410e789e353 100644 --- a/src/test/ui/issues/issue-3214.stderr +++ b/src/test/ui/issues/issue-3214.stderr @@ -2,7 +2,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/issue-3214.rs:3:12 | LL | fn foo() { - | --- - type parameter from outer function + | --- - type parameter from outer function being used | | | try adding a local generic parameter in this method instead LL | struct Foo { diff --git a/src/test/ui/issues/issue-45447.rs b/src/test/ui/issues/issue-45447.rs new file mode 100644 index 0000000000000..02c0ce2cc64b0 --- /dev/null +++ b/src/test/ui/issues/issue-45447.rs @@ -0,0 +1,10 @@ +trait Foo { const FOO: Self; } +impl Foo for u32 { const FOO: Self = 1; } +fn bar(n: T) { + const BASE: T = T::FOO; + //~^ ERROR can't use generic parameters in a `const` + //~| ERROR can't use generic parameters in a `const` + type Type = T; + //~^ ERROR can't use generic parameters in associated type +} +fn main() {} diff --git a/src/test/ui/issues/issue-45447.stderr b/src/test/ui/issues/issue-45447.stderr new file mode 100644 index 0000000000000..d35e3729d0673 --- /dev/null +++ b/src/test/ui/issues/issue-45447.stderr @@ -0,0 +1,34 @@ +error[E0401]: can't use generic parameters in a `const` + --> $DIR/issue-45447.rs:4:17 + | +LL | fn bar(n: T) { + | - type parameter being used +LL | const BASE: T = T::FOO; + | ^ use of generic parameter in a `const` + | + = help: a `const` need a type instead of a generic parameter + +error[E0401]: can't use generic parameters in a `const` + --> $DIR/issue-45447.rs:4:21 + | +LL | fn bar(n: T) { + | - type parameter being used +LL | const BASE: T = T::FOO; + | ^^^^^^ use of generic parameter in a `const` + | + = help: a `const` need a type instead of a generic parameter + +error[E0401]: can't use generic parameters in associated type + --> $DIR/issue-45447.rs:7:17 + | +LL | fn bar(n: T) { + | - type parameter being used +... +LL | type Type = T; + | ^ use of generic parameter in associated type + | + = help: associated type need a type instead of a generic parameter + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0401`. diff --git a/src/test/ui/issues/issue-5997-enum.stderr b/src/test/ui/issues/issue-5997-enum.stderr index 1c58b9c391104..d0d3096795985 100644 --- a/src/test/ui/issues/issue-5997-enum.stderr +++ b/src/test/ui/issues/issue-5997-enum.stderr @@ -2,7 +2,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/issue-5997-enum.rs:2:16 | LL | fn f() -> bool { - | - - type parameter from outer function + | - - type parameter from outer function being used | | | try adding a local generic parameter in this method instead LL | enum E { V(Z) } diff --git a/src/test/ui/issues/issue-5997-struct.stderr b/src/test/ui/issues/issue-5997-struct.stderr index 5b388d16d7553..16ffd51a874b1 100644 --- a/src/test/ui/issues/issue-5997-struct.stderr +++ b/src/test/ui/issues/issue-5997-struct.stderr @@ -2,7 +2,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/issue-5997-struct.rs:2:14 | LL | fn f() -> bool { - | - - type parameter from outer function + | - - type parameter from outer function being used | | | try adding a local generic parameter in this method instead LL | struct S(T); diff --git a/src/test/ui/nested-ty-params.stderr b/src/test/ui/nested-ty-params.stderr index f6741b5e5e82a..58f87451aece4 100644 --- a/src/test/ui/nested-ty-params.stderr +++ b/src/test/ui/nested-ty-params.stderr @@ -2,7 +2,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/nested-ty-params.rs:3:16 | LL | fn hd(v: Vec ) -> U { - | - type parameter from outer function + | - type parameter from outer function being used LL | fn hd1(w: [U]) -> U { return w[0]; } | --- ^ use of generic parameter from outer function | | @@ -12,7 +12,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/nested-ty-params.rs:3:23 | LL | fn hd(v: Vec ) -> U { - | - type parameter from outer function + | - type parameter from outer function being used LL | fn hd1(w: [U]) -> U { return w[0]; } | --- ^ use of generic parameter from outer function | | diff --git a/src/test/ui/resolve/resolve-type-param-in-item-in-trait.stderr b/src/test/ui/resolve/resolve-type-param-in-item-in-trait.stderr index 10a703ee09351..89c7b401f7f63 100644 --- a/src/test/ui/resolve/resolve-type-param-in-item-in-trait.stderr +++ b/src/test/ui/resolve/resolve-type-param-in-item-in-trait.stderr @@ -2,7 +2,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/resolve-type-param-in-item-in-trait.rs:8:22 | LL | trait TraitA { - | - type parameter from outer function + | - type parameter from outer function being used LL | fn outer(&self) { | ----- try adding a local generic parameter in this method instead LL | enum Foo { @@ -13,7 +13,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/resolve-type-param-in-item-in-trait.rs:16:23 | LL | trait TraitB { - | - type parameter from outer function + | - type parameter from outer function being used LL | fn outer(&self) { | ----- try adding a local generic parameter in this method instead LL | struct Foo(A); @@ -23,7 +23,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/resolve-type-param-in-item-in-trait.rs:23:28 | LL | trait TraitC { - | - type parameter from outer function + | - type parameter from outer function being used LL | fn outer(&self) { | ----- try adding a local generic parameter in this method instead LL | struct Foo { a: A } @@ -33,7 +33,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/resolve-type-param-in-item-in-trait.rs:30:22 | LL | trait TraitD { - | - type parameter from outer function + | - type parameter from outer function being used LL | fn outer(&self) { LL | fn foo(a: A) { } | ------ ^ use of generic parameter from outer function diff --git a/src/test/ui/type/type-arg-out-of-scope.stderr b/src/test/ui/type/type-arg-out-of-scope.stderr index 0b6283fbc51e9..4ce34c8063d03 100644 --- a/src/test/ui/type/type-arg-out-of-scope.stderr +++ b/src/test/ui/type/type-arg-out-of-scope.stderr @@ -2,7 +2,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/type-arg-out-of-scope.rs:3:29 | LL | fn foo(x: T) { - | - type parameter from outer function + | - type parameter from outer function being used LL | fn bar(f: Box T>) { } | --- ^ use of generic parameter from outer function | | @@ -12,7 +12,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/type-arg-out-of-scope.rs:3:35 | LL | fn foo(x: T) { - | - type parameter from outer function + | - type parameter from outer function being used LL | fn bar(f: Box T>) { } | --- ^ use of generic parameter from outer function | |