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:
Holly Borla
2022-04-12 18:27:43 -07:00
committed by GitHub
12 changed files with 80 additions and 30 deletions

View File

@@ -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();

View File

@@ -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}}

View File

@@ -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)
}

View File

@@ -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,

View File

@@ -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}}

View File

@@ -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 {}

View File

@@ -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

View File

@@ -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}}
}

View File

@@ -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 []

View File

@@ -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}}

View File

@@ -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}}

View File

@@ -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 {