Skip to content

Commit 0ade7b7

Browse files
committed
AST: Type::subst() preserves TypeAliasType sugar
Fixes <rdar://problem/45313760>.
1 parent b1ef4c8 commit 0ade7b7

File tree

11 files changed

+88
-22
lines changed

11 files changed

+88
-22
lines changed

lib/AST/Type.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3261,7 +3261,23 @@ static Type substType(Type derivedType,
32613261
boxTy->getLayout(),
32623262
newSubMap);
32633263
}
3264-
3264+
3265+
// Special-case TypeAliasType; we need to substitute conformances.
3266+
if (auto aliasTy = dyn_cast<TypeAliasType>(type)) {
3267+
Type parentTy;
3268+
if (auto origParentTy = aliasTy->getParent())
3269+
parentTy = substType(origParentTy,
3270+
substitutions, lookupConformances, options);
3271+
auto underlyingTy = substType(aliasTy->getSinglyDesugaredType(),
3272+
substitutions, lookupConformances, options);
3273+
if (parentTy && parentTy->isExistentialType())
3274+
return underlyingTy;
3275+
auto subMap = aliasTy->getSubstitutionMap()
3276+
.subst(substitutions, lookupConformances, options);
3277+
return Type(TypeAliasType::get(aliasTy->getDecl(), parentTy,
3278+
subMap, underlyingTy));
3279+
}
3280+
32653281
// We only substitute for substitutable types and dependent member types.
32663282

32673283
// For dependent member types, we may need to look up the member if the
@@ -3985,7 +4001,7 @@ case TypeKind::Id:
39854001
return *this;
39864002

39874003
return TypeAliasType::get(alias->getDecl(), newParentType, subMap,
3988-
newUnderlyingType);
4004+
newUnderlyingType);
39894005
}
39904006

39914007
case TypeKind::Paren: {

lib/Sema/TypeCheckProtocolInference.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,11 @@ AssociatedTypeInference::getSubstOptionsWithCurrentTypeWitnesses() {
10721072
}
10731073

10741074
Type type = self->typeWitnesses.begin(assocType)->first;
1075+
1076+
// FIXME: Get rid of this hack.
1077+
if (auto *aliasTy = dyn_cast<TypeAliasType>(type.getPointer()))
1078+
type = aliasTy->getSinglyDesugaredType();
1079+
10751080
return type->mapTypeOutOfContext().getPointer();
10761081
};
10771082
return options;

test/Constraints/dictionary_literal.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ useDictStringInt(["Hello" : nil])
3131

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

3636
// Generic dictionary literals.
3737
useDict(["Hello" : 1])
@@ -66,7 +66,7 @@ var _: MyDictionary<String, Int>? = ["foo", 1, "bar", 42] // expected-error {{d
6666
var _: MyDictionary<String, Int>? = ["foo", 1.0, 2] // expected-error {{cannot convert value of type '[Double]' to specified type 'MyDictionary<String, Int>?'}}
6767
// expected-error@-1 {{cannot convert value of type 'String' to expected element type 'Double'}}
6868

69-
var _: MyDictionary<String, Int>? = ["foo" : 1.0] // expected-error {{cannot convert value of type 'Double' to expected dictionary value type 'Int'}}
69+
var _: MyDictionary<String, Int>? = ["foo" : 1.0] // expected-error {{cannot convert value of type 'Double' to expected dictionary value type 'MyDictionary<String, Int>.Value' (aka 'Int')}}
7070

7171

7272
// <rdar://problem/24058895> QoI: Should handle [] in dictionary contexts better

test/Constraints/tuple.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,14 @@ protocol Kingdom {
190190
associatedtype King
191191
}
192192
struct Victory<General> {
193-
init<K: Kingdom>(_ king: K) where K.King == General {} // expected-note {{where 'General' = '(x: Int, y: Int)', 'K.King' = '(Int, Int)'}}
193+
init<K: Kingdom>(_ king: K) where K.King == General {} // expected-note {{where 'General' = '(x: Int, y: Int)', 'K.King' = 'MagicKingdom<(Int, Int)>.King' (aka '(Int, Int)')}}
194194
}
195195
struct MagicKingdom<K> : Kingdom {
196196
typealias King = K
197197
}
198198
func magify<T>(_ t: T) -> MagicKingdom<T> { return MagicKingdom() }
199199
func foo(_ pair: (Int, Int)) -> Victory<(x: Int, y: Int)> {
200-
return Victory(magify(pair)) // expected-error {{initializer 'init(_:)' requires the types '(x: Int, y: Int)' and '(Int, Int)' be equivalent}}
200+
return Victory(magify(pair)) // expected-error {{initializer 'init(_:)' requires the types '(x: Int, y: Int)' and 'MagicKingdom<(Int, Int)>.King' (aka '(Int, Int)') be equivalent}}
201201
}
202202

203203

test/Constraints/tuple_arguments.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,7 +1257,7 @@ do {
12571257
s.requirementTwo(3.0, 4.0)
12581258
s.requirementTwo((3.0, 4.0)) // expected-error {{missing argument for parameter #2 in call}}
12591259

1260-
s.requirementTuple(3.0, 4.0) // expected-error {{instance method 'requirementTuple' expects a single parameter of type '(Double, Double)'}} {{22-22=(}} {{30-30=)}}
1260+
s.requirementTuple(3.0, 4.0) // expected-error {{instance method 'requirementTuple' expects a single parameter of type '(GenericConforms<Double>.Element, GenericConforms<Double>.Element)' (aka '(Double, Double)')}} {{22-22=(}} {{30-30=)}}
12611261
s.requirementTuple((3.0, 4.0))
12621262

12631263
let sTwo = GenericConforms<(Double, Double)>()
@@ -1284,7 +1284,7 @@ do {
12841284
s.requirementTwo(a, b)
12851285
s.requirementTwo((a, b)) // expected-error {{missing argument for parameter #2 in call}}
12861286

1287-
s.requirementTuple(a, b) // expected-error {{instance method 'requirementTuple' expects a single parameter of type '(Double, Double)'}} {{22-22=(}} {{26-26=)}}
1287+
s.requirementTuple(a, b) // expected-error {{instance method 'requirementTuple' expects a single parameter of type '(GenericConforms<Double>.Element, GenericConforms<Double>.Element)' (aka '(Double, Double)')}} {{22-22=(}} {{26-26=)}}
12881288
s.requirementTuple((a, b))
12891289

12901290
let sTwo = GenericConforms<(Double, Double)>()
@@ -1309,7 +1309,7 @@ do {
13091309
s.requirementTwo(a, b)
13101310
s.requirementTwo((a, b)) // expected-error {{missing argument for parameter #2 in call}}
13111311

1312-
s.requirementTuple(a, b) // expected-error {{instance method 'requirementTuple' expects a single parameter of type '(Double, Double)'}} {{22-22=(}} {{26-26=)}}
1312+
s.requirementTuple(a, b) // expected-error {{instance method 'requirementTuple' expects a single parameter of type '(GenericConforms<Double>.Element, GenericConforms<Double>.Element)' (aka '(Double, Double)')}} {{22-22=(}} {{26-26=)}}
13131313
s.requirementTuple((a, b))
13141314

13151315
var sTwo = GenericConforms<(Double, Double)>()
@@ -1331,9 +1331,9 @@ do {
13311331
s.takesClosure({ x in })
13321332
s.takesClosure({ (x: Double) in })
13331333

1334-
s.takesClosureTwo({ _ = $0 }) // expected-error {{contextual closure type '(Double, Double) -> ()' expects 2 arguments, but 1 was used in closure body}}
1335-
s.takesClosureTwo({ x in }) // expected-error {{contextual closure type '(Double, Double) -> ()' expects 2 arguments, but 1 was used in closure body}}
1336-
s.takesClosureTwo({ (x: (Double, Double)) in }) // expected-error {{contextual closure type '(Double, Double) -> ()' expects 2 arguments, but 1 was used in closure body}}
1334+
s.takesClosureTwo({ _ = $0 }) // expected-error {{contextual closure type '(GenericConforms<Double>.Element, GenericConforms<Double>.Element) -> ()' (aka '(Double, Double) -> ()') expects 2 arguments, but 1 was used in closure body}}
1335+
s.takesClosureTwo({ x in }) // expected-error {{contextual closure type '(GenericConforms<Double>.Element, GenericConforms<Double>.Element) -> ()' (aka '(Double, Double) -> ()') expects 2 arguments, but 1 was used in closure body}}
1336+
s.takesClosureTwo({ (x: (Double, Double)) in }) // expected-error {{contextual closure type '(GenericConforms<Double>.Element, GenericConforms<Double>.Element) -> ()' (aka '(Double, Double) -> ()') expects 2 arguments, but 1 was used in closure body}}
13371337
s.takesClosureTwo({ _ = $0; _ = $1 })
13381338
s.takesClosureTwo({ (x, y) in })
13391339
s.takesClosureTwo({ (x: Double, y:Double) in })

test/Generics/deduction.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,20 +208,20 @@ func callMin(_ x: Int, y: Int, a: Float, b: Float) {
208208
min2(a, b) // expected-error{{argument type 'Float' does not conform to expected type 'IsBefore'}}
209209
}
210210

211-
func rangeOfIsBefore<R : IteratorProtocol>(_ range: R) where R.Element : IsBefore {} // expected-note {{'R.Element' = 'Double'}}
211+
func rangeOfIsBefore<R : IteratorProtocol>(_ range: R) where R.Element : IsBefore {} // expected-note {{where 'R.Element' = 'IndexingIterator<[Double]>.Element' (aka 'Double')}}
212212

213213
func callRangeOfIsBefore(_ ia: [Int], da: [Double]) {
214214
rangeOfIsBefore(ia.makeIterator())
215-
rangeOfIsBefore(da.makeIterator()) // expected-error{{global function 'rangeOfIsBefore' requires that 'Double' conform to 'IsBefore'}}
215+
rangeOfIsBefore(da.makeIterator()) // expected-error{{global function 'rangeOfIsBefore' requires that 'IndexingIterator<[Double]>.Element' (aka 'Double') conform to 'IsBefore'}}
216216
}
217217

218218
func testEqualIterElementTypes<A: IteratorProtocol, B: IteratorProtocol>(_ a: A, _ b: B) where A.Element == B.Element {}
219-
// expected-note@-1 {{where 'A.Element' = 'Int', 'B.Element' = 'Double'}}
219+
// expected-note@-1 {{where 'A.Element' = 'IndexingIterator<[Int]>.Element' (aka 'Int'), 'B.Element' = 'IndexingIterator<[Double]>.Element' (aka 'Double')}}
220220
func compareIterators() {
221221
var a: [Int] = []
222222
var b: [Double] = []
223223
testEqualIterElementTypes(a.makeIterator(), b.makeIterator())
224-
// expected-error@-1 {{global function 'testEqualIterElementTypes' requires the types 'Int' and 'Double' be equivalent}}
224+
// expected-error@-1 {{global function 'testEqualIterElementTypes' requires the types 'IndexingIterator<[Int]>.Element' (aka 'Int') and 'IndexingIterator<[Double]>.Element' (aka 'Double') be equivalent}}
225225
}
226226

227227
protocol P_GI {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERRIDE_1 | %FileCheck %s -check-prefix=OVERRIDE_1
2+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERRIDE_2 | %FileCheck %s -check-prefix=OVERRIDE_2
3+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERRIDE_3 | %FileCheck %s -check-prefix=OVERRIDE_3
4+
5+
struct Generic<T> {}
6+
7+
protocol MyProtocol {
8+
associatedtype Result
9+
typealias Arg1 = Generic<Self>
10+
typealias Arg2<X> = Generic<X>
11+
func foo<U>(arg1: Arg1, arg2: Arg2<U>, arg3: Arg2<Int>, arg4: [Arg1], arg5: Arg2<U>? arg6: Generic<Arg2<Generic<Arg2<Int>>>>) -> Result
12+
func bar() -> Result
13+
}
14+
15+
struct MyStruct1 : MyProtocol {
16+
// No 'Result' witness.
17+
func #^OVERRIDE_1^#
18+
}
19+
20+
struct MyStruct2 : MyProtocol {
21+
// Explicit 'Result' witness by 'typealias'.
22+
typealias Result = String
23+
func #^OVERRIDE_2^#
24+
}
25+
26+
struct MyStruct3 : MyProtocol {
27+
// Implicit 'Result' witness by inference.
28+
func bar() -> String
29+
func #^OVERRIDE_3^#
30+
}
31+
32+
// OVERRIDE_1: Begin completions, 2 items
33+
// OVERRIDE_1-DAG: Decl[InstanceMethod]/Super: foo<U>(arg1: MyStruct1.Arg1, arg2: MyStruct1.Arg2<U>, arg3: MyStruct1.Arg2<Int>, arg4: [MyStruct1.Arg1], arg5: MyStruct1.Arg2<U>?, arg6: Generic<MyStruct1.Arg2<Generic<MyStruct1.Arg2<Int>>>>) -> MyStruct1.Result {|};
34+
// OVERRIDE_1-DAG: Decl[InstanceMethod]/Super: bar() -> MyStruct1.Result {|};
35+
// OVERRIDE_1: End completions
36+
37+
// OVERRIDE_2: Begin completions, 2 items
38+
// OVERRIDE_2-DAG: Decl[InstanceMethod]/Super: foo<U>(arg1: MyStruct2.Arg1, arg2: MyStruct2.Arg2<U>, arg3: MyStruct2.Arg2<Int>, arg4: [MyStruct2.Arg1], arg5: MyStruct2.Arg2<U>?, arg6: Generic<MyStruct2.Arg2<Generic<MyStruct2.Arg2<Int>>>>) -> String {|};
39+
// OVERRIDE_2-DAG: Decl[InstanceMethod]/Super: bar() -> String {|};
40+
// OVERRIDE_2: End completions
41+
42+
// OVERRIDE_3-DAG: Begin completions, 1 items
43+
// OVERRIDE_3-DAG: Decl[InstanceMethod]/Super: foo<U>(arg1: MyStruct3.Arg1, arg2: MyStruct3.Arg2<U>, arg3: MyStruct3.Arg2<Int>, arg4: [MyStruct3.Arg1], arg5: MyStruct3.Arg2<U>?, arg6: Generic<MyStruct3.Arg2<Generic<MyStruct3.Arg2<Int>>>>) -> String {|};
44+
// OVERRIDE_3-DAG: End completions
45+

test/decl/typealias/generic.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ class GenericClass<T> {
158158
}
159159

160160
func testCaptureInvalid1<S>(s: S, t: T) -> TA<Int> {
161-
return TA<S>(a: t, b: s) // expected-error {{cannot convert return expression of type 'GenericClass<T>.TA<S>' (aka 'MyType<T, S>') to return type 'MyType<T, Int>'}}
161+
return TA<S>(a: t, b: s) // expected-error {{cannot convert return expression of type 'GenericClass<T>.TA<S>' (aka 'MyType<T, S>') to return type 'GenericClass<T>.TA<Int>' (aka 'MyType<T, Int>')}}
162162
}
163163

164164
func testCaptureInvalid2<S>(s: Int, t: T) -> TA<S> {

test/expr/capture/generic_params.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ func outerGeneric<T>(t: T, x: AnyObject) {
2929
// CHECK: func_decl{{.*}}"localFunction(tt:)" interface type='<T> (tt: TT) -> ()' {{.*}} captures=(<generic> )
3030
func localFunction(tt: TT) {}
3131

32-
// CHECK: closure_expr type='((a: T, b: T)) -> ()' {{.*}} captures=(<generic> )
32+
// CHECK: closure_expr type='(TT) -> ()' {{.*}} captures=(<generic> )
3333
let _: (TT) -> () = { _ in }
3434
}

test/stmt/foreach.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ func patterns(gir: GoodRange<Int>, gtr: GoodTupleIterator) {
6060
var sumf : Float
6161
for i : Int in gir { sum = sum + i }
6262
for i in gir { sum = sum + i }
63-
for f : Float in gir { sum = sum + f } // expected-error{{cannot convert sequence element type 'Int' to expected type 'Float'}}
64-
for f : ElementProtocol in gir { } // expected-error {{sequence element type 'Int' does not conform to expected protocol 'ElementProtocol'}}
63+
for f : Float in gir { sum = sum + f } // expected-error{{cannot convert sequence element type 'GoodRange<Int>.Element' (aka 'Int') to expected type 'Float'}}
64+
for f : ElementProtocol in gir { } // expected-error {{sequence element type 'GoodRange<Int>.Element' (aka 'Int') does not conform to expected protocol 'ElementProtocol'}}
6565

6666
for (i, f) : (Int, Float) in gtr { sum = sum + i }
6767

0 commit comments

Comments
 (0)