From b604488f1c6860c531187bed95369f182ab07b64 Mon Sep 17 00:00:00 2001 From: Kavon Farvardin Date: Fri, 14 Jun 2024 12:25:39 -0700 Subject: [PATCH 1/2] Demangler: edge case in existential demangling We now may have constrained existentials that have no primary associated types, so there won't be any arguments for the parameterized protocol type. Because the "constrained" part is that there's an inverse. resolves rdar://128695929 --- lib/AST/ASTDemangler.cpp | 14 ++++++++++++-- test/Interpreter/moveonly_existentials.swift | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index ae667d06a5e9c..a44d72db3b2c6 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -783,8 +783,18 @@ Type ASTBuilder::createConstrainedExistentialType( } args.push_back(argTy->getSecond()); } - Type constrainedBase = - ParameterizedProtocolType::get(base->getASTContext(), baseTy, args); + + Type constrainedBase; + + // We may not have any arguments because the constrained existential is a + // plain protocol with an inverse requirement. + if (args.empty()) { + constrainedBase = + ProtocolType::get(baseDecl, baseTy, base->getASTContext()); + } else { + constrainedBase = + ParameterizedProtocolType::get(base->getASTContext(), baseTy, args); + } // Handle inverse requirements. if (!inverseRequirements.empty()) { diff --git a/test/Interpreter/moveonly_existentials.swift b/test/Interpreter/moveonly_existentials.swift index 929d7942fa1bb..f3ab9465e8036 100644 --- a/test/Interpreter/moveonly_existentials.swift +++ b/test/Interpreter/moveonly_existentials.swift @@ -1,5 +1,5 @@ // RUN: %empty-directory(%t) -// RUN: %target-build-swift %s -o %t/bin +// RUN: %target-build-swift -g %s -o %t/bin // RUN: %target-codesign %t/bin // RUN: %target-run %t/bin | %FileCheck %s From 0ecf982b78c10353d8e102a1c6bbe3f3349d3b82 Mon Sep 17 00:00:00 2001 From: Kavon Farvardin Date: Fri, 14 Jun 2024 17:42:02 -0700 Subject: [PATCH 2/2] Demangler: fix demangling `any ~Copyable` --- lib/AST/ASTDemangler.cpp | 75 ++++++++++--------- .../constrained_existentials.swift | 14 ++++ 2 files changed, 55 insertions(+), 34 deletions(-) diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index a44d72db3b2c6..d5e6754845ecc 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -755,47 +755,54 @@ Type ASTBuilder::createExistentialMetatypeType( Type ASTBuilder::createConstrainedExistentialType( Type base, ArrayRef constraints, ArrayRef inverseRequirements) { - // FIXME: Generalize to other kinds of bases. - if (!base->getAs()) - return Type(); - auto baseTy = base->castTo(); - auto baseDecl = baseTy->getDecl(); - llvm::SmallDenseMap cmap; - for (const auto &req : constraints) { - switch (req.getKind()) { - case RequirementKind::SameShape: - llvm_unreachable("Same-shape requirement not supported here"); - case RequirementKind::Conformance: - case RequirementKind::Superclass: - case RequirementKind::Layout: - continue; + Type constrainedBase; + + if (auto baseTy = base->getAs()) { + auto baseDecl = baseTy->getDecl(); + llvm::SmallDenseMap cmap; + for (const auto &req : constraints) { + switch (req.getKind()) { + case RequirementKind::SameShape: + llvm_unreachable("Same-shape requirement not supported here"); + case RequirementKind::Conformance: + case RequirementKind::Superclass: + case RequirementKind::Layout: + continue; - case RequirementKind::SameType: - if (auto *DMT = req.getFirstType()->getAs()) - cmap[DMT->getName()] = req.getSecondType(); + case RequirementKind::SameType: + if (auto *DMT = req.getFirstType()->getAs()) + cmap[DMT->getName()] = req.getSecondType(); + } } - } - llvm::SmallVector args; - for (auto *assocTy : baseDecl->getPrimaryAssociatedTypes()) { - auto argTy = cmap.find(assocTy->getName()); - if (argTy == cmap.end()) { - return Type(); + llvm::SmallVector args; + for (auto *assocTy : baseDecl->getPrimaryAssociatedTypes()) { + auto argTy = cmap.find(assocTy->getName()); + if (argTy == cmap.end()) { + return Type(); + } + args.push_back(argTy->getSecond()); } - args.push_back(argTy->getSecond()); - } - - Type constrainedBase; - // We may not have any arguments because the constrained existential is a - // plain protocol with an inverse requirement. - if (args.empty()) { - constrainedBase = - ProtocolType::get(baseDecl, baseTy, base->getASTContext()); + // We may not have any arguments because the constrained existential is a + // plain protocol with an inverse requirement. + if (args.empty()) { + constrainedBase = + ProtocolType::get(baseDecl, baseTy, base->getASTContext()); + } else { + constrainedBase = + ParameterizedProtocolType::get(base->getASTContext(), baseTy, args); + } + } else if (base->isAny()) { + // The only other case should be that we got an empty PCT, which is equal to + // the Any type. The other constraints should have been encoded in the + // existential's generic signature (and arrive as BuiltInverseRequirement). + constrainedBase = base; } else { - constrainedBase = - ParameterizedProtocolType::get(base->getASTContext(), baseTy, args); + return Type(); } + assert(constrainedBase); + // Handle inverse requirements. if (!inverseRequirements.empty()) { InvertibleProtocolSet inverseSet; diff --git a/test/TypeDecoder/constrained_existentials.swift b/test/TypeDecoder/constrained_existentials.swift index b5f5691d3129b..e84ac363d043a 100644 --- a/test/TypeDecoder/constrained_existentials.swift +++ b/test/TypeDecoder/constrained_existentials.swift @@ -5,6 +5,7 @@ // RUN: %lldb-moduleimport-test %t/constrained_existentials -type-from-mangled=%t/input | %FileCheck %s --match-full-lines func blackHole(_: Any...) {} +func blackHole_noncopyable(_: consuming any ~Copyable) {} protocol BaseProto { associatedtype A @@ -43,3 +44,16 @@ do { blackHole(e0, e1, e2) } + +protocol NCProto: ~Copyable {} +struct NC: ~Copyable {} +struct GenNC: ~Copyable, NCProto {} + +do { + let e0: any NCProto & ~Copyable = GenNC() + let e1: any NCProto & ~Copyable = GenNC() + + // FIXME: breaks the MoveChecker (rdar://129885532) +// blackHole_noncopyable(consume e0) +// blackHole_noncopyable(consume e1) +}