Skip to content

Commit 0c7ec65

Browse files
committed
[Type checker] Array/dictionary literals define to Swift.(Array|Dictionary)
The type checker was performing local name lookup to find the Array and Dictionary types to use as defaults for array and dictionary literals. Make sure we only look for Swift.Array and Swift.Dictionary. Fixes SR-9611 / rdar://problem/47085684. (cherry picked from commit 90a8aaa)
1 parent 5bf394d commit 0c7ec65

File tree

3 files changed

+31
-19
lines changed

3 files changed

+31
-19
lines changed

lib/Sema/TypeCheckExpr.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,7 @@ static Type lookupDefaultLiteralType(TypeChecker &TC, DeclContext *dc,
658658
Type TypeChecker::getDefaultType(ProtocolDecl *protocol, DeclContext *dc) {
659659
Type *type = nullptr;
660660
const char *name = nullptr;
661+
bool performLocalLookup = true;
661662

662663
// ExpressibleByUnicodeScalarLiteral -> UnicodeScalarType
663664
if (protocol ==
@@ -711,13 +712,15 @@ Type TypeChecker::getDefaultType(ProtocolDecl *protocol, DeclContext *dc) {
711712
KnownProtocolKind::ExpressibleByArrayLiteral)){
712713
type = &ArrayLiteralType;
713714
name = "Array";
715+
performLocalLookup = false;
714716
}
715717
// ExpressibleByDictionaryLiteral -> Dictionary
716718
else if (protocol == getProtocol(
717719
SourceLoc(),
718720
KnownProtocolKind::ExpressibleByDictionaryLiteral)) {
719721
type = &DictionaryLiteralType;
720722
name = "Dictionary";
723+
performLocalLookup = false;
721724
}
722725
// _ExpressibleByColorLiteral -> _ColorLiteralType
723726
else if (protocol == getProtocol(
@@ -746,7 +749,8 @@ Type TypeChecker::getDefaultType(ProtocolDecl *protocol, DeclContext *dc) {
746749

747750
// If we haven't found the type yet, look for it now.
748751
if (!*type) {
749-
*type = lookupDefaultLiteralType(*this, dc, name);
752+
if (performLocalLookup)
753+
*type = lookupDefaultLiteralType(*this, dc, name);
750754

751755
if (!*type)
752756
*type = lookupDefaultLiteralType(*this, getStdlibModule(dc), name);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// SR-9611: Array type locally interfers with array literals.
4+
struct Array { }
5+
6+
func foo() {
7+
_ = ["a", "b", "c"]
8+
}

test/Constraints/dictionary_literal.swift

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ final class DictStringInt : ExpressibleByDictionaryLiteral {
66
init(dictionaryLiteral elements: (String, Int)...) { }
77
}
88

9-
final class Dictionary<K, V> : ExpressibleByDictionaryLiteral {
9+
final class MyDictionary<K, V> : ExpressibleByDictionaryLiteral {
1010
typealias Key = K
1111
typealias Value = V
1212
init(dictionaryLiteral elements: (K, V)...) { }
1313
}
1414

1515
func useDictStringInt(_ d: DictStringInt) {}
16-
func useDict<K, V>(_ d: Dictionary<K,V>) {}
16+
func useDict<K, V>(_ d: MyDictionary<K,V>) {}
1717

1818
// Concrete dictionary literals.
1919
useDictStringInt(["Hello" : 1])
@@ -30,7 +30,7 @@ useDictStringInt(["Hello" : nil])
3030
// expected-error@-1 {{'nil' is not compatible with expected dictionary value type 'Int'}}
3131

3232
typealias FuncBoolToInt = (Bool) -> Int
33-
let dict1: Dictionary<String, FuncBoolToInt> = ["Hello": nil]
33+
let dict1: MyDictionary<String, FuncBoolToInt> = ["Hello": nil]
3434
// expected-error@-1 {{'nil' is not compatible with expected dictionary value type '(Bool) -> Int'}}
3535

3636
// Generic dictionary literals.
@@ -39,7 +39,7 @@ useDict(["Hello" : 1, "World" : 2])
3939
useDict(["Hello" : 1.5, "World" : 2])
4040
useDict([1 : 1.5, 3 : 2.5])
4141

42-
// Fall back to Dictionary<K, V> if no context is otherwise available.
42+
// Fall back to Swift.Dictionary<K, V> if no context is otherwise available.
4343
var a = ["Hello" : 1, "World" : 2]
4444
var a2 : Dictionary<String, Int> = a
4545
var a3 = ["Hello" : 1]
@@ -52,20 +52,20 @@ var b3 = [1 : 2.5]
5252
// <rdar://problem/22584076> QoI: Using array literal init with dictionary produces bogus error
5353

5454
// expected-note @+1 {{did you mean to use a dictionary literal instead?}}
55-
var _: Dictionary<String, (Int) -> Int>? = [ // expected-error {{dictionary of type 'Dictionary<String, (Int) -> Int>' cannot be initialized with array literal}}
55+
var _: MyDictionary<String, (Int) -> Int>? = [ // expected-error {{dictionary of type 'MyDictionary<String, (Int) -> Int>' cannot be initialized with array literal}}
5656
"closure_1" as String, {(Int) -> Int in 0},
5757
"closure_2", {(Int) -> Int in 0}]
5858

5959

60-
var _: Dictionary<String, Int>? = ["foo", 1] // expected-error {{dictionary of type 'Dictionary<String, Int>' cannot be initialized with array literal}}
61-
// expected-note @-1 {{did you mean to use a dictionary literal instead?}} {{41-42=:}}
60+
var _: MyDictionary<String, Int>? = ["foo", 1] // expected-error {{dictionary of type 'MyDictionary<String, Int>' cannot be initialized with array literal}}
61+
// expected-note @-1 {{did you mean to use a dictionary literal instead?}} {{43-44=:}}
6262

63-
var _: Dictionary<String, Int>? = ["foo", 1, "bar", 42] // expected-error {{dictionary of type 'Dictionary<String, Int>' cannot be initialized with array literal}}
64-
// expected-note @-1 {{did you mean to use a dictionary literal instead?}} {{41-42=:}} {{51-52=:}}
63+
var _: MyDictionary<String, Int>? = ["foo", 1, "bar", 42] // expected-error {{dictionary of type 'MyDictionary<String, Int>' cannot be initialized with array literal}}
64+
// expected-note @-1 {{did you mean to use a dictionary literal instead?}} {{43-44=:}} {{53-54=:}}
6565

66-
var _: Dictionary<String, Int>? = ["foo", 1.0, 2] // expected-error {{cannot convert value of type '[Any]' to specified type 'Dictionary<String, Int>?'}}
66+
var _: MyDictionary<String, Int>? = ["foo", 1.0, 2] // expected-error {{cannot convert value of type '[Any]' to specified type 'MyDictionary<String, Int>?'}}
6767

68-
var _: Dictionary<String, Int>? = ["foo" : 1.0] // expected-error {{cannot convert value of type 'Double' to expected dictionary value type 'Int'}}
68+
var _: MyDictionary<String, Int>? = ["foo" : 1.0] // expected-error {{cannot convert value of type 'Double' to expected dictionary value type 'Int'}}
6969

7070

7171
// <rdar://problem/24058895> QoI: Should handle [] in dictionary contexts better
@@ -78,33 +78,33 @@ class C : A { }
7878

7979
func testDefaultExistentials() {
8080
let _ = ["a" : 1, "b" : 2.5, "c" : "hello"]
81-
// 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>}}
81+
// expected-error@-1{{heterogeneous collection literal could only be inferred to '[String : Any]'; add explicit type annotation if this is intentional}}{{46-46= as [String : Any]}}
8282

8383
let _: [String : Any] = ["a" : 1, "b" : 2.5, "c" : "hello"]
8484

8585
let _ = ["a" : 1, "b" : nil, "c" : "hello"]
86-
// 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?>}}
86+
// expected-error@-1{{heterogeneous collection literal could only be inferred to '[String : Any?]'; add explicit type annotation if this is intentional}}{{46-46= as [String : Any?]}}
8787

8888
let _: [String : Any?] = ["a" : 1, "b" : nil, "c" : "hello"]
8989

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

93-
let _: Int = d2 // expected-error{{value of type 'Dictionary<AnyHashable, Any>'}}
93+
let _: Int = d2 // expected-error{{value of type '[AnyHashable : Any]'}}
9494

9595
let _ = ["a": 1,
9696
"b": ["a", 2, 3.14159],
9797
"c": ["a": 2, "b": 3.5]]
98-
// expected-error@-3{{heterogeneous collection literal could only be inferred to 'Dictionary<String, Any>'; add explicit type annotation if this is intentional}}
98+
// expected-error@-3{{heterogeneous collection literal could only be inferred to '[String : Any]'; add explicit type annotation if this is intentional}}
9999

100100
let d3 = ["b" : B(), "c" : C()]
101-
let _: Int = d3 // expected-error{{value of type 'Dictionary<String, A>'}}
101+
let _: Int = d3 // expected-error{{value of type '[String : A]'}}
102102

103103
let _ = ["a" : B(), 17 : "seventeen", 3.14159 : "Pi"]
104-
// expected-error@-1{{heterogeneous collection literal could only be inferred to 'Dictionary<AnyHashable, Any>'}}
104+
// expected-error@-1{{heterogeneous collection literal could only be inferred to '[AnyHashable : Any]'}}
105105

106106
let _ = ["a" : "hello", 17 : "string"]
107-
// expected-error@-1{{heterogeneous collection literal could only be inferred to 'Dictionary<AnyHashable, String>'}}
107+
// expected-error@-1{{heterogeneous collection literal could only be inferred to '[AnyHashable : String]'}}
108108
}
109109

110110
// SR-4952, rdar://problem/32330004 - Assertion failure during swift::ASTVisitor<::FailureDiagnosis,...>::visit

0 commit comments

Comments
 (0)