diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 0f58206eee9f3..501a81c903256 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -28,7 +28,7 @@ use rustc_span::{BytePos, Span}; use tracing::debug; use crate::imports::{Import, ImportKind, ImportResolver}; -use crate::late::Rib; +use crate::late::{PatternSource, Rib}; use crate::path_names_to_string; use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, Finalize}; use crate::{HasGenericParams, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot}; @@ -896,25 +896,40 @@ impl<'a> Resolver<'a> { err } ResolutionError::BindingShadowsSomethingUnacceptable { - shadowing_binding_descr, + shadowing_binding, name, participle, article, - shadowed_binding_descr, + shadowed_binding, shadowed_binding_span, } => { + let shadowed_binding_descr = shadowed_binding.descr(); let mut err = struct_span_err!( self.session, span, E0530, "{}s cannot shadow {}s", - shadowing_binding_descr, + shadowing_binding.descr(), shadowed_binding_descr, ); err.span_label( span, format!("cannot be named the same as {} {}", article, shadowed_binding_descr), ); + match (shadowing_binding, shadowed_binding) { + ( + PatternSource::Match, + Res::Def(DefKind::Ctor(CtorOf::Variant | CtorOf::Struct, CtorKind::Fn), _), + ) => { + err.span_suggestion( + span, + "try specify the pattern arguments", + format!("{}(..)", name), + Applicability::Unspecified, + ); + } + _ => (), + } let msg = format!("the {} `{}` is {} here", shadowed_binding_descr, name, participle); err.span_label(shadowed_binding_span, msg); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 640d13ea43547..f37acca3d9f27 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -50,7 +50,7 @@ struct BindingInfo { } #[derive(Copy, Clone, PartialEq, Eq, Debug)] -enum PatternSource { +pub enum PatternSource { Match, Let, For, @@ -64,7 +64,7 @@ enum IsRepeatExpr { } impl PatternSource { - fn descr(self) -> &'static str { + pub fn descr(self) -> &'static str { match self { PatternSource::Match => "match binding", PatternSource::Let => "let binding", @@ -2845,11 +2845,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.report_error( ident.span, ResolutionError::BindingShadowsSomethingUnacceptable { - shadowing_binding_descr: pat_src.descr(), + shadowing_binding: pat_src, name: ident.name, participle: if binding.is_import() { "imported" } else { "defined" }, article: binding.res().article(), - shadowed_binding_descr: binding.res().descr(), + shadowed_binding: binding.res(), shadowed_binding_span: binding.span, }, ); @@ -2861,11 +2861,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.report_error( ident.span, ResolutionError::BindingShadowsSomethingUnacceptable { - shadowing_binding_descr: pat_src.descr(), + shadowing_binding: pat_src, name: ident.name, participle: "defined", article: res.article(), - shadowed_binding_descr: res.descr(), + shadowed_binding: res, shadowed_binding_span: self.r.opt_span(def_id).expect("const parameter defined outside of local crate"), } ); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 28ef384f2c5ad..8968179c92e4b 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -61,7 +61,7 @@ use tracing::debug; use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion}; use imports::{Import, ImportKind, ImportResolver, NameResolution}; -use late::{HasGenericParams, PathSource}; +use late::{HasGenericParams, PathSource, PatternSource}; use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; use crate::access_levels::AccessLevelsVisitor; @@ -230,11 +230,11 @@ enum ResolutionError<'a> { ), /// Error E0530: `X` bindings cannot shadow `Y`s. BindingShadowsSomethingUnacceptable { - shadowing_binding_descr: &'static str, + shadowing_binding: PatternSource, name: Symbol, participle: &'static str, article: &'static str, - shadowed_binding_descr: &'static str, + shadowed_binding: Res, shadowed_binding_span: Span, }, /// Error E0128: generic parameters with a default cannot use forward-declared identifiers. diff --git a/src/test/ui/empty/empty-struct-tuple-pat.stderr b/src/test/ui/empty/empty-struct-tuple-pat.stderr index 9f44747381a9a..8d0f75d204c2f 100644 --- a/src/test/ui/empty/empty-struct-tuple-pat.stderr +++ b/src/test/ui/empty/empty-struct-tuple-pat.stderr @@ -5,7 +5,10 @@ LL | struct Empty2(); | ---------------- the tuple struct `Empty2` is defined here ... LL | Empty2 => () - | ^^^^^^ cannot be named the same as a tuple struct + | ^^^^^^ + | | + | cannot be named the same as a tuple struct + | help: try specify the pattern arguments: `Empty2(..)` error[E0530]: match bindings cannot shadow tuple structs --> $DIR/empty-struct-tuple-pat.rs:25:9 @@ -14,7 +17,10 @@ LL | use empty_struct::*; | --------------- the tuple struct `XEmpty6` is imported here ... LL | XEmpty6 => () - | ^^^^^^^ cannot be named the same as a tuple struct + | ^^^^^^^ + | | + | cannot be named the same as a tuple struct + | help: try specify the pattern arguments: `XEmpty6(..)` error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::Empty4` --> $DIR/empty-struct-tuple-pat.rs:29:9 diff --git a/src/test/ui/pattern/pat-tuple-field-count-cross.stderr b/src/test/ui/pattern/pat-tuple-field-count-cross.stderr index c0cc56aa86e26..d9295746158bb 100644 --- a/src/test/ui/pattern/pat-tuple-field-count-cross.stderr +++ b/src/test/ui/pattern/pat-tuple-field-count-cross.stderr @@ -5,7 +5,10 @@ LL | use declarations_for_tuple_field_count_errors::*; | -------------------------------------------- the tuple struct `Z1` is imported here ... LL | Z1 => {} - | ^^ cannot be named the same as a tuple struct + | ^^ + | | + | cannot be named the same as a tuple struct + | help: try specify the pattern arguments: `Z1(..)` error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0` --> $DIR/pat-tuple-field-count-cross.rs:9:9 diff --git a/src/test/ui/pattern/pat-tuple-overfield.stderr b/src/test/ui/pattern/pat-tuple-overfield.stderr index 856e7918cb75c..54d89e03101dc 100644 --- a/src/test/ui/pattern/pat-tuple-overfield.stderr +++ b/src/test/ui/pattern/pat-tuple-overfield.stderr @@ -5,7 +5,10 @@ LL | struct Z1(); | ------------ the tuple struct `Z1` is defined here ... LL | Z1 => {} - | ^^ cannot be named the same as a tuple struct + | ^^ + | | + | cannot be named the same as a tuple struct + | help: try specify the pattern arguments: `Z1(..)` error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0` --> $DIR/pat-tuple-overfield.rs:52:9 diff --git a/src/test/ui/pattern/pattern-binding-disambiguation.stderr b/src/test/ui/pattern/pattern-binding-disambiguation.stderr index faa0d7c30743b..1529e538b5521 100644 --- a/src/test/ui/pattern/pattern-binding-disambiguation.stderr +++ b/src/test/ui/pattern/pattern-binding-disambiguation.stderr @@ -5,7 +5,10 @@ LL | struct TupleStruct(); | --------------------- the tuple struct `TupleStruct` is defined here ... LL | TupleStruct => {} - | ^^^^^^^^^^^ cannot be named the same as a tuple struct + | ^^^^^^^^^^^ + | | + | cannot be named the same as a tuple struct + | help: try specify the pattern arguments: `TupleStruct(..)` error[E0530]: match bindings cannot shadow tuple variants --> $DIR/pattern-binding-disambiguation.rs:33:9 @@ -14,7 +17,10 @@ LL | use E::*; | ---- the tuple variant `TupleVariant` is imported here ... LL | TupleVariant => {} - | ^^^^^^^^^^^^ cannot be named the same as a tuple variant + | ^^^^^^^^^^^^ + | | + | cannot be named the same as a tuple variant + | help: try specify the pattern arguments: `TupleVariant(..)` error[E0530]: match bindings cannot shadow struct variants --> $DIR/pattern-binding-disambiguation.rs:36:9