Skip to content

Commit 3992fd9

Browse files
authored
Merge pull request #80327 from slavapestov/fix-useless-method
Small fixes for new abstract conformance representation
2 parents 8c8ed34 + 865c040 commit 3992fd9

File tree

7 files changed

+81
-66
lines changed

7 files changed

+81
-66
lines changed

include/swift/AST/TypeTransform.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ case TypeKind::Id:
154154
return *result;
155155

156156
auto subMap = opaque->getSubstitutions();
157-
auto newSubMap = asDerived().transformSubMap(subMap);
157+
auto newSubMap = asDerived().transformSubstitutionMap(subMap);
158158
if (newSubMap == subMap)
159159
return t;
160160
if (!newSubMap)
@@ -177,7 +177,7 @@ case TypeKind::Id:
177177
auto subMap = env->getOuterSubstitutions();
178178
auto uuid = env->getOpenedExistentialUUID();
179179

180-
auto newSubMap = asDerived().transformSubMap(subMap);
180+
auto newSubMap = asDerived().transformSubstitutionMap(subMap);
181181
if (newSubMap == subMap)
182182
return t;
183183
if (!newSubMap)
@@ -259,7 +259,7 @@ case TypeKind::Id:
259259
}
260260

261261
auto oldSubMap = boxTy->getSubstitutions();
262-
auto newSubMap = asDerived().transformSubMap(oldSubMap);
262+
auto newSubMap = asDerived().transformSubstitutionMap(oldSubMap);
263263
if (oldSubMap && !newSubMap)
264264
return Type();
265265
changed |= (oldSubMap != newSubMap);
@@ -281,7 +281,7 @@ case TypeKind::Id:
281281
return fnTy;
282282

283283
auto updateSubs = [&](SubstitutionMap &subs) -> bool {
284-
auto newSubs = asDerived().transformSubMap(subs);
284+
auto newSubs = asDerived().transformSubstitutionMap(subs);
285285
if (subs && !newSubs)
286286
return false;
287287
if (subs == newSubs)
@@ -1052,7 +1052,7 @@ case TypeKind::Id:
10521052

10531053
// If original was non-empty and transformed is empty, we're
10541054
// signaling failure, that is, a Type() return from doIt().
1055-
SubstitutionMap transformSubMap(SubstitutionMap subs) {
1055+
SubstitutionMap transformSubstitutionMap(SubstitutionMap subs) {
10561056
if (subs.empty())
10571057
return subs;
10581058

lib/AST/ASTDumper.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -5527,6 +5527,12 @@ class PrintConformance : public PrintBase {
55275527
assert(conformance.isAbstract());
55285528

55295529
printHead("abstract_conformance", ASTNodeColor, label);
5530+
5531+
PrintOptions PO;
5532+
PO.OpaqueReturnTypePrinting =
5533+
PrintOptions::OpaqueReturnTypePrintingMode::StableReference;
5534+
5535+
printTypeField(conformance.getType(), Label::always("type"), PO);
55305536
printReferencedDeclField(conformance.getProtocol(),
55315537
Label::always("protocol"));
55325538
printFoot();

lib/AST/ProtocolConformanceRef.cpp

+27-32
Original file line numberDiff line numberDiff line change
@@ -93,23 +93,24 @@ ProtocolConformanceRef::subst(Type origType, InFlightSubstitution &IFS) const {
9393
if (isPack())
9494
return getPack()->subst(IFS);
9595

96-
// Handle abstract conformances below:
96+
ASSERT(isAbstract());
97+
auto *proto = getProtocol();
9798

9899
// If the type is an opaque archetype, the conformance will remain abstract,
99100
// unless we're specifically substituting opaque types.
100-
if (auto origArchetype = origType->getAs<ArchetypeType>()) {
101-
if (!IFS.shouldSubstituteOpaqueArchetypes()
102-
&& isa<OpaqueTypeArchetypeType>(origArchetype)) {
103-
return *this;
101+
if (auto origArchetype = origType->getAs<OpaqueTypeArchetypeType>()) {
102+
if (!IFS.shouldSubstituteOpaqueArchetypes()) {
103+
return forAbstract(origType.subst(IFS), proto);
104104
}
105105
}
106106

107+
// FIXME: Handle local archetypes as above!
108+
107109
// Otherwise, compute the substituted type.
108110
auto substType = origType.subst(IFS);
109111

110-
auto *proto = getProtocol();
111-
112112
// If the type is an existential, it must be self-conforming.
113+
// FIXME: This feels like it's in the wrong place.
113114
if (substType->isExistentialType()) {
114115
auto optConformance =
115116
lookupConformance(substType, proto, /*allowMissing=*/true);
@@ -119,7 +120,7 @@ ProtocolConformanceRef::subst(Type origType, InFlightSubstitution &IFS) const {
119120
return ProtocolConformanceRef::forInvalid();
120121
}
121122

122-
// Check the conformance map.
123+
// Local conformance lookup into the substitution map.
123124
// FIXME: Pack element level?
124125
return IFS.lookupConformance(origType->getCanonicalType(), substType, proto,
125126
/*level=*/0);
@@ -128,24 +129,20 @@ ProtocolConformanceRef::subst(Type origType, InFlightSubstitution &IFS) const {
128129
ProtocolConformanceRef ProtocolConformanceRef::mapConformanceOutOfContext() const {
129130
if (isConcrete()) {
130131
return getConcrete()->subst(
131-
[](SubstitutableType *type) -> Type {
132-
if (auto *archetypeType = type->getAs<ArchetypeType>())
133-
return archetypeType->getInterfaceType();
134-
return type;
135-
},
132+
MapTypeOutOfContext(),
136133
MakeAbstractConformanceForGenericType(),
137134
SubstFlags::PreservePackExpansionLevel |
138135
SubstFlags::SubstitutePrimaryArchetypes);
139136
} else if (isPack()) {
140137
return getPack()->subst(
141-
[](SubstitutableType *type) -> Type {
142-
if (auto *archetypeType = type->getAs<ArchetypeType>())
143-
return archetypeType->getInterfaceType();
144-
return type;
145-
},
138+
MapTypeOutOfContext(),
146139
MakeAbstractConformanceForGenericType(),
147140
SubstFlags::PreservePackExpansionLevel |
148141
SubstFlags::SubstitutePrimaryArchetypes);
142+
} else if (isAbstract()) {
143+
auto *abstract = getAbstract();
144+
return forAbstract(abstract->getType()->mapTypeOutOfContext(),
145+
abstract->getProtocol());
149146
}
150147

151148
return *this;
@@ -266,6 +263,15 @@ ProtocolConformanceRef::getAssociatedConformance(Type conformingType,
266263
return conformance->getAssociatedConformance(assocType, protocol);
267264
}
268265

266+
auto computeSubjectType = [&](Type conformingType) -> Type {
267+
return assocType.transformRec(
268+
[&](TypeBase *t) -> std::optional<Type> {
269+
if (isa<GenericTypeParamType>(t))
270+
return conformingType;
271+
return std::nullopt;
272+
});
273+
};
274+
269275
// An associated conformance of an archetype might be known to be
270276
// a concrete conformance, if the subject type is fixed to a concrete
271277
// type in the archetype's generic signature. We don't actually have
@@ -276,15 +282,8 @@ ProtocolConformanceRef::getAssociatedConformance(Type conformingType,
276282
// conformances where they store their subject types, we can also
277283
// cache the lookups inside the abstract conformance instance too.
278284
if (auto archetypeType = conformingType->getAs<ArchetypeType>()) {
279-
conformingType = archetypeType->getInterfaceType();
280285
auto *genericEnv = archetypeType->getGenericEnvironment();
281-
282-
auto subjectType = assocType.transformRec(
283-
[&](TypeBase *t) -> std::optional<Type> {
284-
if (isa<GenericTypeParamType>(t))
285-
return conformingType;
286-
return std::nullopt;
287-
});
286+
auto subjectType = computeSubjectType(archetypeType->getInterfaceType());
288287

289288
return lookupConformance(
290289
genericEnv->mapTypeIntoContext(subjectType),
@@ -296,12 +295,8 @@ ProtocolConformanceRef::getAssociatedConformance(Type conformingType,
296295
// signature of the substitution (or in the case of type variables,
297296
// we have no visibility into constraints). See the parallel hack
298297
// to handle this in SubstitutionMap::lookupConformance().
299-
CONDITIONAL_ASSERT(conformingType->isTypeParameter() ||
300-
conformingType->isTypeVariableOrMember() ||
301-
conformingType->is<UnresolvedType>() ||
302-
conformingType->is<PlaceholderType>());
303-
304-
return ProtocolConformanceRef::forAbstract(conformingType, protocol);
298+
auto subjectType = computeSubjectType(conformingType);
299+
return ProtocolConformanceRef::forAbstract(subjectType, protocol);
305300
}
306301

307302
/// Check of all types used by the conformance are canonical.

lib/AST/SubstitutionMap.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ SubstitutionMap SubstitutionMap::subst(InFlightSubstitution &IFS) const {
381381
ProtocolConformanceRef(conformance.getConcrete()->subst(IFS)));
382382
} else {
383383
auto origType = req.getFirstType();
384-
auto substType = origType.subst(*this, IFS.getOptions());
384+
auto substType = origType.subst(*this);
385385

386386
newConformances.push_back(conformance.subst(substType, IFS));
387387
}

lib/AST/TypeSubstitution.cpp

+9-22
Original file line numberDiff line numberDiff line change
@@ -1108,37 +1108,23 @@ ProtocolConformanceRef swift::substOpaqueTypesWithUnderlyingTypes(
11081108
ProtocolConformanceRef ReplaceOpaqueTypesWithUnderlyingTypes::
11091109
operator()(CanType maybeOpaqueType, Type replacementType,
11101110
ProtocolDecl *protocol) const {
1111-
auto abstractRef = ProtocolConformanceRef::forAbstract(maybeOpaqueType, protocol);
1112-
11131111
auto archetype = dyn_cast<OpaqueTypeArchetypeType>(maybeOpaqueType);
1114-
if (!archetype) {
1115-
if (maybeOpaqueType->isTypeParameter() ||
1116-
maybeOpaqueType->is<ArchetypeType>())
1117-
return abstractRef;
1118-
1119-
// SIL type lowering may have already substituted away the opaque type, in
1120-
// which case we'll end up "substituting" the same type.
1121-
if (maybeOpaqueType->isEqual(replacementType)) {
1122-
return lookupConformance(replacementType, protocol);
1123-
}
1124-
1125-
llvm_unreachable("origType should have been an opaque type or type parameter");
1126-
}
1112+
if (!archetype)
1113+
return lookupConformance(replacementType, protocol);
11271114

11281115
auto *genericEnv = archetype->getGenericEnvironment();
11291116
auto *decl = genericEnv->getOpaqueTypeDecl();
11301117
auto outerSubs = genericEnv->getOuterSubstitutions();
11311118

11321119
auto substitutionKind = shouldPerformSubstitution(decl);
1133-
if (substitutionKind == OpaqueSubstitutionKind::DontSubstitute) {
1134-
return abstractRef;
1135-
}
1120+
if (substitutionKind == OpaqueSubstitutionKind::DontSubstitute)
1121+
return lookupConformance(replacementType, protocol);
11361122

11371123
auto subs = decl->getUniqueUnderlyingTypeSubstitutions();
11381124
// If the body of the opaque decl providing decl has not been type checked we
11391125
// don't have a underlying substitution.
11401126
if (!subs.has_value())
1141-
return abstractRef;
1127+
return lookupConformance(replacementType, protocol);
11421128

11431129
// Apply the underlying type substitutions to the interface type of the
11441130
// archetype in question. This will map the inner generic signature of the
@@ -1159,7 +1145,7 @@ operator()(CanType maybeOpaqueType, Type replacementType,
11591145
return true;
11601146
return false;
11611147
}))
1162-
return abstractRef;
1148+
return lookupConformance(replacementType, protocol);
11631149

11641150
// Then apply the substitutions from the root opaque archetype, to specialize
11651151
// for its type arguments. We perform this substitution after checking for
@@ -1168,7 +1154,8 @@ operator()(CanType maybeOpaqueType, Type replacementType,
11681154
auto substTy = partialSubstTy.subst(outerSubs);
11691155

11701156
auto partialSubstRef =
1171-
abstractRef.subst(archetype->getInterfaceType(), *subs);
1157+
subs->lookupConformance(archetype->getInterfaceType()->getCanonicalType(),
1158+
protocol);
11721159
auto substRef =
11731160
partialSubstRef.subst(partialSubstTy, outerSubs);
11741161

@@ -1181,7 +1168,7 @@ operator()(CanType maybeOpaqueType, Type replacementType,
11811168
// type back to the caller. This substitution will fail at runtime
11821169
// instead.
11831170
if (!alreadySeen->insert(seenKey).second) {
1184-
return abstractRef;
1171+
return lookupConformance(replacementType, protocol);
11851172
}
11861173

11871174
auto res = ::substOpaqueTypesWithUnderlyingTypesRec(

test/Frontend/debug-generic-signatures.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ struct Generic<T> {}
9898
// CHECK-NEXT: (assoc_conformance type="Self" proto="Escapable"
9999
// CHECK-NEXT: (builtin_conformance type="Generic<T>" protocol="Escapable"))
100100
// CHECK-NEXT: (assoc_conformance type="Self.A" proto="Copyable"
101-
// CHECK-NEXT: (abstract_conformance protocol="Copyable"))
101+
// CHECK-NEXT: (abstract_conformance type="T" protocol="Copyable"))
102102
// CHECK-NEXT: (assoc_conformance type="Self.A" proto="Escapable"
103-
// CHECK-NEXT: (abstract_conformance protocol="Escapable"))
103+
// CHECK-NEXT: (abstract_conformance type="T" protocol="Escapable"))
104104
// CHECK-NEXT: (requirement "T" conforms_to "P1"))
105105
extension Generic: P1 where T: P1 {
106106
typealias A = T
@@ -123,9 +123,9 @@ class Super<T, U> {}
123123
// CHECK-NEXT: (assoc_conformance type="Self" proto="Escapable"
124124
// CHECK-NEXT: (builtin_conformance type="Super<T, U>" protocol="Escapable"))
125125
// CHECK-NEXT: (assoc_conformance type="Self.A" proto="P2"
126-
// CHECK-NEXT: (abstract_conformance protocol="P2"))
126+
// CHECK-NEXT: (abstract_conformance type="T" protocol="P2"))
127127
// CHECK-NEXT: (assoc_conformance type="Self.B" proto="P2"
128-
// CHECK-NEXT: (abstract_conformance protocol="P2"))
128+
// CHECK-NEXT: (abstract_conformance type="T" protocol="P2"))
129129
// CHECK-NEXT: (requirement "T" conforms_to "P2")
130130
// CHECK-NEXT: (requirement "U" conforms_to "P2"))
131131
extension Super: P2 where T: P2, U: P2 {
@@ -177,9 +177,9 @@ extension Super: P2 where T: P2, U: P2 {
177177
// CHECK-NEXT: (assoc_conformance type="Self" proto="Escapable"
178178
// CHECK-NEXT: (builtin_conformance type="Super<T, U>" protocol="Escapable"))
179179
// CHECK-NEXT: (assoc_conformance type="Self.A" proto="P2"
180-
// CHECK-NEXT: (abstract_conformance protocol="P2"))
180+
// CHECK-NEXT: (abstract_conformance type="T" protocol="P2"))
181181
// CHECK-NEXT: (assoc_conformance type="Self.B" proto="P2"
182-
// CHECK-NEXT: (abstract_conformance protocol="P2"))
182+
// CHECK-NEXT: (abstract_conformance type="T" protocol="P2"))
183183
// CHECK-NEXT: (requirement "T" conforms_to "P2")
184184
// CHECK-NEXT: (requirement "U" conforms_to "P2"))))
185185
class Sub: Super<NonRecur, Recur> {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %target-swift-frontend -emit-silgen %s -target %target-cpu-apple-macosx11 -swift-version 5
2+
3+
// REQUIRES: objc_interop
4+
// REQUIRES: OS=macosx
5+
6+
import SwiftUI
7+
8+
struct MyView: View {
9+
@State private var isPresented = false
10+
11+
var body: some View {
12+
NavigationView {
13+
Form {
14+
subsection
15+
}
16+
.listStyle(DefaultListStyle())
17+
.navigationTitle(Text(""))
18+
.sheet(isPresented: $isPresented,
19+
onDismiss: { },
20+
content: { Text("") })
21+
}
22+
}
23+
24+
private var subsection: some View {
25+
Text("")
26+
}
27+
}

0 commit comments

Comments
 (0)