Skip to content

Commit d213fb1

Browse files
committed
[CS] Visit all fixed bindings for constraint re-activation
This fixes a correctness issue with the old implementation where we could fail to re-activate a coercion constraint, and then let invalid code get past Sema, causing either miscompiles or crashes later down the pipeline.
1 parent a066289 commit d213fb1

File tree

4 files changed

+54
-38
lines changed

4 files changed

+54
-38
lines changed

lib/Sema/ConstraintGraph.cpp

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -566,33 +566,39 @@ llvm::TinyPtrVector<Constraint *> ConstraintGraph::gatherConstraints(
566566
acceptConstraintFn(constraint);
567567
};
568568

569-
// Add constraints for the given adjacent type variable.
570569
llvm::SmallPtrSet<TypeVariableType *, 4> typeVars;
570+
llvm::SmallPtrSet<Constraint *, 8> visitedConstraints;
571+
572+
if (kind == GatheringKind::AllMentions) {
573+
// If we've been asked for "all mentions" of a type variable, search for
574+
// constraints involving both it and its fixed bindings.
575+
depthFirstSearch(
576+
*this, typeVar,
577+
[&](TypeVariableType *typeVar) {
578+
return typeVars.insert(typeVar).second;
579+
},
580+
[&](Constraint *constraint) {
581+
if (acceptConstraint(constraint))
582+
constraints.push_back(constraint);
583+
584+
// Don't recurse into the constraint's type variables.
585+
return false;
586+
},
587+
visitedConstraints);
588+
return constraints;
589+
}
590+
591+
// Add constraints for the given adjacent type variable.
571592

572593
// Local function to add constraints
573-
llvm::SmallPtrSet<Constraint *, 4> visitedConstraints;
574594
auto addConstraintsOfAdjacency = [&](TypeVariableType *adjTypeVar) {
575-
ArrayRef<TypeVariableType *> adjTypeVarsToVisit;
576-
switch (kind) {
577-
case GatheringKind::EquivalenceClass:
578-
adjTypeVarsToVisit = adjTypeVar;
579-
break;
595+
if (!typeVars.insert(adjTypeVar).second)
596+
return;
580597

581-
case GatheringKind::AllMentions:
582-
adjTypeVarsToVisit
583-
= (*this)[CS.getRepresentative(adjTypeVar)].getEquivalenceClass();
584-
break;
585-
}
586-
587-
for (auto adjTypeVarEquiv : adjTypeVarsToVisit) {
588-
if (!typeVars.insert(adjTypeVarEquiv).second)
589-
continue;
590-
591-
for (auto constraint : (*this)[adjTypeVarEquiv].getConstraints()) {
592-
if (visitedConstraints.insert(constraint).second &&
593-
acceptConstraint(constraint))
594-
constraints.push_back(constraint);
595-
}
598+
for (auto constraint : (*this)[adjTypeVar].getConstraints()) {
599+
if (visitedConstraints.insert(constraint).second &&
600+
acceptConstraint(constraint))
601+
constraints.push_back(constraint);
596602
}
597603
};
598604

@@ -613,20 +619,6 @@ llvm::TinyPtrVector<Constraint *> ConstraintGraph::gatherConstraints(
613619
for (auto adjTypeVar : node.getFixedBindings()) {
614620
addConstraintsOfAdjacency(adjTypeVar);
615621
}
616-
617-
switch (kind) {
618-
case GatheringKind::EquivalenceClass:
619-
break;
620-
621-
case GatheringKind::AllMentions:
622-
// Retrieve the constraints from adjacent bindings.
623-
for (auto adjTypeVar : node.getAdjacencies()) {
624-
addConstraintsOfAdjacency(adjTypeVar);
625-
}
626-
627-
break;
628-
}
629-
630622
}
631623

632624
return constraints;

test/Constraints/bridging.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ func bridgeTupleToAnyObject() {
373373

374374
// Array defaulting and bridging type checking error per rdar://problem/54274245
375375
func rdar54274245(_ arr: [Any]?) {
376-
_ = (arr ?? []) as [NSObject]
376+
_ = (arr ?? []) as [NSObject] // expected-error {{type of expression is ambiguous without more context}}
377377
}
378378

379379
// rdar://problem/60501780 - failed to infer NSString as a value type of a dictionary

test/Constraints/casts.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,28 @@ func test_tuple_casts_no_warn() {
238238
_ = arr as! [(a: Foo, Foo)] // expected-warning {{cast from '[(Any, Any)]' to unrelated type '[(a: Foo, Foo)]' always fails}}
239239
_ = tup as! (a: Foo, Foo) // expected-warning {{cast from '(Any, Any)' to unrelated type '(a: Foo, Foo)' always fails}}
240240
}
241+
242+
infix operator ^^^
243+
func ^^^ <T> (lhs: T?, rhs: @autoclosure () -> T) -> T { lhs! }
244+
func ^^^ <T> (lhs: T?, rhs: @autoclosure () -> T?) -> T? { lhs! }
245+
246+
// SR-12369: Make sure we don't drop the coercion constraint.
247+
func test_coercions_with_overloaded_operator(str: String, optStr: String?, veryOptString: String????) {
248+
_ = (str ?? "") as Int // expected-error {{cannot convert value of type 'String' to type 'Int' in coercion}}
249+
_ = (optStr ?? "") as Int // expected-error {{cannot convert value of type 'String' to type 'Int' in coercion}}
250+
_ = (optStr ?? "") as Int? // expected-error {{cannot convert value of type 'String' to type 'Int?' in coercion}}
251+
252+
_ = (str ^^^ "") as Int // expected-error {{cannot convert value of type 'String' to type 'Int' in coercion}}
253+
_ = (optStr ^^^ "") as Int // expected-error {{cannot convert value of type 'String' to type 'Int' in coercion}}
254+
_ = (optStr ^^^ "") as Int? // expected-error {{cannot convert value of type 'String' to type 'Int?' in coercion}}
255+
256+
_ = ([] ?? []) as String // expected-error {{cannot convert value of type '[Any]' to type 'String' in coercion}}
257+
_ = ([""] ?? []) as [Int: Int] // expected-error {{cannot convert value of type '[String]' to type '[Int : Int]' in coercion}}
258+
_ = (["": ""] ?? [:]) as [Int] // expected-error {{cannot convert value of type '[String : String]' to type '[Int]' in coercion}}
259+
_ = (["": ""] ?? [:]) as Set<Int> // expected-error {{cannot convert value of type '[String : String]' to type 'Set<Int>' in coercion}}
260+
_ = (["": ""] ?? [:]) as Int? // expected-error {{cannot convert value of type '[String : String]' to type 'Int?' in coercion}}
261+
262+
_ = ("" ?? "" ?? "") as Float // expected-error {{cannot convert value of type 'String' to type 'Float' in coercion}}
263+
_ = (veryOptString ?? "" ?? "") as [String] // expected-error {{cannot convert value of type 'String???' to type '[String]' in coercion}}
264+
_ = (veryOptString ?? "" ?? "" ?? "" ?? "") as [String] // expected-error {{cannot convert value of type 'String???' to type '[String]' in coercion}}
265+
}

validation-test/Sema/type_checker_perf/slow/sr139.swift renamed to validation-test/Sema/type_checker_perf/fast/sr139.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@
33

44
// SR-139:
55
// Infinite recursion parsing bitwise operators
6-
// expected-error@+1 {{unable to type-check this expression in reasonable time}}
76
let x = UInt32(0x1FF)&0xFF << 24 | UInt32(0x1FF)&0xFF << 16 | UInt32(0x1FF)&0xFF << 8 | (UInt32(0x1FF)&0xFF)
87

0 commit comments

Comments
 (0)