Skip to content

Commit 7104d8f

Browse files
authored
Merge pull request #75875 from slavapestov/type-subst-rework
Start of Type::subst() rework
2 parents 9315673 + 3c5298f commit 7104d8f

File tree

7 files changed

+104
-72
lines changed

7 files changed

+104
-72
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ class ASTMangler : public Mangler {
680680

681681
void appendClosureEntity(const AbstractClosureExpr *closure);
682682

683-
void appendClosureComponents(Type Ty, unsigned discriminator, bool isImplicit,
683+
void appendClosureComponents(CanType Ty, unsigned discriminator, bool isImplicit,
684684
const DeclContext *parentContext,
685685
ArrayRef<GenericEnvironment *> capturedEnvs);
686686

include/swift/AST/TypeTransform.h

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -367,30 +367,13 @@ case TypeKind::Id:
367367

368368
case TypeKind::OpaqueTypeArchetype: {
369369
auto opaque = cast<OpaqueTypeArchetypeType>(base);
370-
if (opaque->getSubstitutions().empty())
370+
auto subMap = opaque->getSubstitutions();
371+
auto newSubMap = asDerived().transformSubMap(subMap);
372+
if (newSubMap == subMap)
371373
return t;
372-
373-
SmallVector<Type, 4> newSubs;
374-
bool anyChanged = false;
375-
for (auto replacement : opaque->getSubstitutions().getReplacementTypes()) {
376-
Type newReplacement = doIt(replacement, TypePosition::Invariant);
377-
if (!newReplacement)
378-
return Type();
379-
newSubs.push_back(newReplacement);
380-
if (replacement.getPointer() != newReplacement.getPointer())
381-
anyChanged = true;
382-
}
383-
384-
if (!anyChanged)
385-
return t;
386-
387-
// FIXME: This re-looks-up conformances instead of transforming them in
388-
// a systematic way.
389-
auto sig = opaque->getDecl()->getGenericSignature();
390-
auto newSubMap =
391-
SubstitutionMap::get(sig,
392-
QueryReplacementTypeArray{sig, newSubs},
393-
LookUpConformanceInModule());
374+
if (!newSubMap)
375+
return Type();
376+
394377
return OpaqueTypeArchetypeType::get(opaque->getDecl(),
395378
opaque->getInterfaceType(),
396379
newSubMap);
@@ -999,6 +982,32 @@ case TypeKind::Id:
999982

1000983
llvm_unreachable("Unhandled type in transformation");
1001984
}
985+
986+
// If original was non-empty and transformed is empty, we're
987+
// signaling failure, that is, a Type() return from doIt().
988+
SubstitutionMap transformSubMap(SubstitutionMap subs) {
989+
if (subs.empty())
990+
return subs;
991+
992+
SmallVector<Type, 4> newSubs;
993+
bool anyChanged = false;
994+
for (auto replacement : subs.getReplacementTypes()) {
995+
Type newReplacement = doIt(replacement, TypePosition::Invariant);
996+
if (!newReplacement)
997+
return SubstitutionMap();
998+
newSubs.push_back(newReplacement);
999+
if (replacement.getPointer() != newReplacement.getPointer())
1000+
anyChanged = true;
1001+
}
1002+
1003+
if (!anyChanged)
1004+
return subs;
1005+
1006+
auto sig = subs.getGenericSignature();
1007+
return SubstitutionMap::get(sig,
1008+
QueryReplacementTypeArray{sig, newSubs},
1009+
LookUpConformanceInModule());
1010+
}
10021011
};
10031012

10041013
}

lib/AST/ASTMangler.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3752,10 +3752,12 @@ void ASTMangler::appendAssociatedTypeName(DependentMemberType *dmt,
37523752

37533753
void ASTMangler::appendClosureEntity(
37543754
const SerializedAbstractClosureExpr *closure) {
3755-
assert(!closure->getType()->hasLocalArchetype() &&
3755+
auto canType = closure->getType()->getCanonicalType();
3756+
assert(!canType->hasLocalArchetype() &&
37563757
"Not enough information here to handle this case");
37573758

3758-
appendClosureComponents(closure->getType(), closure->getDiscriminator(),
3759+
appendClosureComponents(canType,
3760+
closure->getDiscriminator(),
37593761
closure->isImplicit(), closure->getParent(),
37603762
ArrayRef<GenericEnvironment *>());
37613763
}
@@ -3769,17 +3771,18 @@ void ASTMangler::appendClosureEntity(const AbstractClosureExpr *closure) {
37693771
// code; the type-checker currently isn't strict about producing typed
37703772
// expression nodes when it fails. Once we enforce that, we can remove this.
37713773
if (!type)
3772-
type = ErrorType::get(closure->getASTContext());
3774+
type = CanType(ErrorType::get(closure->getASTContext()));
37733775

3774-
if (type->hasLocalArchetype())
3776+
auto canType = type->getCanonicalType();
3777+
if (canType->hasLocalArchetype())
37753778
capturedEnvs = closure->getCaptureInfo().getGenericEnvironments();
37763779

3777-
appendClosureComponents(type, closure->getDiscriminator(),
3780+
appendClosureComponents(canType, closure->getDiscriminator(),
37783781
isa<AutoClosureExpr>(closure), closure->getParent(),
37793782
capturedEnvs);
37803783
}
37813784

3782-
void ASTMangler::appendClosureComponents(Type Ty, unsigned discriminator,
3785+
void ASTMangler::appendClosureComponents(CanType Ty, unsigned discriminator,
37833786
bool isImplicit,
37843787
const DeclContext *parentContext,
37853788
ArrayRef<GenericEnvironment *> capturedEnvs) {
@@ -3793,9 +3796,9 @@ void ASTMangler::appendClosureComponents(Type Ty, unsigned discriminator,
37933796

37943797
Ty = Ty.subst(MapLocalArchetypesOutOfContext(Sig, capturedEnvs),
37953798
MakeAbstractConformanceForGenericType(),
3796-
SubstFlags::PreservePackExpansionLevel);
3799+
SubstFlags::PreservePackExpansionLevel)->getCanonicalType();
37973800

3798-
appendType(Ty->getCanonicalType(), Sig);
3801+
appendType(Ty, Sig);
37993802
appendOperator(isImplicit ? "fu" : "fU", Index(discriminator));
38003803
}
38013804

lib/AST/TypeSubstitution.cpp

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,8 @@ class TypeSubstituter : public TypeTransform<TypeSubstituter> {
489489
: level(level), IFS(IFS) {}
490490

491491
std::optional<Type> transform(TypeBase *type, TypePosition position);
492+
493+
SubstitutionMap transformSubstitutionMap(SubstitutionMap subs);
492494
};
493495

494496
}
@@ -624,6 +626,11 @@ TypeSubstituter::transform(TypeBase *type, TypePosition position) {
624626
level);
625627
}
626628

629+
SubstitutionMap TypeSubstituter::transformSubstitutionMap(SubstitutionMap subs) {
630+
// FIXME: Take level into account? Move level down into IFS?
631+
return subs.subst(IFS);
632+
}
633+
627634
Type Type::subst(SubstitutionMap substitutions,
628635
SubstOptions options) const {
629636
InFlightSubstitutionViaSubMap IFS(substitutions, options);
@@ -1038,18 +1045,6 @@ Type TypeBase::adjustSuperclassMemberDeclType(const ValueDecl *baseDecl,
10381045
// Replacing opaque result archetypes with their underlying types
10391046
//===----------------------------------------------------------------------===//
10401047

1041-
static std::optional<std::pair<ArchetypeType *, OpaqueTypeArchetypeType *>>
1042-
getArchetypeAndRootOpaqueArchetype(Type maybeOpaqueType) {
1043-
auto archetype = dyn_cast<ArchetypeType>(maybeOpaqueType.getPointer());
1044-
if (!archetype)
1045-
return std::nullopt;
1046-
auto opaqueRoot = dyn_cast<OpaqueTypeArchetypeType>(archetype->getRoot());
1047-
if (!opaqueRoot)
1048-
return std::nullopt;
1049-
1050-
return std::make_pair(archetype, opaqueRoot);
1051-
}
1052-
10531048
OpaqueSubstitutionKind
10541049
ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution(
10551050
OpaqueTypeDecl *opaque) const {
@@ -1187,19 +1182,20 @@ ReplaceOpaqueTypesWithUnderlyingTypes::ReplaceOpaqueTypesWithUnderlyingTypes(
11871182

11881183
Type ReplaceOpaqueTypesWithUnderlyingTypes::
11891184
operator()(SubstitutableType *maybeOpaqueType) const {
1190-
auto archetypeAndRoot = getArchetypeAndRootOpaqueArchetype(maybeOpaqueType);
1191-
if (!archetypeAndRoot)
1185+
auto *archetype = dyn_cast<OpaqueTypeArchetypeType>(maybeOpaqueType);
1186+
if (!archetype)
11921187
return maybeOpaqueType;
11931188

1194-
auto archetype = archetypeAndRoot->first;
1195-
auto opaqueRoot = archetypeAndRoot->second;
1189+
auto *genericEnv = archetype->getGenericEnvironment();
1190+
auto *decl = genericEnv->getOpaqueTypeDecl();
1191+
auto outerSubs = genericEnv->getOpaqueSubstitutions();
11961192

1197-
auto substitutionKind = shouldPerformSubstitution(opaqueRoot->getDecl());
1193+
auto substitutionKind = shouldPerformSubstitution(decl);
11981194
if (substitutionKind == OpaqueSubstitutionKind::DontSubstitute) {
11991195
return maybeOpaqueType;
12001196
}
12011197

1202-
auto subs = opaqueRoot->getDecl()->getUniqueUnderlyingTypeSubstitutions();
1198+
auto subs = decl->getUniqueUnderlyingTypeSubstitutions();
12031199
// If the body of the opaque decl providing decl has not been type checked we
12041200
// don't have a underlying substitution.
12051201
if (!subs.has_value())
@@ -1231,11 +1227,11 @@ operator()(SubstitutableType *maybeOpaqueType) const {
12311227
// for its type arguments. We perform this substitution after checking for
12321228
// visibility, since we do not want the result of the visibility check to
12331229
// depend on the substitutions previously applied.
1234-
auto substTy = partialSubstTy.subst(opaqueRoot->getSubstitutions());
1230+
auto substTy = partialSubstTy.subst(outerSubs);
12351231

12361232
// If the type changed, but still contains opaque types, recur.
12371233
if (!substTy->isEqual(maybeOpaqueType) && substTy->hasOpaqueArchetype()) {
1238-
SeenDecl seenKey(opaqueRoot->getDecl(), opaqueRoot->getSubstitutions());
1234+
SeenDecl seenKey(decl, outerSubs);
12391235
if (auto *alreadySeen = this->seenDecls) {
12401236
// Detect substitution loops. If we find one, just bounce the original
12411237
// type back to the caller. This substitution will fail at runtime
@@ -1305,8 +1301,8 @@ operator()(CanType maybeOpaqueType, Type replacementType,
13051301
ProtocolDecl *protocol) const {
13061302
auto abstractRef = ProtocolConformanceRef(protocol);
13071303

1308-
auto archetypeAndRoot = getArchetypeAndRootOpaqueArchetype(maybeOpaqueType);
1309-
if (!archetypeAndRoot) {
1304+
auto archetype = dyn_cast<OpaqueTypeArchetypeType>(maybeOpaqueType);
1305+
if (!archetype) {
13101306
if (maybeOpaqueType->isTypeParameter() ||
13111307
maybeOpaqueType->is<ArchetypeType>())
13121308
return abstractRef;
@@ -1320,15 +1316,16 @@ operator()(CanType maybeOpaqueType, Type replacementType,
13201316
llvm_unreachable("origType should have been an opaque type or type parameter");
13211317
}
13221318

1323-
auto archetype = archetypeAndRoot->first;
1324-
auto opaqueRoot = archetypeAndRoot->second;
1319+
auto *genericEnv = archetype->getGenericEnvironment();
1320+
auto *decl = genericEnv->getOpaqueTypeDecl();
1321+
auto outerSubs = genericEnv->getOpaqueSubstitutions();
13251322

1326-
auto substitutionKind = shouldPerformSubstitution(opaqueRoot->getDecl());
1323+
auto substitutionKind = shouldPerformSubstitution(decl);
13271324
if (substitutionKind == OpaqueSubstitutionKind::DontSubstitute) {
13281325
return abstractRef;
13291326
}
13301327

1331-
auto subs = opaqueRoot->getDecl()->getUniqueUnderlyingTypeSubstitutions();
1328+
auto subs = decl->getUniqueUnderlyingTypeSubstitutions();
13321329
// If the body of the opaque decl providing decl has not been type checked we
13331330
// don't have a underlying substitution.
13341331
if (!subs.has_value())
@@ -1359,16 +1356,16 @@ operator()(CanType maybeOpaqueType, Type replacementType,
13591356
// for its type arguments. We perform this substitution after checking for
13601357
// visibility, since we do not want the result of the visibility check to
13611358
// depend on the substitutions previously applied.
1362-
auto substTy = partialSubstTy.subst(opaqueRoot->getSubstitutions());
1359+
auto substTy = partialSubstTy.subst(outerSubs);
13631360

13641361
auto partialSubstRef =
13651362
abstractRef.subst(archetype->getInterfaceType(), *subs);
13661363
auto substRef =
1367-
partialSubstRef.subst(partialSubstTy, opaqueRoot->getSubstitutions());
1364+
partialSubstRef.subst(partialSubstTy, outerSubs);
13681365

13691366
// If the type still contains opaque types, recur.
13701367
if (substTy->hasOpaqueArchetype()) {
1371-
SeenDecl seenKey(opaqueRoot->getDecl(), opaqueRoot->getSubstitutions());
1368+
SeenDecl seenKey(decl, outerSubs);
13721369

13731370
if (auto *alreadySeen = this->seenDecls) {
13741371
// Detect substitution loops. If we find one, just bounce the original

lib/IRGen/GenProto.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1764,11 +1764,7 @@ void WitnessTableBuilderBase::defineAssociatedTypeWitnessTableAccessFunction(
17641764
CanType associatedType,
17651765
ProtocolConformanceRef associatedConformance) {
17661766
bool hasArchetype = associatedType->hasArchetype();
1767-
OpaqueTypeArchetypeType *associatedRootOpaqueType = nullptr;
1768-
if (auto assocArchetype = dyn_cast<ArchetypeType>(associatedType)) {
1769-
associatedRootOpaqueType = dyn_cast<OpaqueTypeArchetypeType>(
1770-
assocArchetype->getRoot());
1771-
}
1767+
bool isOpaqueArchetype = isa<OpaqueTypeArchetypeType>(associatedType);
17721768

17731769
assert(isa<NormalProtocolConformance>(Conformance) && "has associated type");
17741770

@@ -1827,7 +1823,7 @@ void WitnessTableBuilderBase::defineAssociatedTypeWitnessTableAccessFunction(
18271823
}
18281824

18291825
// If there are no archetypes, return a reference to the table.
1830-
if (!hasArchetype && !associatedRootOpaqueType) {
1826+
if (!hasArchetype && !isOpaqueArchetype) {
18311827
auto wtable = conformanceI->getTable(IGF, &associatedTypeMetadata);
18321828
IGF.Builder.CreateRet(wtable);
18331829
return;

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2012,22 +2012,22 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function,
20122012

20132013
auto options = SILParameterInfo::Options();
20142014

2015-
Type type;
2015+
CanType type;
20162016
VarDecl *varDecl = nullptr;
20172017
if (auto *expr = capture.getPackElement()) {
2018-
type = expr->getType();
2018+
type = expr->getType()->getCanonicalType();
20192019
} else {
20202020
varDecl = cast<VarDecl>(capture.getDecl());
2021-
type = varDecl->getTypeInContext();
2021+
type = varDecl->getTypeInContext()->getCanonicalType();
20222022

20232023
// If we're capturing a parameter pack, wrap it in a tuple.
2024-
if (type->is<PackExpansionType>()) {
2024+
if (isa<PackExpansionType>(type)) {
20252025
assert(!cast<ParamDecl>(varDecl)->supportsMutation() &&
20262026
"Cannot capture a pack as an lvalue");
20272027

20282028
SmallVector<TupleTypeElt, 1> elts;
20292029
elts.push_back(type);
2030-
type = TupleType::get(elts, TC.Context);
2030+
type = CanType(TupleType::get(elts, TC.Context));
20312031
}
20322032

20332033
if (isolatedParam == varDecl) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
2+
3+
struct S {
4+
var y: Int { fatalError() }
5+
}
6+
7+
struct G<Element> {
8+
func f<T>(_: (Element) -> T) -> [T] { fatalError() }
9+
}
10+
11+
protocol P {
12+
typealias A = S
13+
var x: G<A> { get }
14+
}
15+
16+
// CHECK-LABEL: sil private [ossa] @$s29phantom_existential_typealias5test11pSaySiGAA1P_p_tFSiAA1SVXEfU_ : $@convention(thin) @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <S, Int> {
17+
18+
func test1(p: any P) -> [Int] {
19+
return p.x.f { $0.y }
20+
}
21+
22+
func callee(_: () -> ()) {}
23+
24+
func test2(p: any P) {
25+
let a = p.x
26+
callee { _ = a }
27+
}

0 commit comments

Comments
 (0)