Skip to content

Commit 3e4b95f

Browse files
committed
ASTMangler: Fix substitution round-tripping in the DWARF mangler
When mangling sugared types for DWARF debug info, we would occassionally mix generic parameter types from different generic environments. Since the mangling for a generic parameter type only recorded the depth and the index, even for distinct sugared forms, the remangler would produce a more 'compact' mangling, by folding together generic parameters that have the same depth/index, but distinct sugarings in the AST. Prevent this from happening by desugaring DWARF types the correct amount, substituting away generic parameters while preserving everything else. Also, re-enable the round-trip verification with the remangler. Fixes <rdar://problem/59496022>, <https://bugs.swift.org/browse/SR-12204>.
1 parent 549f630 commit 3e4b95f

File tree

3 files changed

+39
-8
lines changed

3 files changed

+39
-8
lines changed

lib/AST/ASTMangler.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,28 @@ std::string ASTMangler::mangleSILDifferentiabilityWitnessKey(
445445
return result;
446446
}
447447

448+
// In order for the remangler to work correctly, it must agree with
449+
// AST mangler on the substitution scheme. The AST mangler will use a
450+
// substitution if a mangled type is identical to a previous type.
451+
//
452+
// In the DWARF mangling, we don't canonicalize types. Therefore, any
453+
// two types that differ by sugar must have distinct manglings. If this
454+
// invariant is not maintained, then demangling and remangling a type
455+
// will no longer be idempotent.
456+
//
457+
// Since we don't have a distinct mangling for sugared generic
458+
// parameter types, we must desugar them here.
459+
static Type getTypeForDWARFMangling(Type t) {
460+
return t.subst(
461+
[](SubstitutableType *t) -> Type {
462+
if (isa<GenericTypeParamType>(t))
463+
return t->getCanonicalType();
464+
return t;
465+
},
466+
MakeAbstractConformanceForGenericType(),
467+
SubstFlags::AllowLoweredTypes);
468+
}
469+
448470
std::string ASTMangler::mangleTypeForDebugger(Type Ty, const DeclContext *DC) {
449471
PrettyStackTraceType prettyStackTrace(Ty->getASTContext(),
450472
"mangling type for debugger", Ty);
@@ -453,6 +475,8 @@ std::string ASTMangler::mangleTypeForDebugger(Type Ty, const DeclContext *DC) {
453475
OptimizeProtocolNames = false;
454476
beginMangling();
455477

478+
Ty = getTypeForDWARFMangling(Ty);
479+
456480
if (DC)
457481
bindGenericParameters(DC);
458482

@@ -552,7 +576,9 @@ std::string ASTMangler::mangleTypeAsContextUSR(const NominalTypeDecl *type) {
552576
std::string ASTMangler::mangleTypeAsUSR(Type Ty) {
553577
DWARFMangling = true;
554578
beginMangling();
555-
579+
580+
Ty = getTypeForDWARFMangling(Ty);
581+
556582
if (auto *fnType = Ty->getAs<AnyFunctionType>()) {
557583
appendFunction(fnType, false);
558584
} else {
@@ -1130,6 +1156,10 @@ void ASTMangler::appendType(Type type, const ValueDecl *forDecl) {
11301156

11311157
case TypeKind::GenericTypeParam: {
11321158
auto paramTy = cast<GenericTypeParamType>(tybase);
1159+
// If this assertion fires, it probably means the type being mangled here
1160+
// didn't go through getTypeForDWARFMangling().
1161+
assert(paramTy->getDecl() == nullptr &&
1162+
"cannot mangle non-canonical generic parameter");
11331163
// A special mangling for the very first generic parameter. This shows up
11341164
// frequently because it corresponds to 'Self' in protocol requirement
11351165
// generic signatures.

lib/Basic/Mangler.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,15 +130,8 @@ std::string Mangler::finalize() {
130130
Storage.clear();
131131

132132
#ifndef NDEBUG
133-
/*
134-
Verification is temporarily disabled, because of:
135-
rdar://problem/59813007
136-
rdar://problem/59496022
137-
https://bugs.swift.org/browse/SR-12204
138-
139133
if (StringRef(result).startswith(MANGLING_PREFIX_STR))
140134
verify(result);
141-
*/
142135
#endif
143136

144137
return result;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - | %FileCheck %s
2+
3+
extension Optional: Comparable where Wrapped: Comparable {
4+
public static func v(in r: ClosedRange<Self>) {}
5+
public static func < (lhs: Self, rhs: Self) -> Bool { false }
6+
}
7+
8+
// CHECK: sSNyxSgAASL23retroactive_conformancexSLHD1__HCg_GD

0 commit comments

Comments
 (0)