diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index ae667d06a5e9c..d5e6754845ecc 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -755,36 +755,53 @@ 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()); + } + + // 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); } - args.push_back(argTy->getSecond()); + } 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 { + return Type(); } - Type constrainedBase = - ParameterizedProtocolType::get(base->getASTContext(), baseTy, args); + + assert(constrainedBase); // 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 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) +}