diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index a30c25d2663..7619e628d54 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -2783,6 +2783,10 @@ ERROR(requires_generic_params_made_equal,none, ERROR(requires_generic_param_made_equal_to_concrete,none, "same-type requirement makes generic parameter %0 non-generic", (Type)) +ERROR(shadowed_generic_param,none, + "generic parameter %0 shadows generic parameter from outer scope with the same name", + (DeclName)) + ERROR(recursive_decl_reference,none, "%0 %1 references itself", (DescriptiveDeclKind, DeclBaseName)) ERROR(recursive_generic_signature,none, diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index eb4ed46637d..f95ef9b5a88 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -454,11 +454,10 @@ static void diagnoseDuplicateDecls(T &&decls) { other->diagnose(diag::invalid_redecl_prev, other->getName()); }); - // Mark the decl as invalid, unless it's a GenericTypeParamDecl, which is - // expected to maintain its type of GenericTypeParamType. - // This is needed to avoid emitting a duplicate diagnostic when running - // redeclaration checking in the case where the VarDecl is part of the - // enclosing context, e.g `let (x, x) = (0, 0)`. + // Mark the decl as invalid. This is needed to avoid emitting a + // duplicate diagnostic when running redeclaration checking in + // the case where the VarDecl is part of the enclosing context, + // e.g `let (x, x) = (0, 0)`. if (!isa(current)) current->setInvalid(); } @@ -492,7 +491,7 @@ static void checkGenericParams(GenericContext *ownerCtx) { [](Requirement, RequirementRepr *) { return false; }); // Check for duplicate generic parameter names. - diagnoseDuplicateDecls(*genericParams); + TypeChecker::checkShadowedGenericParams(ownerCtx); } template diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index dd7ccfbd755..93c8b4f7449 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -498,6 +498,63 @@ void TypeChecker::checkReferencedGenericParams(GenericContext *dc) { } } +/// Ensure we don't re-declare any generic parameters in the current scope, +/// or shadow a generic parameter from an outer scope. +void TypeChecker::checkShadowedGenericParams(GenericContext *dc) { + // Collect all outer generic parameters for lookup. + llvm::SmallDenseMap genericParamDecls; + for (auto *parentDC = dc->getParent(); parentDC != nullptr; + parentDC = parentDC->getParentForLookup()) { + if (auto *extensionDecl = dyn_cast(parentDC)) { + parentDC = extensionDecl->getExtendedNominal(); + + // This can happen with invalid code. + if (parentDC == nullptr) + return; + } + if (auto *parentDecl = parentDC->getAsDecl()) { + if (auto *parentGeneric = parentDecl->getAsGenericContext()) { + if (auto *genericParamList = parentGeneric->getGenericParams()) { + for (auto *genericParamDecl : genericParamList->getParams()) { + if (genericParamDecl->isOpaqueType()) + continue; + genericParamDecls[genericParamDecl->getName()] = genericParamDecl; + } + } + } + } + } + + for (auto *genericParamDecl : dc->getGenericParams()->getParams()) { + if (genericParamDecl->isOpaqueType() || genericParamDecl->isImplicit()) + continue; + + auto found = genericParamDecls.find(genericParamDecl->getName()); + if (found != genericParamDecls.end()) { + auto *existingParamDecl = found->second; + + if (existingParamDecl->getDeclContext() == dc) { + genericParamDecl->diagnose( + diag::invalid_redecl, + genericParamDecl->getName()); + } else { + genericParamDecl->diagnose( + diag::shadowed_generic_param, + genericParamDecl->getName()).warnUntilSwiftVersion(6); + } + + if (existingParamDecl->getLoc()) { + existingParamDecl->diagnose(diag::invalid_redecl_prev, + existingParamDecl->getName()); + } + + continue; + } + + genericParamDecls[genericParamDecl->getName()] = genericParamDecl; + } +} + /// /// Generic types /// diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 73a44a89470..c6f0049c0de 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -500,6 +500,10 @@ void checkProtocolSelfRequirements(ValueDecl *decl); /// declaration's type, otherwise we have no way to infer them. void checkReferencedGenericParams(GenericContext *dc); +/// Ensure we don't re-declare any generic parameters in the current scope, +/// or shadow a generic parameter from an outer scope. +void checkShadowedGenericParams(GenericContext *dc); + /// Diagnose a requirement failure. /// /// \param errorLoc The location at which an error shall be emitted. diff --git a/test/AutoDiff/Sema/derivative_attr_type_checking.swift b/test/AutoDiff/Sema/derivative_attr_type_checking.swift index 9b4bc05592c..310c1896bad 100644 --- a/test/AutoDiff/Sema/derivative_attr_type_checking.swift +++ b/test/AutoDiff/Sema/derivative_attr_type_checking.swift @@ -496,7 +496,7 @@ extension Struct { } // expected-note @+1 {{candidate subscript does not have a setter}} - subscript(x: T) -> T { x } + subscript(x: U) -> U { x } } extension Struct where T: Differentiable & AdditiveArithmetic { @derivative(of: subscript.get) @@ -534,14 +534,14 @@ extension Struct where T: Differentiable & AdditiveArithmetic { } @derivative(of: subscript(_:).get, wrt: self) - func vjpSubscriptGenericGetter(x: T) -> (value: T, pullback: (T.TangentVector) -> TangentVector) { + func vjpSubscriptGenericGetter(x: U) -> (value: U, pullback: (U.TangentVector) -> TangentVector) { return (x, { _ in .zero }) } // expected-error @+2 {{a derivative already exists for '_'}} // expected-note @-6 {{other attribute declared here}} @derivative(of: subscript(_:), wrt: self) - func vjpSubscriptGeneric(x: T) -> (value: T, pullback: (T.TangentVector) -> TangentVector) { + func vjpSubscriptGeneric(x: U) -> (value: U, pullback: (U.TangentVector) -> TangentVector) { return (x, { _ in .zero }) } @@ -576,8 +576,8 @@ extension Struct where T: Differentiable & AdditiveArithmetic { // Error: original subscript has no setter. // expected-error @+1 {{referenced declaration 'subscript(_:)' could not be resolved}} @derivative(of: subscript(_:).set, wrt: self) - mutating func vjpSubscriptGeneric_NoSetter(x: T) -> ( - value: T, pullback: (T.TangentVector) -> TangentVector + mutating func vjpSubscriptGeneric_NoSetter(x: U) -> ( + value: U, pullback: (U.TangentVector) -> TangentVector ) { return (x, { _ in .zero }) } diff --git a/test/Compatibility/accessibility.swift b/test/Compatibility/accessibility.swift index 32a8f0e7039..f71c686646d 100644 --- a/test/Compatibility/accessibility.swift +++ b/test/Compatibility/accessibility.swift @@ -516,8 +516,8 @@ public struct PublicGenericIPReq where T: PrivateProto {} // e public func genericFunc(_: T) {} // expected-error {{function cannot be declared public because its generic parameter uses an internal type}} {} public class GenericClass { // expected-error {{generic class cannot be declared public because its generic parameter uses an internal type}} - public init(_: T) {} // expected-error {{initializer cannot be declared public because its generic parameter uses a private type}} - public func genericMethod(_: T) {} // expected-error {{instance method cannot be declared public because its generic parameter uses a private type}} + public init(_: U) {} // expected-error {{initializer cannot be declared public because its generic parameter uses a private type}} + public func genericMethod(_: U) {} // expected-error {{instance method cannot be declared public because its generic parameter uses a private type}} } public enum GenericEnum { // expected-error {{generic enum cannot be declared public because its generic parameter uses an internal type}} case A diff --git a/test/Constraints/generics.swift b/test/Constraints/generics.swift index 1bec0aa3752..0bd6e7c78c8 100644 --- a/test/Constraints/generics.swift +++ b/test/Constraints/generics.swift @@ -508,11 +508,12 @@ public struct S5 { // rdar://problem/24329052 - QoI: call argument archetypes not lining up leads to ambiguity errors -struct S_24329052 { // expected-note {{generic parameter 'T' of generic struct 'S_24329052' declared here}} +struct S_24329052 { // expected-note {{generic parameter 'T' of generic struct 'S_24329052' declared here}} expected-note {{'T' previously declared here}} var foo: (T) -> Void // expected-note@+1 {{generic parameter 'T' of instance method 'bar(_:)' declared here}} func bar(_ v: T) { foo(v) } // expected-error@-1 {{cannot convert value of type 'T' (generic parameter of instance method 'bar(_:)') to expected argument type 'T' (generic parameter of generic struct 'S_24329052')}} + // expected-warning@-2 {{generic parameter 'T' shadows generic parameter from outer scope with the same name; this is an error in Swift 6}} } extension Sequence { @@ -943,7 +944,7 @@ do { struct Outer { struct Inner {} - func container() -> Inner { + func container() -> Inner { return Inner() } } diff --git a/test/Constraints/issue-53296.swift b/test/Constraints/issue-53296.swift index c54b67b9949..312b5f877fa 100644 --- a/test/Constraints/issue-53296.swift +++ b/test/Constraints/issue-53296.swift @@ -20,7 +20,7 @@ final class ViewController { extension ViewController: ViewDataSource where T == String { // expected-note@-1 {{requirement from conditional conformance of 'ViewController' to 'ViewDataSource'}} - func foo() -> [T] { + func foo() -> [U] { return [] } } diff --git a/test/Constraints/members.swift b/test/Constraints/members.swift index 7eb6bda78d0..b3f2be50864 100644 --- a/test/Constraints/members.swift +++ b/test/Constraints/members.swift @@ -553,8 +553,8 @@ func rdar_48114578() { struct S { var value: T - static func valueOf(_ v: T) -> S { - return S(value: v) + static func valueOf(_ v: U) -> S { + return S(value: v) } } diff --git a/test/Constraints/pack-expansion-expressions.swift b/test/Constraints/pack-expansion-expressions.swift index 5a75e895fa4..87b1e870aae 100644 --- a/test/Constraints/pack-expansion-expressions.swift +++ b/test/Constraints/pack-expansion-expressions.swift @@ -219,8 +219,8 @@ do { } do { - func testRef() -> (repeat each T, String) { fatalError() } - func testResult() -> (repeat each T) { fatalError() } + func testRef() -> (repeat each U, String) { fatalError() } + func testResult() -> (repeat each U) { fatalError() } func experiment1() -> (repeat each U, String) { testResult() // Ok diff --git a/test/Constraints/super_method.swift b/test/Constraints/super_method.swift index 403eedc3edb..cab55b71dfb 100644 --- a/test/Constraints/super_method.swift +++ b/test/Constraints/super_method.swift @@ -43,7 +43,7 @@ class X { } class Y : X { - func otherMethod(_ x: Int, y: U) { + func otherMethod(_ x: Int, y: V) { super.method(x, y: y) } } diff --git a/test/Generics/shadowed_generic_params.swift b/test/Generics/shadowed_generic_params.swift new file mode 100644 index 00000000000..a902325ba2e --- /dev/null +++ b/test/Generics/shadowed_generic_params.swift @@ -0,0 +1,17 @@ +// RUN: %target-typecheck-verify-swift + +struct Outer { // expected-note 2{{'T' previously declared here}} + struct Inner { // expected-note 2{{'V' previously declared here}} + func foo(_: T) {} // expected-warning {{generic parameter 'T' shadows generic parameter from outer scope with the same name; this is an error in Swift 6}} + func bar(_: V) {} // expected-warning {{generic parameter 'V' shadows generic parameter from outer scope with the same name; this is an error in Swift 6}} + } +} + +extension Outer.Inner { + func baz(_: T) {} // expected-warning {{generic parameter 'T' shadows generic parameter from outer scope with the same name; this is an error in Swift 6}} + func quux(_: V) {} // expected-warning {{generic parameter 'V' shadows generic parameter from outer scope with the same name; this is an error in Swift 6}} +} + +extension Sequence { + func bing(_: Self) {} // expected-warning {{generic parameter 'Self' shadows generic parameter from outer scope with the same name; this is an error in Swift 6}} +} \ No newline at end of file diff --git a/test/Sema/accessibility.swift b/test/Sema/accessibility.swift index 14e23f8ac03..89fa4a16c72 100644 --- a/test/Sema/accessibility.swift +++ b/test/Sema/accessibility.swift @@ -935,9 +935,9 @@ package struct PackageGenericIPReq where T: PrivateProto {} // public func genericFunc(_: T) {} // expected-error {{function cannot be declared public because its generic parameter uses an internal type}} {} public func genericFuncPackage(_: T) {} // expected-error {{function cannot be declared public because its generic parameter uses a package type}} {} public class GenericClass { // expected-error {{generic class cannot be declared public because its generic parameter uses an internal type}} - public init(_: T) {} // expected-error {{initializer cannot be declared public because its generic parameter uses a private type}} - public func genericMethod(_: T) {} // expected-error {{instance method cannot be declared public because its generic parameter uses a private type}} - public func genericMethodPackage(_: T) {} // expected-error {{instance method cannot be declared public because its generic parameter uses a package type}} + public init(_: U) {} // expected-error {{initializer cannot be declared public because its generic parameter uses a private type}} + public func genericMethod(_: U) {} // expected-error {{instance method cannot be declared public because its generic parameter uses a private type}} + public func genericMethodPackage(_: U) {} // expected-error {{instance method cannot be declared public because its generic parameter uses a package type}} } public enum GenericEnum { // expected-error {{generic enum cannot be declared public because its generic parameter uses an internal type}} case A @@ -948,8 +948,8 @@ public enum GenericEnumPackage { // expected-error {{generic en package func packageGenericFunc(_: T) {} // expected-error {{function cannot be declared package because its generic parameter uses an internal type}} {} package class PackageGenericClassT { // expected-error {{generic class cannot be declared package because its generic parameter uses an internal type}} - package init(_: T) {} // expected-error {{initializer cannot be declared package because its generic parameter uses a private type}} - package func packageGenericMethod(_: T) {} // expected-error {{instance method cannot be declared package because its generic parameter uses a private type}} + package init(_: U) {} // expected-error {{initializer cannot be declared package because its generic parameter uses a private type}} + package func packageGenericMethod(_: U) {} // expected-error {{instance method cannot be declared package because its generic parameter uses a private type}} } package enum PackageGenericEnumT { // expected-error {{generic enum cannot be declared package because its generic parameter uses an internal type}} case A diff --git a/test/Sema/moveonly_illegal_types.swift b/test/Sema/moveonly_illegal_types.swift index e239b443139..b44e947a01a 100644 --- a/test/Sema/moveonly_illegal_types.swift +++ b/test/Sema/moveonly_illegal_types.swift @@ -39,7 +39,7 @@ enum Maybe { } struct CerebralValley { - struct GenericBro {} + struct GenericBro {} struct TechBro {} } diff --git a/test/attr/attr_override.swift b/test/attr/attr_override.swift index 81310ec8887..870e6010cd1 100644 --- a/test/attr/attr_override.swift +++ b/test/attr/attr_override.swift @@ -516,7 +516,7 @@ protocol Protocol2 {} // Base class is generic, derived class is concrete. class Base1 { - func foo(arg: T) {} + func foo(arg: U) {} } class Derived1: Base1 { override func foo(arg: T) {} // Ok? @@ -528,14 +528,14 @@ class Base2 { func foo() {} } class Derived2: Base2 { - override func foo(arg: T) {} // expected-error {{method does not override any method from its superclass}} + override func foo(arg: U) {} // expected-error {{method does not override any method from its superclass}} } // Base class generic w/ method generic, derived class generic w/ method not // generic. class Base3 { - func foo(arg: T) {} + func foo(arg: U) {} } class Derived3: Base3 { override func foo() {} // expected-error {{method does not override any method from its superclass}} @@ -545,10 +545,10 @@ class Derived3: Base3 { // but different requirement. class Base4 { - func foo(arg: T) {} + func foo(arg: U) {} } class Derived4: Base4 { - override func foo(arg: T) {} // expected-error {{method does not override any method from its superclass}} + override func foo(arg: U) {} // expected-error {{method does not override any method from its superclass}} } // Base class not generic w/ method generic, derived class not generic w/ method @@ -578,7 +578,7 @@ class Base7 { func foo(arg: T) {} } class Derived7: Base7 { - override func foo(arg: T) {} // expected-error {{method does not override any method from its superclass}} + override func foo(arg: U) {} // expected-error {{method does not override any method from its superclass}} } // Override with orthogonal requirement on contextual generic parameter. diff --git a/test/attr/attr_rethrows_protocol.swift b/test/attr/attr_rethrows_protocol.swift index 5f0d32f25b5..a2f31c74064 100644 --- a/test/attr/attr_rethrows_protocol.swift +++ b/test/attr/attr_rethrows_protocol.swift @@ -175,7 +175,7 @@ struct ConformsToSimpleThrowsClosure : SimpleThrowsClosu try t.source() } - func doIt2(_: T) rethrows {} + func doIt2(_: U) rethrows {} // expected-note@-1 {{candidate is 'rethrows' via a conformance, but the protocol requirement is not from a '@rethrows' protocol}} } diff --git a/test/decl/ext/generic.swift b/test/decl/ext/generic.swift index 753f87b2131..052360e79f0 100644 --- a/test/decl/ext/generic.swift +++ b/test/decl/ext/generic.swift @@ -23,7 +23,7 @@ extension X { // expected-error@-1 {{extensions must not contain stored properties}} static let x = 0 func f() -> Int {} - class C {} + class C {} } typealias GGG = X diff --git a/test/decl/nested/type_in_extension.swift b/test/decl/nested/type_in_extension.swift index dd6423d2f32..e2c0d5c92d1 100644 --- a/test/decl/nested/type_in_extension.swift +++ b/test/decl/nested/type_in_extension.swift @@ -4,7 +4,7 @@ struct G {} extension G { struct H { - func usesBoth(t: T, u: U) -> (T, U) {} + func usesBoth(t: T1, u: U1) -> (T1, U1) {} } } diff --git a/test/decl/nested/type_in_function.swift b/test/decl/nested/type_in_function.swift index 3908dad9394..f5993852f21 100644 --- a/test/decl/nested/type_in_function.swift +++ b/test/decl/nested/type_in_function.swift @@ -85,8 +85,8 @@ class OuterGenericClass { init(t: T) { super.init(); self.t = t } } - class InnerGenericClass : OuterGenericClass // expected-error {{type 'InnerGenericClass' cannot be nested in generic function 'genericFunction'}} - where U : Racoon, U.Stripes == T { + class InnerGenericClass : OuterGenericClass // expected-error {{type 'InnerGenericClass' cannot be nested in generic function 'genericFunction'}} + where V : Racoon, V.Stripes == T { let t: T init(t: T) { super.init(); self.t = t } @@ -130,7 +130,7 @@ func genericFunction(t: T) { class First : Second.UnknownType { } // expected-error@-1 {{type 'First' cannot be nested in generic function 'genericFunction(t:)'}} // expected-error@-2 {{'UnknownType' is not a member type of generic class 'type_in_function.Second'}} - class Second : Second { } // expected-note{{'Second' declared here}} + class Second : Second { } // expected-note{{'Second' declared here}} // expected-error@-1 {{type 'Second' cannot be nested in generic function 'genericFunction(t:)'}} // expected-error@-2 {{'Second' inherits from itself}} } diff --git a/test/decl/nested/type_in_type.swift b/test/decl/nested/type_in_type.swift index 1a8ef97e6ce..76efd11a34b 100644 --- a/test/decl/nested/type_in_type.swift +++ b/test/decl/nested/type_in_type.swift @@ -106,8 +106,8 @@ class OuterGenericClass { } class Middle { - class Inner1 {} - class Inner2 : Middle where T: Inner1 {} + class Inner1 {} + class Inner2 : Middle where U: Inner1 {} } } diff --git a/test/decl/overload.swift b/test/decl/overload.swift index 306271be9b6..544e6eb2826 100644 --- a/test/decl/overload.swift +++ b/test/decl/overload.swift @@ -204,9 +204,9 @@ struct X5 { static func u() {} typealias v = String - func foo(_ t: t) { - let t = t - _ = t + func foo(_ w: w) { + let w = w + _ = w } } diff --git a/test/decl/protocol/existential_member_accesses_self_assoctype.swift b/test/decl/protocol/existential_member_accesses_self_assoctype.swift index 8f5ccb5057e..6d258cbcd9c 100644 --- a/test/decl/protocol/existential_member_accesses_self_assoctype.swift +++ b/test/decl/protocol/existential_member_accesses_self_assoctype.swift @@ -6,7 +6,7 @@ struct Struct { class Inner {} - struct InnerGeneric {} + struct InnerGeneric {} } class Class {} diff --git a/test/decl/typealias/generic.swift b/test/decl/typealias/generic.swift index e96eea5acf4..1935ddeed77 100644 --- a/test/decl/typealias/generic.swift +++ b/test/decl/typealias/generic.swift @@ -197,7 +197,7 @@ class GenericClass { } // Stupid corner case -- underlying type is not dependent - typealias NotDependent = Int + typealias NotDependent = Int func misleadingCode(_: NotDependent) {} } @@ -367,7 +367,7 @@ typealias Id = T extension Id {} // expected-error {{non-nominal type 'Id' cannot be extended}} class OuterGeneric { - typealias Alias = AnotherGeneric + typealias Alias = AnotherGeneric // expected-note@-1 {{generic type 'Alias' declared here}} class InnerNonGeneric : Alias {} // expected-error@-1 {{reference to generic type 'OuterGeneric.Alias' requires arguments in <...>}} diff --git a/validation-test/Sema/result_builder_buildBlock_resolution.swift b/validation-test/Sema/result_builder_buildBlock_resolution.swift index f276d6defed..80a02ade884 100644 --- a/validation-test/Sema/result_builder_buildBlock_resolution.swift +++ b/validation-test/Sema/result_builder_buildBlock_resolution.swift @@ -13,12 +13,12 @@ struct ActionLookup { } @resultBuilder -enum ActionLookupBuilder { - static func buildBlock(_ components: [ActionLookup]...) -> ActionLookup { +enum ActionLookupBuilder { // expected-note 3{{'Identifier' previously declared here}} + static func buildBlock(_ components: [ActionLookup]...) -> ActionLookup { // expected-warning {{generic parameter 'Identifier' shadows generic parameter from outer scope with the same name; this is an error in Swift 6}} fatalError() } - static func buildBlock(_ components: [ActionLookup]...) -> [ActionLookup] { + static func buildBlock(_ components: [ActionLookup]...) -> [ActionLookup] { // expected-warning {{generic parameter 'Identifier' shadows generic parameter from outer scope with the same name; this is an error in Swift 6}} [] } @@ -26,7 +26,7 @@ enum ActionLookupBuilder { [] } - static func buildOptional(_ component: [ActionLookup]?) -> [ActionLookup] { + static func buildOptional(_ component: [ActionLookup]?) -> [ActionLookup] { // expected-warning {{generic parameter 'Identifier' shadows generic parameter from outer scope with the same name; this is an error in Swift 6}} [] } }