Skip to content

Commit 4eb7dad

Browse files
authored
Merge pull request #42331 from hborla/5.7-concrete-generic-params
[5.7][RequirementMachine] Diagnose type parameters that are made concrete by a same-type requirement.
2 parents 2c50735 + d8756fd commit 4eb7dad

12 files changed

+80
-30
lines changed

lib/AST/RequirementMachine/RequirementMachineRequests.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,18 @@ RequirementSignatureRequestRQM::evaluate(Evaluator &evaluator,
413413
machine->computeRequirementDiagnostics(errors, proto->getLoc());
414414
diagnoseRequirementErrors(ctx, errors,
415415
AllowConcreteTypePolicy::NestedAssocTypes);
416+
417+
for (auto *protocol : machine->System.getProtocols()) {
418+
auto selfType = protocol->getSelfInterfaceType();
419+
auto concrete = machine->getConcreteType(selfType,
420+
machine->getGenericParams(),
421+
protocol);
422+
if (!concrete || concrete->hasError())
423+
continue;
424+
425+
protocol->diagnose(diag::requires_generic_param_made_equal_to_concrete,
426+
selfType);
427+
}
416428
}
417429

418430
if (!machine->getErrors()) {
@@ -859,8 +871,6 @@ InferredGenericSignatureRequestRQM::evaluate(
859871
: AllowConcreteTypePolicy::AssocTypes);
860872
}
861873

862-
// FIXME: Handle allowConcreteGenericParams
863-
864874
// Don't bother splitting concrete equivalence classes if there were invalid
865875
// requirements, because the signature is not going to be ABI anyway.
866876
if (!errorFlags.contains(GenericSignatureErrorFlags::HasInvalidRequirements)) {
@@ -887,6 +897,28 @@ InferredGenericSignatureRequestRQM::evaluate(
887897
std::move(machine));
888898
}
889899

900+
if (!allowConcreteGenericParams &&
901+
ctx.LangOpts.RequirementMachineInferredSignatures ==
902+
RequirementMachineMode::Enabled) {
903+
for (auto genericParam : result.getInnermostGenericParams()) {
904+
auto canonical = result.getCanonicalTypeInContext(genericParam);
905+
906+
if (canonical->hasError() || canonical->isEqual(genericParam))
907+
continue;
908+
909+
if (canonical->isTypeParameter()) {
910+
ctx.Diags.diagnose(loc, diag::requires_generic_params_made_equal,
911+
genericParam, result->getSugaredType(canonical))
912+
.warnUntilSwiftVersion(6);
913+
} else {
914+
ctx.Diags.diagnose(loc,
915+
diag::requires_generic_param_made_equal_to_concrete,
916+
genericParam)
917+
.warnUntilSwiftVersion(6);
918+
}
919+
}
920+
}
921+
890922
if (!errorFlags.contains(GenericSignatureErrorFlags::HasInvalidRequirements)) {
891923
// Check invariants.
892924
result.verify();

test/Compatibility/accessibility.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %target-typecheck-verify-swift -swift-version 4 -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
2-
// RUN: %target-typecheck-verify-swift -swift-version 4.2 -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
1+
// RUN: %target-typecheck-verify-swift -swift-version 4
2+
// RUN: %target-typecheck-verify-swift -swift-version 4.2
33

44
public protocol PublicProto {
55
func publicReq()
@@ -503,7 +503,7 @@ struct DefaultGeneric<T> {}
503503

504504
struct DefaultGenericPrivate<T: PrivateProto> {} // expected-error {{generic struct must be declared private or fileprivate because its generic parameter uses a private type}}
505505
struct DefaultGenericPrivate2<T: PrivateClass> {} // expected-error {{generic struct must be declared private or fileprivate because its generic parameter uses a private type}}
506-
struct DefaultGenericPrivateReq<T> where T == PrivateClass {} // expected-error {{same-type requirement makes generic parameter 'T' non-generic}}
506+
struct DefaultGenericPrivateReq<T> where T == PrivateClass {} // expected-warning {{same-type requirement makes generic parameter 'T' non-generic}}
507507
// expected-error@-1 {{generic struct must be declared private or fileprivate because its generic requirement uses a private type}}
508508
struct DefaultGenericPrivateReq2<T> where T: PrivateProto {} // expected-error {{generic struct must be declared private or fileprivate because its generic requirement uses a private type}}
509509

test/Constraints/generic_super_constraint.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ func foo<T>(_ x: T) -> Derived where T: Base<Int>, T: Derived {
88
return x
99
}
1010

11+
// FIXME: There is no explicit same-type requirement written.
12+
// expected-warning@+1{{same-type requirement makes generic parameter 'T' non-generic}}
1113
func bar<T, U>(_ x: U, y: T) -> (Derived, Int) where U: Base<T>, U: Derived {
1214
return (x, y)
1315
}

test/Generics/concrete_contraction_unrelated_typealias.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
1+
// RUN: %target-swift-frontend -typecheck -verify %s -debug-generic-signatures -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
22

33
// Another GenericSignatureBuilder oddity, reduced from RxSwift.
44
//
@@ -27,8 +27,8 @@ class GenericDelegateProxy<P : AnyObject, D> {
2727
// CHECK-NEXT: <P, D, Proxy where P == Proxy.[DelegateProxyType]Parent, D == Proxy.[DelegateProxyType]Delegate, Proxy : GenericDelegateProxy<P, D>, Proxy : DelegateProxyType>
2828
init<Proxy: DelegateProxyType>(_: Proxy.Type)
2929
where Proxy: GenericDelegateProxy<P, D>,
30-
Proxy.Parent == P,
31-
Proxy.Delegate == D {}
30+
Proxy.Parent == P, // expected-warning {{redundant same-type constraint 'GenericDelegateProxy<P, D>.Parent' (aka 'P') == 'P'}}
31+
Proxy.Delegate == D {} // expected-warning {{redundant same-type constraint 'GenericDelegateProxy<P, D>.Delegate' (aka 'D') == 'D'}}
3232
}
3333

3434
class SomeClass {}
@@ -53,6 +53,8 @@ class ConcreteDelegateProxy {
5353
// CHECK-LABEL: .ConcreteDelegateProxy.init(_:_:_:)@
5454
// CHECK-NEXT: <P, D, Proxy where P == SomeClass, D == SomeStruct, Proxy : ConcreteDelegateProxy, Proxy : DelegateProxyType, Proxy.[DelegateProxyType]Delegate == SomeStruct, Proxy.[DelegateProxyType]Parent == SomeClass>
5555

56+
// expected-warning@+2 {{same-type requirement makes generic parameter 'P' non-generic}}
57+
// expected-warning@+1 {{same-type requirement makes generic parameter 'D' non-generic}}
5658
init<P, D, Proxy: DelegateProxyType>(_: P, _: D, _: Proxy.Type)
5759
where Proxy: ConcreteDelegateProxy,
5860
Proxy.Parent == P,

test/Generics/function_defs.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
1+
// RUN: %target-typecheck-verify-swift
22

33
//===----------------------------------------------------------------------===//
44
// Type-check function definitions
@@ -294,10 +294,11 @@ func badTypeConformance5<T>(_: T) where T & Sequence : EqualComparable { }
294294
// expected-error@-1 {{non-protocol, non-class type 'T' cannot be used within a protocol-constrained type}}
295295

296296
func badTypeConformance6<T>(_: T) where [T] : Collection { }
297-
// expected-error@-1{{type '[T]' in conformance requirement does not refer to a generic parameter or associated type}}
297+
// expected-warning@-1{{redundant conformance constraint '[T]' : 'Collection'}}
298298

299299
func badTypeConformance7<T, U>(_: T, _: U) where T? : U { }
300-
// expected-error@-1{{type 'T?' in conformance requirement does not refer to a generic parameter or associated type}}
300+
// expected-error@-1{{type 'T?' constrained to non-protocol, non-class type 'U'}}
301301

302302
func badSameType<T, U : GeneratesAnElement, V>(_ : T, _ : U)
303-
where T == U.Element, U.Element == V {} // expected-error{{same-type requirement makes generic parameters 'T' and 'V' equivalent}}
303+
where T == U.Element, U.Element == V {}
304+
// expected-warning@-2{{same-type requirement makes generic parameters 'V' and 'T' equivalent}}

test/Generics/protocol_self_concrete_error.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77

88
struct S {}
99

10+
// expected-error@+2 {{same-type requirement makes generic parameter 'Self' non-generic}}
1011
// expected-error@+1 {{no type for 'Self' can satisfy both 'Self == S' and 'Self : P'}}
1112
protocol P where Self == S {}

test/Generics/requirement_machine_diagnostics.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ func concreteSameTypeRedundancy<T>(_: T) where Int == Int {}
4747

4848
func concreteSameTypeRedundancy<T>(_: T) where Array<Int> == Array<T> {}
4949
// expected-warning@-1{{redundant same-type constraint 'Array<Int>' == 'Array<T>'}}
50+
// expected-warning@-2{{same-type requirement makes generic parameter 'T' non-generic}}
5051

5152
protocol P {}
5253
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
198199
func typeMatcherSugar<T>(_: T) where Array<Int> == Array<T>, Array<Int> == Array<T> {}
199200
// expected-warning@-1 2{{redundant same-type constraint 'Array<Int>' == 'Array<T>'}}
200201
// expected-warning@-2{{redundant same-type constraint 'T' == 'Int'}}
202+
// expected-warning@-3{{same-type requirement makes generic parameter 'T' non-generic}}
203+
204+
205+
struct ConcreteSelf: ConcreteProtocol {}
206+
207+
protocol ConcreteProtocol where Self == ConcreteSelf {}
208+
// expected-error@-1 {{same-type requirement makes generic parameter 'Self' non-generic}}
201209

202210
// MARK: - Conflict diagnostics
203211

test/Generics/superclass_constraint_nested_type.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
2-
// RUN: not %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify 2>&1 | %FileCheck %s
1+
// RUN: %target-typecheck-verify-swift
2+
// RUN: %target-swift-frontend -typecheck -verify %s -debug-generic-signatures 2>&1 | %FileCheck %s
33

44
// rdar://problem/39481178 - Introducing a superclass constraint does not add
55
// same-type constraints on nested types
@@ -19,10 +19,10 @@ extension P {
1919
// CHECK-LABEL: .f1@
2020
// CHECK-NEXT: <Self, T where Self : C, T == Int>
2121
func f1<T>(_: T) where T == Q, Self : C {}
22-
// expected-error@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
22+
// expected-warning@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
2323

2424
// CHECK-LABEL: .f2@
2525
// CHECK-NEXT: <Self, T where Self : C, T == Int>
2626
func f2<T>(_: T) where Self : C, T == Q {}
27-
// expected-error@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
27+
// expected-warning@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
2828
}

test/IDE/print_usrs_opaque_types.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
// opaque result types, even in the presence of errors or unusual generic
33
// signatures.
44

5-
// RUN: %target-typecheck-verify-swift -disable-availability-checking -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
5+
// RUN: %target-typecheck-verify-swift -disable-availability-checking
66
// RUN: %target-swift-ide-test -print-usrs -source-filename %s | %FileCheck -strict-whitespace %s
77

88
// CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test0C21UnifyingGenericParams1xQrx_tq_Rszr0_lF
99
func testUnifyingGenericParams<T, U>(x: T) -> some Collection where T == U {
10-
// expected-error@-1 {{same-type requirement makes generic parameters 'T' and 'U' equivalent}}
10+
// expected-warning@-1 {{same-type requirement makes generic parameters 'U' and 'T' equivalent}}
1111
return []
1212
}
1313

@@ -18,14 +18,14 @@ func testUnifyingGenericParams2<T, U>(x: T) -> some Collection where T: Collecti
1818

1919
// CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test0C24ConcretizingGenericParam1xQrSi_tSiRszlF
2020
func testConcretizingGenericParam<T>(x: T) -> some Collection where T == Int {
21-
// expected-error@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
21+
// expected-warning@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
2222
return []
2323
}
2424

2525
struct GenericContext<T> {
2626
// CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test14GenericContextV0c8UnifyingD6Params1xQrx_tqd__RszlF
2727
func testUnifyingGenericParams<U>(x: T) -> some Collection where T == U {
28-
// expected-error@-1 {{same-type requirement makes generic parameters 'U' and 'T' equivalent}}
28+
// expected-warning@-1 {{same-type requirement makes generic parameters 'U' and 'T' equivalent}}
2929
return []
3030
}
3131

@@ -36,7 +36,7 @@ struct GenericContext<T> {
3636

3737
// CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test14GenericContextVyQrxcqd__Rszluip
3838
subscript<U>(x: T) -> some Collection where T == U {
39-
// expected-error@-1 {{same-type requirement makes generic parameters 'U' and 'T' equivalent}}
39+
// expected-warning@-1 {{same-type requirement makes generic parameters 'U' and 'T' equivalent}}
4040
// CHECK: [[@LINE+1]]:{{[0-9]+}} s:14swift_ide_test14GenericContextVyQrxcqd__Rszluig
4141
get {
4242
return []

test/Sema/accessibility.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// 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
1+
// RUN: %target-typecheck-verify-swift -enable-objc-interop -disable-objc-attr-requires-foundation-module -swift-version 5
22

33
public protocol PublicProto {
44
func publicReq()
@@ -520,7 +520,7 @@ struct DefaultGeneric<T> {}
520520

521521
struct DefaultGenericPrivate<T: PrivateProto> {} // expected-error {{generic struct must be declared private or fileprivate because its generic parameter uses a private type}}
522522
struct DefaultGenericPrivate2<T: PrivateClass> {} // expected-error {{generic struct must be declared private or fileprivate because its generic parameter uses a private type}}
523-
struct DefaultGenericPrivateReq<T> where T == PrivateClass {} // expected-error {{same-type requirement makes generic parameter 'T' non-generic}}
523+
struct DefaultGenericPrivateReq<T> where T == PrivateClass {} // expected-warning {{same-type requirement makes generic parameter 'T' non-generic}}
524524
// expected-error@-1 {{generic struct must be declared private or fileprivate because its generic requirement uses a private type}}
525525
struct DefaultGenericPrivateReq2<T> where T: PrivateProto {} // expected-error {{generic struct must be declared private or fileprivate because its generic requirement uses a private type}}
526526

test/decl/typealias/generic.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
1+
// RUN: %target-typecheck-verify-swift
22

33
struct MyType<TyA, TyB> { // expected-note {{generic type 'MyType' declared here}}
44
// 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>
3333
typealias BadA<T : Int> = MyType<String, T> // expected-error {{type 'T' constrained to non-protocol, non-class type 'Int'}}
3434

3535
typealias BadB<T where T == Int> = MyType<String, T> // expected-error {{associated types must not have a generic parameter list}}
36-
// expected-error@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
36+
// expected-warning@-1 {{same-type requirement makes generic parameter 'T' non-generic}}
3737

3838
typealias BadC<T,T> = MyType<String, T> // expected-error {{invalid redeclaration of 'T'}}
3939
// expected-note @-1 {{'T' previously declared here}}

test/decl/typealias/protocol.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
1+
// RUN: %target-typecheck-verify-swift
22

33
// Tests for typealias inside protocols
44

@@ -143,14 +143,18 @@ protocol P3 {
143143
}
144144

145145
// Test for not crashing on recursive aliases
146+
// FIXME: Nonsense redundant requirement warnings
146147
protocol Circular {
147148
typealias Y = Self.Y // expected-error {{type alias 'Y' references itself}} expected-note {{while resolving type 'Self.Y'}}
149+
// expected-warning@-1 {{redundant same-type constraint 'Self.Y' == 'Self.Y'}}
148150

149151
typealias Y2 = Y2 // expected-error {{type alias 'Y2' references itself}} expected-note {{while resolving type 'Y2'}}
152+
// expected-warning@-1 {{redundant same-type constraint 'Self.Y2' == 'Self.Y2'}}
150153

151154
typealias Y3 = Y4 // expected-error {{type alias 'Y3' references itself}} expected-note {{while resolving type 'Y4'}}
152155

153156
typealias Y4 = Y3 // expected-note {{through reference here}} expected-note {{while resolving type 'Y3'}}
157+
// expected-warning@-1 {{redundant same-type constraint 'Self.Y4' == 'Self.Y3'}}
154158
}
155159

156160
// Qualified and unqualified references to protocol typealiases from concrete type
@@ -250,8 +254,8 @@ protocol P9 {
250254
typealias A = Int
251255
}
252256

253-
func testT9a<T: P9, U>(_: T, _: U) where T.A == U { } // expected-error {{same-type requirement makes generic parameter 'U' non-generic}}
254-
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}}
257+
func testT9a<T: P9, U>(_: T, _: U) where T.A == U { } // expected-warning {{same-type requirement makes generic parameter 'U' non-generic}}
258+
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'}}
255259

256260

257261
struct X<T> { }
@@ -268,7 +272,7 @@ protocol P10 {
268272
typealias U = Float
269273
}
270274

271-
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}}
275+
extension P10 where T == Int { } // expected-warning{{redundant same-type constraint 'Self.T' == 'Int'}}
272276

273277
extension P10 where A == X<T> { }
274278

@@ -277,7 +281,7 @@ extension P10 where A == X<U> { }
277281
extension P10 where A == X<Self.U> { }
278282

279283
extension P10 where V == Int { } // expected-warning {{'V' is deprecated: just use Int, silly}}
280-
// expected-warning@-1{{neither type in same-type constraint ('Self.V' (aka 'Int') or 'Int') refers to a generic parameter or associated type}}
284+
// expected-warning@-1{{redundant same-type constraint 'Self.V' == 'Int'}}
281285

282286
// rdar://problem/36003312
283287
protocol P11 {

0 commit comments

Comments
 (0)