Skip to content

Commit 00cc260

Browse files
committed
[Sema] Penalize conversions to Any.
We previously penalized bindings to Any, and that resulted in inappropriately rejecting solutions where we bind a decl that is explicitly typed Any. That penalty was removed in 170dc8a, but that has led to a variety of source compatibility issues. So now, we'll reintroduce a penalty for Any-typed things, but instead of penalizing bindings (which happen both because of explicitly-typed values in the source, and implicitly due to attempting various types for a particular type variable), penalize casts, which are always present in some form in the source. Thanks go to John for the suggestion. Fixes SR-3817 (aka rdar://problem/30311052) SR-3786 (aka rdar://problem/30268529) rdar://problem/29907555
1 parent 13a6574 commit 00cc260

File tree

6 files changed

+30
-8
lines changed

6 files changed

+30
-8
lines changed

lib/Sema/CSRanking.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ void ConstraintSystem::increaseScore(ScoreKind kind, unsigned value) {
7474
case SK_ScalarPointerConversion:
7575
log << "scalar-to-pointer conversion";
7676
break;
77+
case SK_EmptyExistentialConversion:
78+
log << "empty-existential conversion";
79+
break;
7780
}
7881
log << ")\n";
7982
}

lib/Sema/CSSimplify.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,6 +2066,11 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
20662066
if (concrete && type2->isExistentialType() &&
20672067
!type1->is<LValueType>() &&
20682068
kind >= ConstraintKind::Subtype) {
2069+
2070+
// Penalize conversions to Any.
2071+
if (kind >= ConstraintKind::Conversion && type2->isAny())
2072+
increaseScore(ScoreKind::SK_EmptyExistentialConversion);
2073+
20692074
conversionsOrFixes.push_back(ConversionRestrictionKind::Existential);
20702075
}
20712076

lib/Sema/ConstraintSystem.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,10 @@ enum ScoreKind {
407407
SK_ScalarPointerConversion,
408408
/// A conversion from an array to a pointer of matching element type.
409409
SK_ArrayPointerConversion,
410+
/// A conversion to an empty existential type ('Any' or '{}').
411+
SK_EmptyExistentialConversion,
410412

411-
SK_LastScoreKind = SK_ArrayPointerConversion,
413+
SK_LastScoreKind = SK_EmptyExistentialConversion,
412414
};
413415

414416
/// The number of score kinds.

test/Constraints/array_literal.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,10 @@ let router = Company(
227227
}
228228
]
229229
)
230+
231+
// Infer [[Int]] for SR3786aa.
232+
// FIXME: As noted in SR-3786, this was the behavior in Swift 3, but
233+
// it seems like the wrong choice and is less by design than by
234+
// accident.
235+
let SR3786a: [Int] = [1, 2, 3]
236+
let SR3786aa = [SR3786a.reversed(), SR3786a]

test/Constraints/diag_ambiguities.swift

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,9 @@ func rdar29691909(o: AnyObject) -> Any? {
3636
return rdar29691909_callee(o) // expected-error{{ambiguous use of 'rdar29691909_callee'}}
3737
}
3838

39-
// FIXME: The fix for this broke other things. We want to get this
40-
// test case running again, though.
41-
// Ensure that we decay Any! to Any? rather than allowing Any!-to-Any
42-
// conversion directly and ending up with an ambiguity here.
43-
//func rdar29907555(_ value: Any!) -> String {
44-
// return "\(value)" // no error
45-
//}
39+
func rdar29907555(_ value: Any!) -> String {
40+
return "\(value)" // no error
41+
}
4642

4743
struct SR3715 {
4844
var overloaded: Int!

test/Constraints/overload.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,12 @@ func overloadedMethod<T>() {}
186186

187187
overloadedMethod()
188188
// expected-error@-1 {{missing argument for parameter 'n' in call}}
189+
190+
// Ensure we select the overload of '??' returning T? rather than T.
191+
func SR3817(_ d: [String : Any], _ s: String, _ t: String) -> Any {
192+
if let r = d[s] ?? d[t] {
193+
return r
194+
} else {
195+
return 0
196+
}
197+
}

0 commit comments

Comments
 (0)