Skip to content

Commit 09a56c1

Browse files
committed
[SR-4347] default to Any? instead of Any if there is a nil literal
1 parent 3d11679 commit 09a56c1

File tree

3 files changed

+43
-24
lines changed

3 files changed

+43
-24
lines changed

lib/Sema/CSSolver.cpp

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,26 +1173,30 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
11731173
// If we're supposed to add optional supertype bindings, do so now.
11741174
if (addOptionalSupertypeBindings) {
11751175
for (unsigned i : indices(result.Bindings)) {
1176-
// Only interested in supertype bindings.
11771176
auto &binding = result.Bindings[i];
1178-
if (binding.Kind != AllowedBindingKind::Supertypes) continue;
1179-
1180-
// If the type doesn't conform to ExpressibleByNilLiteral,
1181-
// produce an optional of that type as a potential binding. We
1182-
// overwrite the binding in place because the non-optional type
1183-
// will fail to type-check against the nil-literal conformance.
1184-
auto nominalBindingDecl = binding.BindingType->getAnyNominal();
1185-
bool conformsToExprByNilLiteral = false;
1186-
if (nominalBindingDecl) {
1187-
SmallVector<ProtocolConformance *, 2> conformances;
1188-
conformsToExprByNilLiteral = nominalBindingDecl->lookupConformance(
1189-
cs.DC->getParentModule(),
1190-
cs.getASTContext().getProtocol(
1191-
KnownProtocolKind::ExpressibleByNilLiteral),
1192-
conformances);
1177+
bool wrapInOptional = false;
1178+
1179+
if (binding.Kind == AllowedBindingKind::Supertypes) {
1180+
// If the type doesn't conform to ExpressibleByNilLiteral,
1181+
// produce an optional of that type as a potential binding. We
1182+
// overwrite the binding in place because the non-optional type
1183+
// will fail to type-check against the nil-literal conformance.
1184+
auto nominalBindingDecl = binding.BindingType->getAnyNominal();
1185+
bool conformsToExprByNilLiteral = false;
1186+
if (nominalBindingDecl) {
1187+
SmallVector<ProtocolConformance *, 2> conformances;
1188+
conformsToExprByNilLiteral = nominalBindingDecl->lookupConformance(
1189+
cs.DC->getParentModule(),
1190+
cs.getASTContext().getProtocol(
1191+
KnownProtocolKind::ExpressibleByNilLiteral),
1192+
conformances);
1193+
}
1194+
wrapInOptional = !conformsToExprByNilLiteral;
1195+
} else if (binding.isDefaultableBinding() && binding.BindingType->isAny()) {
1196+
wrapInOptional = true;
11931197
}
11941198

1195-
if (!conformsToExprByNilLiteral) {
1199+
if (wrapInOptional) {
11961200
binding.BindingType = OptionalType::get(binding.BindingType);
11971201
}
11981202
}

test/Constraints/array_literal.swift

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,28 +121,38 @@ class A { }
121121
class B : A { }
122122
class C : A { }
123123

124-
/// Check for defaulting the element type to 'Any'.
124+
/// Check for defaulting the element type to 'Any' / 'Any?'.
125125
func defaultToAny(i: Int, s: String) {
126126
let a1 = [1, "a", 3.5]
127127
// expected-error@-1{{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}}
128128
let _: Int = a1 // expected-error{{value of type '[Any]'}}
129129

130130
let a2: Array = [1, "a", 3.5]
131131
// expected-error@-1{{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}}
132-
133132
let _: Int = a2 // expected-error{{value of type '[Any]'}}
133+
134+
let a3 = [1, "a", nil, 3.5]
135+
// expected-error@-1{{heterogeneous collection literal could only be inferred to '[Any?]'; add explicit type annotation if this is intentional}}
136+
let _: Int = a3 // expected-error{{value of type '[Any?]'}}
137+
138+
let a4: Array = [1, "a", nil, 3.5]
139+
// expected-error@-1{{heterogeneous collection literal could only be inferred to '[Any?]'; add explicit type annotation if this is intentional}}
140+
let _: Int = a4 // expected-error{{value of type '[Any?]'}}
134141

135-
let a3 = []
142+
let a5 = []
136143
// expected-error@-1{{empty collection literal requires an explicit type}}
137-
138-
let _: Int = a3 // expected-error{{value of type '[Any]'}}
144+
let _: Int = a5 // expected-error{{value of type '[Any]'}}
139145

140146
let _: [Any] = [1, "a", 3.5]
141147
let _: [Any] = [1, "a", [3.5, 3.7, 3.9]]
142148
let _: [Any] = [1, "a", [3.5, "b", 3]]
149+
150+
let _: [Any?] = [1, "a", nil, 3.5]
151+
let _: [Any?] = [1, "a", nil, [3.5, 3.7, 3.9]]
152+
let _: [Any?] = [1, "a", nil, [3.5, "b", nil]]
143153

144-
let a4 = [B(), C()]
145-
let _: Int = a4 // expected-error{{value of type '[A]'}}
154+
let a6 = [B(), C()]
155+
let _: Int = a6 // expected-error{{value of type '[A]'}}
146156
}
147157

148158
/// Check handling of 'nil'.

test/Constraints/dictionary_literal.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ func testDefaultExistentials() {
7272
// expected-error@-1{{heterogeneous collection literal could only be inferred to 'Dictionary<String, Any>'; add explicit type annotation if this is intentional}}{{46-46= as Dictionary<String, Any>}}
7373

7474
let _: [String : Any] = ["a" : 1, "b" : 2.5, "c" : "hello"]
75+
76+
let _ = ["a" : 1, "b" : nil, "c" : "hello"]
77+
// expected-error@-1{{heterogeneous collection literal could only be inferred to 'Dictionary<String, Any?>' (aka 'Dictionary<String, Optional<Any>>'); add explicit type annotation if this is intentional}}{{46-46= as Dictionary<String, Any?>}}
78+
79+
let _: [String : Any?] = ["a" : 1, "b" : nil, "c" : "hello"]
7580

7681
let d2 = [:]
7782
// expected-error@-1{{empty collection literal requires an explicit type}}

0 commit comments

Comments
 (0)