Skip to content

Commit 7e59265

Browse files
authored
Merge pull request #81053 from slavapestov/fix-rdar149315905-6.2
[6.2] Workaround for performance regression with opaque archetypes
2 parents 307f330 + 58ecc36 commit 7e59265

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

lib/AST/TypeSubstitution.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ class TypeSubstituter : public TypeTransform<TypeSubstituter> {
329329
std::optional<Type> transformLocalArchetypeType(LocalArchetypeType *local,
330330
TypePosition pos);
331331

332-
SubstitutionMap transformSubstitutionMap(SubstitutionMap subs);
332+
// SubstitutionMap transformSubstitutionMap(SubstitutionMap subs);
333333

334334
CanType transformSILField(CanType fieldTy, TypePosition pos);
335335
};
@@ -446,10 +446,13 @@ Type TypeSubstituter::transformDependentMemberType(DependentMemberType *dependen
446446
return conformance.getTypeWitness(substBase, assocType, IFS.getOptions());
447447
}
448448

449+
// FIXME: This exposes a scalability issue; see test/SILGen/opaque_result_type_slow.swift.
450+
/*
449451
SubstitutionMap TypeSubstituter::transformSubstitutionMap(SubstitutionMap subs) {
450452
// FIXME: Take level into account? Move level down into IFS?
451453
return subs.subst(IFS);
452454
}
455+
*/
453456

454457
CanType TypeSubstituter::transformSILField(CanType fieldTy, TypePosition pos) {
455458
// Type substitution does not walk into the SILBoxType's field types, because
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
public protocol P {}
2+
public protocol Q {}
3+
4+
public func wrap<T: P & Q>(_ t: T) -> some P & Q {
5+
return t
6+
}
7+
8+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module %S/Inputs/opaque_result_type_slow_other.swift -emit-module -emit-module-path %t/opaque_result_type_slow_other.swiftmodule -enable-library-evolution
3+
// RUN: %target-swift-emit-silgen %s -I %t
4+
5+
import opaque_result_type_slow_other
6+
7+
struct G<T: P & Q>: P & Q {}
8+
9+
public func myWrap<T: P & Q>(_ t: T) -> some P & Q {
10+
return G<T>()
11+
}
12+
13+
public func wrapWrap<T: P & Q>(_ t: T) -> some P & Q {
14+
return wrap(wrap(myWrap(t)))
15+
}
16+
17+
public struct S: P, Q {}
18+
19+
// We generate a series of substitution maps where each one contains an opaque archetype,
20+
// and an abstract conformance of this opaque archetype to a protocol. Each opaque archetype
21+
// then has a substitution map of the same form, and so on.
22+
//
23+
// Transforming each substitution map then visits each opaque archetype twice: once as part
24+
// of the replacement type, and again as part of the conformance.
25+
//
26+
// What saves us is that we would skip the conformance substitution in some cases, and perform
27+
// a lookup instead. This lookup is now load bearing, because changing it into a substitution
28+
// makes this program intractably slow.
29+
//
30+
// The correct fix is to probably cache substituted opaque GenericEnvironments, or
31+
// substituted SubstitutionMaps, inside of the InFlightSubstitution.
32+
let x = wrapWrap(wrapWrap(wrapWrap(wrapWrap(wrapWrap(wrapWrap(wrapWrap(wrapWrap(wrapWrap(S())))))))))

0 commit comments

Comments
 (0)