From f70c90c677e98f5267cc7c66fadef76e269097cb Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 11 Aug 2019 18:09:50 +0100 Subject: [PATCH] Move type parameter shadowing errors to resolve For some reason type checking did this. Further it didn't consider hygiene. --- src/librustc_resolve/diagnostics.rs | 14 ++++--- src/librustc_resolve/error_codes.rs | 16 ++++++-- src/librustc_resolve/late.rs | 31 +++++++++++++++ src/librustc_resolve/lib.rs | 2 +- src/librustc_typeck/check/wfcheck.rs | 38 ------------------- src/librustc_typeck/error_codes.rs | 17 +-------- .../duplicate/duplicate-type-parameter.stderr | 14 +++---- src/test/ui/error-codes/E0194.rs | 2 +- src/test/ui/error-codes/E0194.stderr | 8 ++-- src/test/ui/error-codes/E0403.stderr | 2 +- .../shadowing.rs | 16 ++++---- .../shadowing.stderr | 21 +++++++--- .../ui/shadowed/shadowed-type-parameter.rs | 6 +-- .../shadowed/shadowed-type-parameter.stderr | 30 +++++++-------- 14 files changed, 108 insertions(+), 109 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index afdcec19d8ef6..b79e0c2bd3b26 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -169,12 +169,14 @@ impl<'a> Resolver<'a> { err } ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => { - let mut err = struct_span_err!(self.session, - span, - E0403, - "the name `{}` is already used for a generic \ - parameter in this list of generic parameters", - name); + let mut err = struct_span_err!( + self.session, + span, + E0403, + "the name `{}` is already used for a generic \ + parameter in this item's generic parameters", + name, + ); err.span_label(span, "already used"); err.span_label(first_use_span, format!("first use of `{}`", name)); err diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index e01f53786edab..1faaf97e981c1 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -526,15 +526,25 @@ Some type parameters have the same name. Erroneous code example: ```compile_fail,E0403 -fn foo(s: T, u: T) {} // error: the name `T` is already used for a type - // parameter in this type parameter list +fn f(s: T, u: T) {} // error: the name `T` is already used for a generic + // parameter in this item's generic parameters ``` Please verify that none of the type parameters are misspelled, and rename any clashing parameters. Example: ``` -fn foo(s: T, u: Y) {} // ok! +fn f(s: T, u: Y) {} // ok! +``` + +Type parameters in an associated item also cannot shadow parameters from the +containing item: + +```compile_fail,E0403 +trait Foo { + fn do_something(&self) -> T; + fn do_something_else(&self, bar: T); +} ``` "##, diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index d8bd86699b7af..e15d02a9f7ec7 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -111,6 +111,24 @@ crate enum RibKind<'a> { TyParamAsConstParamTy, } +impl RibKind<'_> { + // Whether this rib kind contains generic parameters, as opposed to local + // variables. + crate fn contains_params(&self) -> bool { + match self { + NormalRibKind + | FnItemRibKind + | ConstantItemRibKind + | ModuleRibKind(_) + | MacroDefinition(_) => false, + AssocItemRibKind + | ItemRibKind + | ForwardTyParamBanRibKind + | TyParamAsConstParamTy => true, + } + } +} + /// A single local scope. /// /// A rib represents a scope names can live in. Note that these appear in many places, not just @@ -798,6 +816,19 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { let mut function_type_rib = Rib::new(rib_kind); let mut function_value_rib = Rib::new(rib_kind); let mut seen_bindings = FxHashMap::default(); + // We also can't shadow bindings from the parent item + if let AssocItemRibKind = rib_kind { + let mut add_bindings_for_ns = |ns| { + let parent_rib = self.ribs[ns].iter() + .rfind(|rib| if let ItemRibKind = rib.kind { true } else { false }) + .expect("associated item outside of an item"); + seen_bindings.extend( + parent_rib.bindings.iter().map(|(ident, _)| (*ident, ident.span)), + ); + }; + add_bindings_for_ns(ValueNS); + add_bindings_for_ns(TypeNS); + } for param in &generics.params { match param.kind { GenericParamKind::Lifetime { .. } => {} diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 12c4f5bfe8e61..984473d781e62 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1499,7 +1499,7 @@ impl<'a> Resolver<'a> { debug!("walk rib\n{:?}", ribs[i].bindings); // Use the rib kind to determine whether we are resolving parameters // (modern hygiene) or local variables (legacy hygiene). - let rib_ident = if let AssocItemRibKind | ItemRibKind = ribs[i].kind { + let rib_ident = if ribs[i].kind.contains_params() { modern_ident } else { ident diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index b2c0e34d6fad7..28a1ccda4d841 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -203,7 +203,6 @@ fn check_associated_item( fcx.register_wf_obligation(ty, span, code.clone()); } ty::AssocKind::Method => { - reject_shadowing_parameters(fcx.tcx, item.def_id); let sig = fcx.tcx.fn_sig(item.def_id); let sig = fcx.normalize_associated_types_in(span, &sig); check_fn_or_method(tcx, fcx, span, sig, @@ -998,34 +997,6 @@ fn report_bivariance(tcx: TyCtxt<'_>, span: Span, param_name: ast::Name) { err.emit(); } -fn reject_shadowing_parameters(tcx: TyCtxt<'_>, def_id: DefId) { - let generics = tcx.generics_of(def_id); - let parent = tcx.generics_of(generics.parent.unwrap()); - let impl_params: FxHashMap<_, _> = parent.params.iter().flat_map(|param| match param.kind { - GenericParamDefKind::Lifetime => None, - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { - Some((param.name, param.def_id)) - } - }).collect(); - - for method_param in &generics.params { - // Shadowing is checked in `resolve_lifetime`. - if let GenericParamDefKind::Lifetime = method_param.kind { - continue - } - if impl_params.contains_key(&method_param.name) { - // Tighten up the span to focus on only the shadowing type. - let type_span = tcx.def_span(method_param.def_id); - - // The expectation here is that the original trait declaration is - // local so it should be okay to just unwrap everything. - let trait_def_id = impl_params[&method_param.name]; - let trait_decl_span = tcx.def_span(trait_def_id); - error_194(tcx, type_span, trait_decl_span, &method_param.name.as_str()[..]); - } - } -} - /// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that /// aren't true. fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) { @@ -1152,12 +1123,3 @@ fn error_392( err.span_label(span, "unused parameter"); err } - -fn error_194(tcx: TyCtxt<'_>, span: Span, trait_decl_span: Span, name: &str) { - struct_span_err!(tcx.sess, span, E0194, - "type parameter `{}` shadows another type parameter of the same name", - name) - .span_label(span, "shadows another type parameter") - .span_label(trait_decl_span, format!("first `{}` declared here", name)) - .emit(); -} diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 90118a9f191d9..ca9ce3d22b5cb 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -1718,22 +1718,6 @@ Since we know for certain that `Wrapper` implements `Clone`, there's no reason to also specify it in a `where` clause. "##, -E0194: r##" -A type parameter was declared which shadows an existing one. An example of this -error: - -```compile_fail,E0194 -trait Foo { - fn do_something(&self) -> T; - fn do_something_else(&self, bar: T); -} -``` - -In this example, the trait `Foo` and the trait method `do_something_else` both -define a type parameter `T`. This is not allowed: if the method wishes to -define a type parameter, it must use a different name for it. -"##, - E0195: r##" Your method's lifetime parameters do not match the trait declaration. Erroneous code example: @@ -4837,6 +4821,7 @@ register_diagnostics! { // E0188, // can not cast an immutable reference to a mutable pointer // E0189, // deprecated: can only cast a boxed pointer to a boxed object // E0190, // deprecated: can only cast a &-pointer to an &-object +// E0194, // merged into E0403 // E0196, // cannot determine a type for this closure E0203, // type parameter has more than one relaxed default bound, // and only one is supported diff --git a/src/test/ui/duplicate/duplicate-type-parameter.stderr b/src/test/ui/duplicate/duplicate-type-parameter.stderr index 8606479ff6863..6754574f0b953 100644 --- a/src/test/ui/duplicate/duplicate-type-parameter.stderr +++ b/src/test/ui/duplicate/duplicate-type-parameter.stderr @@ -1,4 +1,4 @@ -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:1:12 | LL | type Foo = Option; @@ -6,7 +6,7 @@ LL | type Foo = Option; | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:4:14 | LL | struct Bar(T); @@ -14,7 +14,7 @@ LL | struct Bar(T); | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:7:14 | LL | struct Baz { @@ -22,7 +22,7 @@ LL | struct Baz { | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:12:12 | LL | enum Boo { @@ -30,7 +30,7 @@ LL | enum Boo { | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:18:11 | LL | fn quux(x: T) {} @@ -38,7 +38,7 @@ LL | fn quux(x: T) {} | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:21:13 | LL | trait Qux {} @@ -46,7 +46,7 @@ LL | trait Qux {} | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:24:8 | LL | impl Qux for Option {} diff --git a/src/test/ui/error-codes/E0194.rs b/src/test/ui/error-codes/E0194.rs index 71eff0e7465a5..8a43f38fcfd5f 100644 --- a/src/test/ui/error-codes/E0194.rs +++ b/src/test/ui/error-codes/E0194.rs @@ -1,7 +1,7 @@ trait Foo { fn do_something(&self) -> T; fn do_something_else(&self, bar: T); - //~^ ERROR E0194 + //~^ ERROR E0403 } fn main() { diff --git a/src/test/ui/error-codes/E0194.stderr b/src/test/ui/error-codes/E0194.stderr index ab4918a4e27d5..f2c908eea0bb0 100644 --- a/src/test/ui/error-codes/E0194.stderr +++ b/src/test/ui/error-codes/E0194.stderr @@ -1,12 +1,12 @@ -error[E0194]: type parameter `T` shadows another type parameter of the same name +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/E0194.rs:3:26 | LL | trait Foo { - | - first `T` declared here + | - first use of `T` LL | fn do_something(&self) -> T; LL | fn do_something_else(&self, bar: T); - | ^ shadows another type parameter + | ^ already used error: aborting due to previous error -For more information about this error, try `rustc --explain E0194`. +For more information about this error, try `rustc --explain E0403`. diff --git a/src/test/ui/error-codes/E0403.stderr b/src/test/ui/error-codes/E0403.stderr index 2bd7de6c24614..d76a58a7c80de 100644 --- a/src/test/ui/error-codes/E0403.stderr +++ b/src/test/ui/error-codes/E0403.stderr @@ -1,4 +1,4 @@ -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/E0403.rs:1:11 | LL | fn foo(s: T, u: T) {} diff --git a/src/test/ui/rfc1598-generic-associated-types/shadowing.rs b/src/test/ui/rfc1598-generic-associated-types/shadowing.rs index 03492631cb7c8..f5197fd01bfd6 100644 --- a/src/test/ui/rfc1598-generic-associated-types/shadowing.rs +++ b/src/test/ui/rfc1598-generic-associated-types/shadowing.rs @@ -1,12 +1,9 @@ +#![allow(incomplete_features)] #![feature(generic_associated_types)] -//FIXME(#44265): The lifetime shadowing and type parameter shadowing -// should cause an error. Now it compiles (erroneously) and this will be addressed -// by a future PR. Then remove the following: -// build-pass (FIXME(62277): could be check-pass?) - trait Shadow<'a> { - type Bar<'a>; // Error: shadowed lifetime + //FIXME(#44265): The lifetime parameter shadowing should cause an error. + type Bar<'a>; } trait NoShadow<'a> { @@ -14,11 +11,12 @@ trait NoShadow<'a> { } impl<'a> NoShadow<'a> for &'a u32 { - type Bar<'a> = i32; // Error: shadowed lifetime + //FIXME(#44265): The lifetime parameter shadowing should cause an error. + type Bar<'a> = i32; } trait ShadowT { - type Bar; // Error: shadowed type parameter + type Bar; //~ ERROR the name `T` is already used } trait NoShadowT { @@ -26,7 +24,7 @@ trait NoShadowT { } impl NoShadowT for Option { - type Bar = i32; // Error: shadowed type parameter + type Bar = i32; //~ ERROR the name `T` is already used } fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr b/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr index 9526df258c497..a06c635084525 100644 --- a/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr @@ -1,8 +1,19 @@ -warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash - --> $DIR/shadowing.rs:1:12 +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowing.rs:19:14 | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait ShadowT { + | - first use of `T` +LL | type Bar; + | ^ already used + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowing.rs:27:14 | - = note: `#[warn(incomplete_features)]` on by default +LL | impl NoShadowT for Option { + | - first use of `T` +LL | type Bar = i32; + | ^ already used + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0403`. diff --git a/src/test/ui/shadowed/shadowed-type-parameter.rs b/src/test/ui/shadowed/shadowed-type-parameter.rs index ba9f3abcf7ade..e74620f8900c0 100644 --- a/src/test/ui/shadowed/shadowed-type-parameter.rs +++ b/src/test/ui/shadowed/shadowed-type-parameter.rs @@ -6,7 +6,7 @@ struct Foo(T); impl Foo { fn shadow_in_method(&self) {} - //~^ ERROR type parameter `T` shadows another type parameter + //~^ ERROR the name `T` is already used fn not_shadow_in_item(&self) { struct Bar(T,U); // not a shadow, separate item @@ -18,10 +18,10 @@ trait Bar { fn dummy(&self) -> T; fn shadow_in_required(&self); - //~^ ERROR type parameter `T` shadows another type parameter + //~^ ERROR the name `T` is already used fn shadow_in_provided(&self) {} - //~^ ERROR type parameter `T` shadows another type parameter + //~^ ERROR the name `T` is already used fn not_shadow_in_required(&self); fn not_shadow_in_provided(&self) {} diff --git a/src/test/ui/shadowed/shadowed-type-parameter.stderr b/src/test/ui/shadowed/shadowed-type-parameter.stderr index 6b4d1fae3de18..0ea82f983f1a7 100644 --- a/src/test/ui/shadowed/shadowed-type-parameter.stderr +++ b/src/test/ui/shadowed/shadowed-type-parameter.stderr @@ -1,29 +1,29 @@ -error[E0194]: type parameter `T` shadows another type parameter of the same name +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowed-type-parameter.rs:8:25 + | +LL | impl Foo { + | - first use of `T` +LL | fn shadow_in_method(&self) {} + | ^ already used + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/shadowed-type-parameter.rs:20:27 | LL | trait Bar { - | - first `T` declared here + | - first use of `T` ... LL | fn shadow_in_required(&self); - | ^ shadows another type parameter + | ^ already used -error[E0194]: type parameter `T` shadows another type parameter of the same name +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/shadowed-type-parameter.rs:23:27 | LL | trait Bar { - | - first `T` declared here + | - first use of `T` ... LL | fn shadow_in_provided(&self) {} - | ^ shadows another type parameter - -error[E0194]: type parameter `T` shadows another type parameter of the same name - --> $DIR/shadowed-type-parameter.rs:8:25 - | -LL | impl Foo { - | - first `T` declared here -LL | fn shadow_in_method(&self) {} - | ^ shadows another type parameter + | ^ already used error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0194`. +For more information about this error, try `rustc --explain E0403`.