mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #42257 from hborla/concrete-generic-params
[RequirementMachine] Diagnose type parameters that are made concrete by a same-type requirement.
This commit is contained in:
@@ -413,6 +413,18 @@ RequirementSignatureRequestRQM::evaluate(Evaluator &evaluator,
|
||||
machine->computeRequirementDiagnostics(errors, proto->getLoc());
|
||||
diagnoseRequirementErrors(ctx, errors,
|
||||
AllowConcreteTypePolicy::NestedAssocTypes);
|
||||
|
||||
for (auto *protocol : machine->System.getProtocols()) {
|
||||
auto selfType = protocol->getSelfInterfaceType();
|
||||
auto concrete = machine->getConcreteType(selfType,
|
||||
machine->getGenericParams(),
|
||||
protocol);
|
||||
if (!concrete || concrete->hasError())
|
||||
continue;
|
||||
|
||||
protocol->diagnose(diag::requires_generic_param_made_equal_to_concrete,
|
||||
selfType);
|
||||
}
|
||||
}
|
||||
|
||||
if (!machine->getErrors()) {
|
||||
@@ -859,8 +871,6 @@ InferredGenericSignatureRequestRQM::evaluate(
|
||||
: AllowConcreteTypePolicy::AssocTypes);
|
||||
}
|
||||
|
||||
// FIXME: Handle allowConcreteGenericParams
|
||||
|
||||
// Don't bother splitting concrete equivalence classes if there were invalid
|
||||
// requirements, because the signature is not going to be ABI anyway.
|
||||
if (!errorFlags.contains(GenericSignatureErrorFlags::HasInvalidRequirements)) {
|
||||
@@ -887,6 +897,28 @@ InferredGenericSignatureRequestRQM::evaluate(
|
||||
std::move(machine));
|
||||
}
|
||||
|
||||
if (!allowConcreteGenericParams &&
|
||||
ctx.LangOpts.RequirementMachineInferredSignatures ==
|
||||
RequirementMachineMode::Enabled) {
|
||||
for (auto genericParam : result.getInnermostGenericParams()) {
|
||||
auto canonical = result.getCanonicalTypeInContext(genericParam);
|
||||
|
||||
if (canonical->hasError() || canonical->isEqual(genericParam))
|
||||
continue;
|
||||
|
||||
if (canonical->isTypeParameter()) {
|
||||
ctx.Diags.diagnose(loc, diag::requires_generic_params_made_equal,
|
||||
genericParam, result->getSugaredType(canonical))
|
||||
.warnUntilSwiftVersion(6);
|
||||
} else {
|
||||
ctx.Diags.diagnose(loc,
|
||||
diag::requires_generic_param_made_equal_to_concrete,
|
||||
genericParam)
|
||||
.warnUntilSwiftVersion(6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!errorFlags.contains(GenericSignatureErrorFlags::HasInvalidRequirements)) {
|
||||
// Check invariants.
|
||||
result.verify();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// RUN: %target-typecheck-verify-swift -swift-version 4 -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
|
||||
// RUN: %target-typecheck-verify-swift -swift-version 4.2 -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
|
||||
// RUN: %target-typecheck-verify-swift -swift-version 4
|
||||
// RUN: %target-typecheck-verify-swift -swift-version 4.2
|
||||
|
||||
public protocol PublicProto {
|
||||
func publicReq()
|
||||
@@ -503,7 +503,7 @@ struct DefaultGeneric<T> {}
|
||||
|
||||
struct DefaultGenericPrivate<T: PrivateProto> {} // expected-error {{generic struct must be declared private or fileprivate because its generic parameter uses a private type}}
|
||||
struct DefaultGenericPrivate2<T: PrivateClass> {} // expected-error {{generic struct must be declared private or fileprivate because its generic parameter uses a private type}}
|
||||
struct DefaultGenericPrivateReq<T> where T == PrivateClass {} // expected-error {{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
struct DefaultGenericPrivateReq<T> where T == PrivateClass {} // expected-warning {{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
// expected-error@-1 {{generic struct must be declared private or fileprivate because its generic requirement uses a private type}}
|
||||
struct DefaultGenericPrivateReq2<T> where T: PrivateProto {} // expected-error {{generic struct must be declared private or fileprivate because its generic requirement uses a private type}}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ func foo<T>(_ x: T) -> Derived where T: Base<Int>, T: Derived {
|
||||
return x
|
||||
}
|
||||
|
||||
// FIXME: There is no explicit same-type requirement written.
|
||||
// expected-warning@+1{{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
func bar<T, U>(_ x: U, y: T) -> (Derived, Int) where U: Base<T>, U: Derived {
|
||||
return (x, y)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
|
||||
// RUN: %target-swift-frontend -typecheck -verify %s -debug-generic-signatures -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
|
||||
|
||||
// Another GenericSignatureBuilder oddity, reduced from RxSwift.
|
||||
//
|
||||
@@ -27,8 +27,8 @@ class GenericDelegateProxy<P : AnyObject, D> {
|
||||
// CHECK-NEXT: <P, D, Proxy where P == Proxy.[DelegateProxyType]Parent, D == Proxy.[DelegateProxyType]Delegate, Proxy : GenericDelegateProxy<P, D>, Proxy : DelegateProxyType>
|
||||
init<Proxy: DelegateProxyType>(_: Proxy.Type)
|
||||
where Proxy: GenericDelegateProxy<P, D>,
|
||||
Proxy.Parent == P,
|
||||
Proxy.Delegate == D {}
|
||||
Proxy.Parent == P, // expected-warning {{redundant same-type constraint 'GenericDelegateProxy<P, D>.Parent' (aka 'P') == 'P'}}
|
||||
Proxy.Delegate == D {} // expected-warning {{redundant same-type constraint 'GenericDelegateProxy<P, D>.Delegate' (aka 'D') == 'D'}}
|
||||
}
|
||||
|
||||
class SomeClass {}
|
||||
@@ -53,6 +53,8 @@ class ConcreteDelegateProxy {
|
||||
// CHECK-LABEL: .ConcreteDelegateProxy.init(_:_:_:)@
|
||||
// CHECK-NEXT: <P, D, Proxy where P == SomeClass, D == SomeStruct, Proxy : ConcreteDelegateProxy, Proxy : DelegateProxyType, Proxy.[DelegateProxyType]Delegate == SomeStruct, Proxy.[DelegateProxyType]Parent == SomeClass>
|
||||
|
||||
// expected-warning@+2 {{same-type requirement makes generic parameter 'P' non-generic}}
|
||||
// expected-warning@+1 {{same-type requirement makes generic parameter 'D' non-generic}}
|
||||
init<P, D, Proxy: DelegateProxyType>(_: P, _: D, _: Proxy.Type)
|
||||
where Proxy: ConcreteDelegateProxy,
|
||||
Proxy.Parent == P,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
|
||||
// RUN: %target-typecheck-verify-swift
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type-check function definitions
|
||||
@@ -294,10 +294,11 @@ func badTypeConformance5<T>(_: T) where T & Sequence : EqualComparable { }
|
||||
// expected-error@-1 {{non-protocol, non-class type 'T' cannot be used within a protocol-constrained type}}
|
||||
|
||||
func badTypeConformance6<T>(_: T) where [T] : Collection { }
|
||||
// expected-error@-1{{type '[T]' in conformance requirement does not refer to a generic parameter or associated type}}
|
||||
// expected-warning@-1{{redundant conformance constraint '[T]' : 'Collection'}}
|
||||
|
||||
func badTypeConformance7<T, U>(_: T, _: U) where T? : U { }
|
||||
// expected-error@-1{{type 'T?' in conformance requirement does not refer to a generic parameter or associated type}}
|
||||
// expected-error@-1{{type 'T?' constrained to non-protocol, non-class type 'U'}}
|
||||
|
||||
func badSameType<T, U : GeneratesAnElement, V>(_ : T, _ : U)
|
||||
where T == U.Element, U.Element == V {} // expected-error{{same-type requirement makes generic parameters 'T' and 'V' equivalent}}
|
||||
where T == U.Element, U.Element == V {}
|
||||
// expected-warning@-2{{same-type requirement makes generic parameters 'V' and 'T' equivalent}}
|
||||
|
||||
@@ -7,5 +7,6 @@
|
||||
|
||||
struct S {}
|
||||
|
||||
// expected-error@+2 {{same-type requirement makes generic parameter 'Self' non-generic}}
|
||||
// expected-error@+1 {{no type for 'Self' can satisfy both 'Self == S' and 'Self : P'}}
|
||||
protocol P where Self == S {}
|
||||
|
||||
@@ -47,6 +47,7 @@ func concreteSameTypeRedundancy<T>(_: T) where Int == Int {}
|
||||
|
||||
func concreteSameTypeRedundancy<T>(_: T) where Array<Int> == Array<T> {}
|
||||
// expected-warning@-1{{redundant same-type constraint 'Array<Int>' == 'Array<T>'}}
|
||||
// expected-warning@-2{{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
|
||||
protocol P {}
|
||||
struct S: P {}
|
||||
@@ -198,6 +199,13 @@ func inferred6<T : P11>(_: T) where T.Y : Hashable, T.Z == Set<T.X>, T.X == T.Y
|
||||
func typeMatcherSugar<T>(_: T) where Array<Int> == Array<T>, Array<Int> == Array<T> {}
|
||||
// expected-warning@-1 2{{redundant same-type constraint 'Array<Int>' == 'Array<T>'}}
|
||||
// expected-warning@-2{{redundant same-type constraint 'T' == 'Int'}}
|
||||
// expected-warning@-3{{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
|
||||
|
||||
struct ConcreteSelf: ConcreteProtocol {}
|
||||
|
||||
protocol ConcreteProtocol where Self == ConcreteSelf {}
|
||||
// expected-error@-1 {{same-type requirement makes generic parameter 'Self' non-generic}}
|
||||
|
||||
// MARK: - Conflict diagnostics
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
|
||||
// RUN: not %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify 2>&1 | %FileCheck %s
|
||||
// RUN: %target-typecheck-verify-swift
|
||||
// RUN: %target-swift-frontend -typecheck -verify %s -debug-generic-signatures 2>&1 | %FileCheck %s
|
||||
|
||||
// rdar://problem/39481178 - Introducing a superclass constraint does not add
|
||||
// same-type constraints on nested types
|
||||
@@ -19,10 +19,10 @@ extension P {
|
||||
// CHECK-LABEL: .f1@
|
||||
// CHECK-NEXT: <Self, T where Self : C, T == Int>
|
||||
func f1<T>(_: T) where T == Q, Self : C {}
|
||||
// expected-error@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
// expected-warning@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
|
||||
// CHECK-LABEL: .f2@
|
||||
// CHECK-NEXT: <Self, T where Self : C, T == Int>
|
||||
func f2<T>(_: T) where Self : C, T == Q {}
|
||||
// expected-error@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
// expected-warning@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
// opaque result types, even in the presence of errors or unusual generic
|
||||
// signatures.
|
||||
|
||||
// RUN: %target-typecheck-verify-swift -disable-availability-checking -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
|
||||
// RUN: %target-typecheck-verify-swift -disable-availability-checking
|
||||
// RUN: %target-swift-ide-test -print-usrs -source-filename %s | %FileCheck -strict-whitespace %s
|
||||
|
||||
// CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test0C21UnifyingGenericParams1xQrx_tq_Rszr0_lF
|
||||
func testUnifyingGenericParams<T, U>(x: T) -> some Collection where T == U {
|
||||
// expected-error@-1 {{same-type requirement makes generic parameters 'T' and 'U' equivalent}}
|
||||
// expected-warning@-1 {{same-type requirement makes generic parameters 'U' and 'T' equivalent}}
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@ func testUnifyingGenericParams2<T, U>(x: T) -> some Collection where T: Collecti
|
||||
|
||||
// CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test0C24ConcretizingGenericParam1xQrSi_tSiRszlF
|
||||
func testConcretizingGenericParam<T>(x: T) -> some Collection where T == Int {
|
||||
// expected-error@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
// expected-warning@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
return []
|
||||
}
|
||||
|
||||
struct GenericContext<T> {
|
||||
// CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test14GenericContextV0c8UnifyingD6Params1xQrx_tqd__RszlF
|
||||
func testUnifyingGenericParams<U>(x: T) -> some Collection where T == U {
|
||||
// expected-error@-1 {{same-type requirement makes generic parameters 'U' and 'T' equivalent}}
|
||||
// expected-warning@-1 {{same-type requirement makes generic parameters 'U' and 'T' equivalent}}
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ struct GenericContext<T> {
|
||||
|
||||
// CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test14GenericContextVyQrxcqd__Rszluip
|
||||
subscript<U>(x: T) -> some Collection where T == U {
|
||||
// expected-error@-1 {{same-type requirement makes generic parameters 'U' and 'T' equivalent}}
|
||||
// expected-warning@-1 {{same-type requirement makes generic parameters 'U' and 'T' equivalent}}
|
||||
// CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test14GenericContextVyQrxcqd__Rszluig
|
||||
get {
|
||||
return []
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %target-typecheck-verify-swift -enable-objc-interop -disable-objc-attr-requires-foundation-module -swift-version 5 -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
|
||||
// RUN: %target-typecheck-verify-swift -enable-objc-interop -disable-objc-attr-requires-foundation-module -swift-version 5
|
||||
|
||||
public protocol PublicProto {
|
||||
func publicReq()
|
||||
@@ -520,7 +520,7 @@ struct DefaultGeneric<T> {}
|
||||
|
||||
struct DefaultGenericPrivate<T: PrivateProto> {} // expected-error {{generic struct must be declared private or fileprivate because its generic parameter uses a private type}}
|
||||
struct DefaultGenericPrivate2<T: PrivateClass> {} // expected-error {{generic struct must be declared private or fileprivate because its generic parameter uses a private type}}
|
||||
struct DefaultGenericPrivateReq<T> where T == PrivateClass {} // expected-error {{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
struct DefaultGenericPrivateReq<T> where T == PrivateClass {} // expected-warning {{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
// expected-error@-1 {{generic struct must be declared private or fileprivate because its generic requirement uses a private type}}
|
||||
struct DefaultGenericPrivateReq2<T> where T: PrivateProto {} // expected-error {{generic struct must be declared private or fileprivate because its generic requirement uses a private type}}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
|
||||
// RUN: %target-typecheck-verify-swift
|
||||
|
||||
struct MyType<TyA, TyB> { // expected-note {{generic type 'MyType' declared here}}
|
||||
// expected-note @-1 {{arguments to generic parameter 'TyB' ('S' and 'Int') are expected to be equal}}
|
||||
@@ -33,7 +33,7 @@ typealias DS<T> = MyType<String, T>
|
||||
typealias BadA<T : Int> = MyType<String, T> // expected-error {{type 'T' constrained to non-protocol, non-class type 'Int'}}
|
||||
|
||||
typealias BadB<T where T == Int> = MyType<String, T> // expected-error {{associated types must not have a generic parameter list}}
|
||||
// expected-error@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
// expected-warning@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
|
||||
|
||||
typealias BadC<T,T> = MyType<String, T> // expected-error {{invalid redeclaration of 'T'}}
|
||||
// expected-note @-1 {{'T' previously declared here}}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
|
||||
// RUN: %target-typecheck-verify-swift
|
||||
|
||||
// Tests for typealias inside protocols
|
||||
|
||||
@@ -143,14 +143,18 @@ protocol P3 {
|
||||
}
|
||||
|
||||
// Test for not crashing on recursive aliases
|
||||
// FIXME: Nonsense redundant requirement warnings
|
||||
protocol Circular {
|
||||
typealias Y = Self.Y // expected-error {{type alias 'Y' references itself}} expected-note {{while resolving type 'Self.Y'}}
|
||||
// expected-warning@-1 {{redundant same-type constraint 'Self.Y' == 'Self.Y'}}
|
||||
|
||||
typealias Y2 = Y2 // expected-error {{type alias 'Y2' references itself}} expected-note {{while resolving type 'Y2'}}
|
||||
// expected-warning@-1 {{redundant same-type constraint 'Self.Y2' == 'Self.Y2'}}
|
||||
|
||||
typealias Y3 = Y4 // expected-error {{type alias 'Y3' references itself}} expected-note {{while resolving type 'Y4'}}
|
||||
|
||||
typealias Y4 = Y3 // expected-note {{through reference here}} expected-note {{while resolving type 'Y3'}}
|
||||
// expected-warning@-1 {{redundant same-type constraint 'Self.Y4' == 'Self.Y3'}}
|
||||
}
|
||||
|
||||
// Qualified and unqualified references to protocol typealiases from concrete type
|
||||
@@ -250,8 +254,8 @@ protocol P9 {
|
||||
typealias A = Int
|
||||
}
|
||||
|
||||
func testT9a<T: P9, U>(_: T, _: U) where T.A == U { } // expected-error {{same-type requirement makes generic parameter 'U' non-generic}}
|
||||
func testT9b<T: P9>(_: T) where T.A == Float { } // expected-error{{generic signature requires types 'T.A' (aka 'Int') and 'Float' to be the same}}
|
||||
func testT9a<T: P9, U>(_: T, _: U) where T.A == U { } // expected-warning {{same-type requirement makes generic parameter 'U' non-generic}}
|
||||
func testT9b<T: P9>(_: T) where T.A == Float { } // expected-error{{no type for 'T.A' can satisfy both 'T.A == Int' and 'T.A == Float'}}
|
||||
|
||||
|
||||
struct X<T> { }
|
||||
@@ -268,7 +272,7 @@ protocol P10 {
|
||||
typealias U = Float
|
||||
}
|
||||
|
||||
extension P10 where T == Int { } // expected-warning{{neither type in same-type constraint ('Self.T' (aka 'Int') or 'Int') refers to a generic parameter or associated type}}
|
||||
extension P10 where T == Int { } // expected-warning{{redundant same-type constraint 'Self.T' == 'Int'}}
|
||||
|
||||
extension P10 where A == X<T> { }
|
||||
|
||||
@@ -277,7 +281,7 @@ extension P10 where A == X<U> { }
|
||||
extension P10 where A == X<Self.U> { }
|
||||
|
||||
extension P10 where V == Int { } // expected-warning {{'V' is deprecated: just use Int, silly}}
|
||||
// expected-warning@-1{{neither type in same-type constraint ('Self.V' (aka 'Int') or 'Int') refers to a generic parameter or associated type}}
|
||||
// expected-warning@-1{{redundant same-type constraint 'Self.V' == 'Int'}}
|
||||
|
||||
// rdar://problem/36003312
|
||||
protocol P11 {
|
||||
|
||||
Reference in New Issue
Block a user