Skip to content

Commit 074684f

Browse files
committed
AST: Use TypeTransform::transformSubMap() to transform TypeAliasType
1 parent ae77d6f commit 074684f

File tree

6 files changed

+62
-30
lines changed

6 files changed

+62
-30
lines changed

include/swift/AST/TypeTransform.h

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -433,23 +433,28 @@ case TypeKind::Id:
433433
if (!newParentType) return newUnderlyingTy;
434434
}
435435

436-
auto subMap = alias->getSubstitutionMap();
437-
for (Type oldReplacementType : subMap.getReplacementTypes()) {
438-
Type newReplacementType = doIt(oldReplacementType, TypePosition::Invariant);
439-
if (!newReplacementType)
440-
return newUnderlyingTy;
441-
442-
// If anything changed with the replacement type, we lose the sugar.
443-
// FIXME: This is really unfortunate.
444-
if (newReplacementType.getPointer() != oldReplacementType.getPointer())
445-
return newUnderlyingTy;
446-
}
436+
if (newParentType && newParentType->isExistentialType())
437+
return newUnderlyingTy;
438+
439+
auto oldSubMap = alias->getSubstitutionMap();
440+
auto newSubMap = asDerived().transformSubMap(oldSubMap);
441+
if (oldSubMap && !newSubMap)
442+
return Type();
447443

448444
if (oldParentType.getPointer() == newParentType.getPointer() &&
449-
oldUnderlyingTy.getPointer() == newUnderlyingTy.getPointer())
445+
oldUnderlyingTy.getPointer() == newUnderlyingTy.getPointer() &&
446+
oldSubMap == newSubMap)
450447
return t;
451448

452-
return TypeAliasType::get(alias->getDecl(), newParentType, subMap,
449+
// Don't leave local archetypes and type variables behind in sugar
450+
// if they don't appear in the underlying type, to avoid confusion.
451+
auto props = newSubMap.getRecursiveProperties();
452+
if (props.hasLocalArchetype() && !newUnderlyingTy->hasLocalArchetype())
453+
return newUnderlyingTy;
454+
if (props.hasTypeVariable() && !newUnderlyingTy->hasTypeVariable())
455+
return newUnderlyingTy;
456+
457+
return TypeAliasType::get(alias->getDecl(), newParentType, newSubMap,
453458
newUnderlyingTy);
454459
}
455460

lib/AST/TypeSubstitution.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -536,20 +536,6 @@ TypeSubstituter::transform(TypeBase *type, TypePosition position) {
536536
return std::nullopt;
537537
}
538538

539-
// Special-case TypeAliasType; we need to substitute conformances.
540-
if (auto aliasTy = dyn_cast<TypeAliasType>(type)) {
541-
Type parentTy;
542-
if (auto origParentTy = aliasTy->getParent())
543-
parentTy = doIt(origParentTy, TypePosition::Invariant);
544-
auto underlyingTy = doIt(aliasTy->getSinglyDesugaredType(),
545-
TypePosition::Invariant);
546-
if (parentTy && parentTy->isExistentialType())
547-
return underlyingTy;
548-
auto subMap = aliasTy->getSubstitutionMap().subst(IFS);
549-
return Type(TypeAliasType::get(aliasTy->getDecl(), parentTy,
550-
subMap, underlyingTy));
551-
}
552-
553539
auto oldLevel = level;
554540
SWIFT_DEFER { level = oldLevel; };
555541

test/Constraints/closures.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ func rdar21078316() {
389389

390390
// <rdar://problem/20978044> QoI: Poor diagnostic when using an incorrect tuple element in a closure
391391
var numbers = [1, 2, 3]
392-
zip(numbers, numbers).filter { $0.2 > 1 } // expected-error {{value of tuple type '(Int, Int)' has no member '2'}}
392+
zip(numbers, numbers).filter { $0.2 > 1 } // expected-error {{value of tuple type 'Zip2Sequence<[Int], [Int]>.Element' (aka '(Int, Int)') has no member '2'}}
393393

394394

395395

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// This is an elaborate reduction for a problem where we create a TypeAliasType
4+
// with a concrete underlying type, but type variables in its substitutions.
5+
//
6+
// Specifically, we get something like `G<$1, $2>.B` below, but the underlying
7+
// type of B is just S, it does not depend on its generic arguments.
8+
//
9+
// The solver doesn't simplify the type variables away in this case, so to
10+
// avoid problems the TypeTransform desugars the typealias in this case.
11+
12+
public protocol P {
13+
associatedtype A
14+
}
15+
16+
public struct Horse<A>: P {}
17+
18+
public struct S {}
19+
20+
@resultBuilder
21+
public enum E<A, B> {
22+
public static func buildExpression<T: P>(_ t: T) -> T where T.A == A {
23+
return t
24+
}
25+
26+
public static func buildBlock<T: P>(_ t: T) -> T {
27+
return t
28+
}
29+
}
30+
31+
public struct G<A, C: P> where C.A == A {
32+
public typealias B = S
33+
34+
public init(_: A.Type, @E<A, B> _: () -> C) {}
35+
}
36+
37+
func testHorse() {
38+
_ = G(S.self) {
39+
Horse()
40+
}
41+
}

test/IDE/complete_call_arg.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1119,7 +1119,7 @@ func testLValueBaseTyOfSubscript() {
11191119
var cache: [String: Codable] = [:]
11201120
if let cached = cache[#^LVALUEBASETY^#
11211121

1122-
// LVALUEBASETY-DAG: Decl[Subscript]/CurrNominal/Flair[ArgLabels]/IsSystem: ['[']{#(position): Dictionary<String, any Codable>.Index#}[']'][#(key: String, value: any Codable)#];
1122+
// LVALUEBASETY-DAG: Decl[Subscript]/CurrNominal/Flair[ArgLabels]/IsSystem: ['[']{#(position): Dictionary<String, any Codable>.Index#}[']'][#Dictionary<String, any Codable>.Element#];
11231123
// LVALUEBASETY-DAG: Decl[Subscript]/CurrNominal/Flair[ArgLabels]/IsSystem: ['[']{#(key): String#}[']'][#@lvalue (any Codable)?#];
11241124
}
11251125

test/Macros/macro_default_argument_diagnostics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,5 @@ func testIdentifier(notOkay: Stringified<String> = #stringify(myString)) {}
5555
// expected-error@+1{{only literals are permitted}}
5656
func testString(interpolated: Stringified<String> = #stringify("Hello \(0b10001)")) {}
5757

58-
// expected-error@+1{{default argument value of type '(Int, String)' cannot be converted to type 'Int'}}
58+
// expected-error@+1{{default argument value of type 'Stringified<Int>' (aka '(Int, String)') cannot be converted to type 'Int'}}
5959
func testReturn(wrongType: Int = #stringify(0)) {}

0 commit comments

Comments
 (0)