Skip to content

ASTMangler: Fix substitution round-tripping in the DWARF mangler #30840

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,28 @@ std::string ASTMangler::mangleSILDifferentiabilityWitnessKey(
return result;
}

// In order for the remangler to work correctly, it must agree with
// AST mangler on the substitution scheme. The AST mangler will use a
// substitution if a mangled type is identical to a previous type.
//
// In the DWARF mangling, we don't canonicalize types. Therefore, any
// two types that differ by sugar must have distinct manglings. If this
// invariant is not maintained, then demangling and remangling a type
// will no longer be idempotent.
//
// Since we don't have a distinct mangling for sugared generic
// parameter types, we must desugar them here.
static Type getTypeForDWARFMangling(Type t) {
return t.subst(
[](SubstitutableType *t) -> Type {
if (isa<GenericTypeParamType>(t))
return t->getCanonicalType();
return t;
},
MakeAbstractConformanceForGenericType(),
SubstFlags::AllowLoweredTypes);
}

std::string ASTMangler::mangleTypeForDebugger(Type Ty, const DeclContext *DC) {
PrettyStackTraceType prettyStackTrace(Ty->getASTContext(),
"mangling type for debugger", Ty);
Expand All @@ -453,6 +475,8 @@ std::string ASTMangler::mangleTypeForDebugger(Type Ty, const DeclContext *DC) {
OptimizeProtocolNames = false;
beginMangling();

Ty = getTypeForDWARFMangling(Ty);

if (DC)
bindGenericParameters(DC);

Expand Down Expand Up @@ -552,7 +576,9 @@ std::string ASTMangler::mangleTypeAsContextUSR(const NominalTypeDecl *type) {
std::string ASTMangler::mangleTypeAsUSR(Type Ty) {
DWARFMangling = true;
beginMangling();


Ty = getTypeForDWARFMangling(Ty);

if (auto *fnType = Ty->getAs<AnyFunctionType>()) {
appendFunction(fnType, false);
} else {
Expand Down Expand Up @@ -1130,6 +1156,10 @@ void ASTMangler::appendType(Type type, const ValueDecl *forDecl) {

case TypeKind::GenericTypeParam: {
auto paramTy = cast<GenericTypeParamType>(tybase);
// If this assertion fires, it probably means the type being mangled here
// didn't go through getTypeForDWARFMangling().
assert(paramTy->getDecl() == nullptr &&
"cannot mangle non-canonical generic parameter");
// A special mangling for the very first generic parameter. This shows up
// frequently because it corresponds to 'Self' in protocol requirement
// generic signatures.
Expand Down
7 changes: 0 additions & 7 deletions lib/Basic/Mangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,8 @@ std::string Mangler::finalize() {
Storage.clear();

#ifndef NDEBUG
/*
Verification is temporarily disabled, because of:
rdar://problem/59813007
rdar://problem/59496022
https://bugs.swift.org/browse/SR-12204

if (StringRef(result).startswith(MANGLING_PREFIX_STR))
verify(result);
*/
#endif

return result;
Expand Down
8 changes: 8 additions & 0 deletions test/DebugInfo/retroactive_conformance.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - | %FileCheck %s

extension Optional: Comparable where Wrapped: Comparable {
public static func v(in r: ClosedRange<Self>) {}
public static func < (lhs: Self, rhs: Self) -> Bool { false }
}

// CHECK: sSNyxSgAASL23retroactive_conformancexSLHD1__HCg_GD