Skip to content

Commit cb25f2b

Browse files
committed
GSB: Diagnose conflicts between concrete-type and AnyObject requirements
1 parent f190e51 commit cb25f2b

File tree

2 files changed

+84
-8
lines changed

2 files changed

+84
-8
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6240,6 +6240,20 @@ void GenericSignatureBuilder::ExplicitRequirement::dump(
62406240
out << rhs.get<LayoutConstraint>();
62416241
}
62426242

6243+
static bool typeImpliesLayoutConstraint(Type t, LayoutConstraint layout) {
6244+
if (layout->isRefCounted() && t->satisfiesClassConstraint())
6245+
return true;
6246+
6247+
return false;
6248+
}
6249+
6250+
static bool typeConflictsWithLayoutConstraint(Type t, LayoutConstraint layout) {
6251+
if (layout->isClass() && !t->satisfiesClassConstraint())
6252+
return true;
6253+
6254+
return false;
6255+
}
6256+
62436257
void GenericSignatureBuilder::computeRedundantRequirements() {
62446258
assert(!Impl->computedRedundantRequirements &&
62456259
"Already computed redundant requirements");
@@ -6397,9 +6411,12 @@ void GenericSignatureBuilder::computeRedundantRequirements() {
63976411
concreteTypeRequirement);
63986412
}
63996413

6414+
Optional<ExplicitRequirement> layoutRequirement;
6415+
64006416
if (equivClass.layout) {
64016417
SmallVector<Constraint<LayoutConstraint>, 2> exact;
64026418
SmallVector<Constraint<LayoutConstraint>, 2> lessSpecific;
6419+
SmallVector<Constraint<LayoutConstraint>, 2> impliedByConcrete;
64036420

64046421
for (const auto &constraint : equivClass.layoutConstraints) {
64056422
auto *source = constraint.source;
@@ -6416,6 +6433,12 @@ void GenericSignatureBuilder::computeRedundantRequirements() {
64166433
if (derivedViaConcrete)
64176434
continue;
64186435

6436+
if (resolvedConcreteType) {
6437+
if (typeImpliesLayoutConstraint(resolvedConcreteType, layout)) {
6438+
impliedByConcrete.push_back(constraint);
6439+
}
6440+
}
6441+
64196442
if (layout == equivClass.layout) {
64206443
exact.push_back(constraint);
64216444
continue;
@@ -6431,12 +6454,16 @@ void GenericSignatureBuilder::computeRedundantRequirements() {
64316454
std::make_pair(req, equivClass.layout));
64326455
}
64336456

6434-
// FIXME: Check for a conflict via the concrete type.
64356457
lessSpecific.push_back(constraint);
64366458
}
64376459

6438-
graph.addConstraintsFromEquivClass(RequirementKind::Layout,
6439-
exact, lessSpecific);
6460+
layoutRequirement =
6461+
graph.addConstraintsFromEquivClass(RequirementKind::Layout,
6462+
exact, lessSpecific);
6463+
6464+
graph.handleConstraintsImpliedByConcrete(RequirementKind::Layout,
6465+
impliedByConcrete,
6466+
concreteTypeRequirement);
64406467
}
64416468

64426469
if (resolvedConcreteType && resolvedSuperclass) {
@@ -6445,6 +6472,13 @@ void GenericSignatureBuilder::computeRedundantRequirements() {
64456472
{*concreteTypeRequirement, *superclassRequirement,
64466473
resolvedConcreteType, resolvedSuperclass});
64476474
}
6475+
} else if (resolvedConcreteType && equivClass.layout) {
6476+
if (typeConflictsWithLayoutConstraint(resolvedConcreteType,
6477+
equivClass.layout)) {
6478+
Impl->ConflictingConcreteTypeRequirements.push_back(
6479+
{*concreteTypeRequirement, *layoutRequirement,
6480+
resolvedConcreteType, equivClass.layout});
6481+
}
64486482
}
64496483
}
64506484

@@ -7267,8 +7301,6 @@ void GenericSignatureBuilder::diagnoseConflictingConcreteTypeRequirements() cons
72677301
SourceLoc loc = pair.concreteTypeRequirement.getSource()->getLoc();
72687302
SourceLoc otherLoc = pair.otherRequirement.getSource()->getLoc();
72697303

7270-
Type otherRHS = pair.otherRHS.get<Type>();
7271-
72727304
if (loc.isInvalid() && otherLoc.isInvalid())
72737305
continue;
72747306

@@ -7280,18 +7312,30 @@ void GenericSignatureBuilder::diagnoseConflictingConcreteTypeRequirements() cons
72807312
switch (pair.otherRequirement.getKind()) {
72817313
case RequirementKind::Superclass: {
72827314
Context.Diags.diagnose(subjectLoc, diag::type_does_not_inherit,
7283-
subjectType, pair.resolvedConcreteType, otherRHS);
7315+
subjectType, pair.resolvedConcreteType,
7316+
pair.otherRHS.get<Type>());
72847317

72857318
if (otherLoc.isValid()) {
72867319
Context.Diags.diagnose(otherLoc, diag::superclass_redundancy_here,
7287-
subjectType, otherRHS);
7320+
subjectType, pair.otherRHS.get<Type>());
7321+
}
7322+
7323+
break;
7324+
}
7325+
7326+
case RequirementKind::Layout: {
7327+
Context.Diags.diagnose(subjectLoc, diag::type_is_not_a_class,
7328+
subjectType, pair.resolvedConcreteType, Type());
7329+
7330+
if (otherLoc.isValid()) {
7331+
Context.Diags.diagnose(otherLoc, diag::previous_layout_constraint,
7332+
subjectType, pair.otherRHS.get<LayoutConstraint>());
72887333
}
72897334

72907335
break;
72917336
}
72927337

72937338
case RequirementKind::Conformance:
7294-
case RequirementKind::Layout:
72957339
case RequirementKind::SameType:
72967340
llvm_unreachable("TODO");
72977341
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %target-typecheck-verify-swift
2+
// RUN: not %target-swift-frontend -typecheck -debug-generic-signatures %s 2>&1 | %FileCheck %s
3+
struct S {}
4+
class C {}
5+
6+
struct G1<T : AnyObject> {}
7+
8+
// CHECK-LABEL: Generic signature: <T where T == S>
9+
extension G1 where T == S {}
10+
// expected-error@-1 {{'T' requires that 'S' be a class type}}
11+
// expected-note@-2 {{same-type constraint 'T' == 'S' implied here}}
12+
13+
// CHECK-LABEL: Generic signature: <T where T == C>
14+
extension G1 where T == C {}
15+
16+
struct G2<U> {}
17+
18+
// CHECK-LABEL: Generic signature: <U where U == S>
19+
extension G2 where U == S, U : AnyObject {}
20+
// expected-error@-1 {{'U' requires that 'S' be a class type}}
21+
// expected-note@-2 {{same-type constraint 'U' == 'S' implied here}}
22+
// expected-note@-3 {{constraint 'U' : 'AnyObject' implied here}}
23+
24+
// CHECK-LABEL: Generic signature: <U where U == C>
25+
extension G2 where U == C, U : AnyObject {}
26+
// expected-warning@-1 {{redundant constraint 'U' : 'AnyObject'}}
27+
// expected-note@-2 {{constraint 'U' : 'AnyObject' implied here}}
28+
29+
// CHECK-LABEL: Generic signature: <U where U : C>
30+
extension G2 where U : C, U : AnyObject {}
31+
// expected-warning@-1 {{redundant constraint 'U' : 'AnyObject'}}
32+
// expected-note@-2 {{constraint 'U' : 'AnyObject' implied here}}

0 commit comments

Comments
 (0)