//===--- Expr.cpp - Swift Language Expression ASTs ------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file implements the Expr class and subclasses. // //===----------------------------------------------------------------------===// #include "swift/AST/Expr.h" #include "swift/Basic/Assertions.h" #include "swift/Basic/Statistic.h" #include "swift/Basic/Unicode.h" #include "swift/Basic/SourceManager.h" #include "swift/AST/ASTContext.h" #include "swift/AST/ASTVisitor.h" #include "swift/AST/Decl.h" // FIXME: Bad dependency #include "swift/AST/ExistentialLayout.h" #include "swift/AST/MacroDiscriminatorContext.h" #include "swift/AST/ParameterList.h" #include "swift/AST/Stmt.h" #include "swift/AST/ASTWalker.h" #include "swift/AST/AvailabilitySpec.h" #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/TypeCheckRequests.h" #include "swift/AST/TypeLoc.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/Twine.h" using namespace swift; #define EXPR(Id, _) \ static_assert(IsTriviallyDestructible::value, \ "Exprs are BumpPtrAllocated; the destructor is never called"); #include "swift/AST/ExprNodes.def" //===----------------------------------------------------------------------===// // Expr methods. //===----------------------------------------------------------------------===// StringRef Expr::getKindName(ExprKind K) { switch (K) { #define EXPR(Id, Parent) case ExprKind::Id: return #Id; #include "swift/AST/ExprNodes.def" } llvm_unreachable("bad ExprKind"); } template static SourceLoc getStartLocImpl(const T *E); template static SourceLoc getEndLocImpl(const T *E); template static SourceLoc getLocImpl(const T *E); // Helper functions to check statically whether a method has been // overridden from its implementation in Expr. The sort of thing you // need when you're avoiding v-tables. namespace { template constexpr bool isOverriddenFromExpr(ReturnType (Class::*)() const) { return true; } template constexpr bool isOverriddenFromExpr(ReturnType (Expr::*)() const) { return false; } template struct Dispatch; /// Dispatch down to a concrete override. template <> struct Dispatch { template static SourceLoc getStartLoc(const T *E) { return E->getStartLoc(); } template static SourceLoc getEndLoc(const T *E) { return E->getEndLoc(); } template static SourceLoc getLoc(const T *E) { return E->getLoc(); } template static SourceRange getSourceRange(const T *E) { return E->getSourceRange(); } }; /// Default implementations for when a method isn't overridden. template <> struct Dispatch { template static SourceLoc getStartLoc(const T *E) { return E->getSourceRange().Start; } template static SourceLoc getEndLoc(const T *E) { return E->getSourceRange().End; } template static SourceLoc getLoc(const T *E) { return getStartLocImpl(E); } template static SourceRange getSourceRange(const T *E) { if (E->getStartLoc().isInvalid() != E->getEndLoc().isInvalid()) return SourceRange(); return { E->getStartLoc(), E->getEndLoc() }; } }; } // end anonymous namespace void Expr::setType(Type T) { assert(!T || !T->hasTypeVariable() || !T->hasPlaceholder()); Ty = T; } void Expr::setImplicit(bool Implicit) { assert(!isa(this) || getType() && "Cannot make a TypeExpr implicit without a contextual type."); Bits.Expr.Implicit = Implicit; } template static SourceRange getSourceRangeImpl(const T *E) { static_assert(isOverriddenFromExpr(&T::getSourceRange) || (isOverriddenFromExpr(&T::getStartLoc) && isOverriddenFromExpr(&T::getEndLoc)), "Expr subclass must implement either getSourceRange() " "or getStartLoc()/getEndLoc()"); return Dispatch::getSourceRange(E); } SourceRange Expr::getSourceRange() const { switch (getKind()) { #define EXPR(ID, PARENT) \ case ExprKind::ID: return getSourceRangeImpl(cast(this)); #include "swift/AST/ExprNodes.def" } llvm_unreachable("expression type not handled!"); } template static SourceLoc getStartLocImpl(const T *E) { return Dispatch::getStartLoc(E); } SourceLoc Expr::getStartLoc() const { switch (getKind()) { #define EXPR(ID, PARENT) \ case ExprKind::ID: return getStartLocImpl(cast(this)); #include "swift/AST/ExprNodes.def" } llvm_unreachable("expression type not handled!"); } template static SourceLoc getEndLocImpl(const T *E) { return Dispatch::getEndLoc(E); } SourceLoc Expr::getEndLoc() const { switch (getKind()) { #define EXPR(ID, PARENT) \ case ExprKind::ID: return getEndLocImpl(cast(this)); #include "swift/AST/ExprNodes.def" } llvm_unreachable("expression type not handled!"); } template static SourceLoc getLocImpl(const T *E) { return Dispatch::getLoc(E); } SourceLoc Expr::getLoc() const { switch (getKind()) { #define EXPR(ID, PARENT) \ case ExprKind::ID: return getLocImpl(cast(this)); #include "swift/AST/ExprNodes.def" } llvm_unreachable("expression type not handled!"); } Expr *Expr::getSemanticsProvidingExpr() { if (auto *IE = dyn_cast(this)) return IE->getSubExpr()->getSemanticsProvidingExpr(); if (auto *TE = dyn_cast(this)) return TE->getSubExpr()->getSemanticsProvidingExpr(); return this; } bool Expr::printConstExprValue(llvm::raw_ostream *OS, llvm::function_ref additionalCheck) const { auto print = [&](StringRef text) { if (OS) { *OS << text; } }; auto *E = getSemanticsProvidingExpr(); assert(E); switch(getKind()) { case ExprKind::BooleanLiteral: { auto isTrue = cast(E)->getValue(); print(isTrue ? "true" : "false"); return true; } case ExprKind::IntegerLiteral: case ExprKind::FloatLiteral: { const auto *NE = cast(E); auto digits = NE->getDigitsText(); assert(!digits.empty()); if (NE->getMinusLoc().isValid()) { print("-"); } print(digits); return true; } case ExprKind::NilLiteral: { print("nil"); return true; } case ExprKind::StringLiteral: { auto *LE = cast(E); print("\""); print(LE->getValue()); print("\""); return true; } case ExprKind::KeyPath: { // FIXME: print keypath print("\\."); return true; } case ExprKind::Array: case ExprKind::Dictionary: { print("["); auto *CE = cast(E); for (unsigned N = CE->getNumElements(), I = 0; I != N; I ++) { auto Ele = CE->getElement(I); auto needComma = I + 1 != N; if (!Ele->printConstExprValue(OS, additionalCheck)) { return false; } if (needComma) print(", "); } print("]"); return true; } case ExprKind::Tuple: { print("("); auto *TE = cast(E); for (unsigned N = TE->getNumElements(), I = 0; I != N; I ++) { auto Ele = TE->getElement(I); auto needComma = I + 1 != N; if (!Ele->printConstExprValue(OS, additionalCheck)) { return false; } if (needComma) print(", "); } print(")"); return true; } default: return additionalCheck && additionalCheck(const_cast(this)); } } bool Expr::isSemanticallyConstExpr( llvm::function_ref additionalCheck) const { return printConstExprValue(nullptr, additionalCheck); } Expr *Expr::getValueProvidingExpr() { Expr *E = getSemanticsProvidingExpr(); if (auto TE = dyn_cast(E)) return TE->getSubExpr()->getValueProvidingExpr(); // TODO: // - tuple literal projection, which may become interestingly idiomatic return E; } DeclRefExpr *Expr::getMemberOperatorRef() { auto expr = this; if (!expr->isImplicit()) return nullptr; auto dotSyntax = dyn_cast(expr); if (!dotSyntax) return nullptr; auto operatorRef = dyn_cast(dotSyntax->getFn()); if (!operatorRef) return nullptr; auto func = dyn_cast(operatorRef->getDecl()); if (!func) return nullptr; if (!func->isOperator()) return nullptr; return operatorRef; } ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const { switch (getKind()) { // No declaration reference. #define NO_REFERENCE(Id) case ExprKind::Id: return ConcreteDeclRef() #define SIMPLE_REFERENCE(Id, Getter) \ case ExprKind::Id: \ return cast(this)->Getter() #define PASS_THROUGH_REFERENCE(Id, GetSubExpr) \ case ExprKind::Id: \ if (auto sub = cast(this)->GetSubExpr()) \ return sub->getReferencedDecl(stopAtParenExpr); \ return ConcreteDeclRef(); NO_REFERENCE(Error); SIMPLE_REFERENCE(NilLiteral, getInitializer); SIMPLE_REFERENCE(IntegerLiteral, getInitializer); SIMPLE_REFERENCE(FloatLiteral, getInitializer); SIMPLE_REFERENCE(BooleanLiteral, getInitializer); SIMPLE_REFERENCE(StringLiteral, getInitializer); SIMPLE_REFERENCE(InterpolatedStringLiteral, getInitializer); NO_REFERENCE(RegexLiteral); NO_REFERENCE(ObjectLiteral); NO_REFERENCE(MagicIdentifierLiteral); NO_REFERENCE(DiscardAssignment); NO_REFERENCE(LazyInitializer); NO_REFERENCE(SingleValueStmt); SIMPLE_REFERENCE(DeclRef, getDeclRef); SIMPLE_REFERENCE(SuperRef, getSelf); NO_REFERENCE(Type); SIMPLE_REFERENCE(OtherConstructorDeclRef, getDeclRef); PASS_THROUGH_REFERENCE(DotSyntaxBaseIgnored, getRHS); // FIXME: Return multiple results? case ExprKind::OverloadedDeclRef: return ConcreteDeclRef(); NO_REFERENCE(UnresolvedDeclRef); SIMPLE_REFERENCE(MemberRef, getMember); SIMPLE_REFERENCE(DynamicMemberRef, getMember); SIMPLE_REFERENCE(DynamicSubscript, getMember); PASS_THROUGH_REFERENCE(UnresolvedSpecialize, getSubExpr); NO_REFERENCE(UnresolvedMember); NO_REFERENCE(UnresolvedDot); NO_REFERENCE(Sequence); case ExprKind::Paren: if (stopAtParenExpr) return ConcreteDeclRef(); return cast(this) ->getSubExpr()->getReferencedDecl(stopAtParenExpr); PASS_THROUGH_REFERENCE(UnresolvedMemberChainResult, getSubExpr); PASS_THROUGH_REFERENCE(DotSelf, getSubExpr); PASS_THROUGH_REFERENCE(Await, getSubExpr); PASS_THROUGH_REFERENCE(Unsafe, getSubExpr); PASS_THROUGH_REFERENCE(Consume, getSubExpr); PASS_THROUGH_REFERENCE(Copy, getSubExpr); PASS_THROUGH_REFERENCE(Borrow, getSubExpr); PASS_THROUGH_REFERENCE(Try, getSubExpr); PASS_THROUGH_REFERENCE(ForceTry, getSubExpr); PASS_THROUGH_REFERENCE(OptionalTry, getSubExpr); PASS_THROUGH_REFERENCE(ExtractFunctionIsolation, getFunctionExpr); NO_REFERENCE(Tuple); SIMPLE_REFERENCE(Array, getInitializer); SIMPLE_REFERENCE(Dictionary, getInitializer); case ExprKind::Subscript: { auto subscript = cast(this); if (subscript->hasDecl()) return subscript->getDecl(); return ConcreteDeclRef(); } NO_REFERENCE(KeyPathApplication); NO_REFERENCE(TupleElement); NO_REFERENCE(CaptureList); NO_REFERENCE(Closure); PASS_THROUGH_REFERENCE(AutoClosure, getSingleExpressionBody); PASS_THROUGH_REFERENCE(InOut, getSubExpr); NO_REFERENCE(VarargExpansion); NO_REFERENCE(PackExpansion); NO_REFERENCE(PackElement); NO_REFERENCE(MaterializePack); NO_REFERENCE(DynamicType); PASS_THROUGH_REFERENCE(RebindSelfInConstructor, getSubExpr); NO_REFERENCE(OpaqueValue); NO_REFERENCE(PropertyWrapperValuePlaceholder); NO_REFERENCE(AppliedPropertyWrapper); NO_REFERENCE(DefaultArgument); PASS_THROUGH_REFERENCE(BindOptional, getSubExpr); PASS_THROUGH_REFERENCE(OptionalEvaluation, getSubExpr); PASS_THROUGH_REFERENCE(ForceValue, getSubExpr); PASS_THROUGH_REFERENCE(OpenExistential, getSubExpr); NO_REFERENCE(Call); NO_REFERENCE(PrefixUnary); NO_REFERENCE(PostfixUnary); NO_REFERENCE(Binary); NO_REFERENCE(DotSyntaxCall); NO_REFERENCE(MakeTemporarilyEscapable); NO_REFERENCE(ConstructorRefCall); PASS_THROUGH_REFERENCE(Load, getSubExpr); NO_REFERENCE(DestructureTuple); PASS_THROUGH_REFERENCE(ABISafeConversion, getSubExpr); PASS_THROUGH_REFERENCE(FunctionConversion, getSubExpr); PASS_THROUGH_REFERENCE(CovariantFunctionConversion, getSubExpr); PASS_THROUGH_REFERENCE(CovariantReturnConversion, getSubExpr); PASS_THROUGH_REFERENCE(MetatypeConversion, getSubExpr); PASS_THROUGH_REFERENCE(CollectionUpcastConversion, getSubExpr); PASS_THROUGH_REFERENCE(Erasure, getSubExpr); PASS_THROUGH_REFERENCE(AnyHashableErasure, getSubExpr); PASS_THROUGH_REFERENCE(DerivedToBase, getSubExpr); PASS_THROUGH_REFERENCE(ArchetypeToSuper, getSubExpr); PASS_THROUGH_REFERENCE(InjectIntoOptional, getSubExpr); PASS_THROUGH_REFERENCE(ClassMetatypeToObject, getSubExpr); PASS_THROUGH_REFERENCE(ExistentialMetatypeToObject, getSubExpr); PASS_THROUGH_REFERENCE(ProtocolMetatypeToObject, getSubExpr); PASS_THROUGH_REFERENCE(InOutToPointer, getSubExpr); PASS_THROUGH_REFERENCE(ArrayToPointer, getSubExpr); PASS_THROUGH_REFERENCE(StringToPointer, getSubExpr); PASS_THROUGH_REFERENCE(PointerToPointer, getSubExpr); PASS_THROUGH_REFERENCE(ForeignObjectConversion, getSubExpr); PASS_THROUGH_REFERENCE(UnevaluatedInstance, getSubExpr); PASS_THROUGH_REFERENCE(DifferentiableFunction, getSubExpr); PASS_THROUGH_REFERENCE(LinearFunction, getSubExpr); PASS_THROUGH_REFERENCE(DifferentiableFunctionExtractOriginal, getSubExpr); PASS_THROUGH_REFERENCE(LinearFunctionExtractOriginal, getSubExpr); PASS_THROUGH_REFERENCE(LinearToDifferentiableFunction, getSubExpr); PASS_THROUGH_REFERENCE(BridgeToObjC, getSubExpr); PASS_THROUGH_REFERENCE(BridgeFromObjC, getSubExpr); PASS_THROUGH_REFERENCE(ConditionalBridgeFromObjC, getSubExpr); PASS_THROUGH_REFERENCE(UnderlyingToOpaque, getSubExpr); PASS_THROUGH_REFERENCE(Unreachable, getSubExpr); PASS_THROUGH_REFERENCE(ActorIsolationErasure, getSubExpr); PASS_THROUGH_REFERENCE(UnsafeCast, getSubExpr); NO_REFERENCE(Coerce); NO_REFERENCE(ForcedCheckedCast); NO_REFERENCE(ConditionalCheckedCast); NO_REFERENCE(Is); NO_REFERENCE(Arrow); NO_REFERENCE(Ternary); NO_REFERENCE(EnumIsCase); NO_REFERENCE(Assign); NO_REFERENCE(CodeCompletion); NO_REFERENCE(UnresolvedPattern); NO_REFERENCE(EditorPlaceholder); NO_REFERENCE(ObjCSelector); NO_REFERENCE(KeyPath); NO_REFERENCE(KeyPathDot); PASS_THROUGH_REFERENCE(CurrentContextIsolation, getActor); NO_REFERENCE(Tap); NO_REFERENCE(TypeJoin); SIMPLE_REFERENCE(MacroExpansion, getMacroRef); NO_REFERENCE(TypeValue); #undef SIMPLE_REFERENCE #undef NO_REFERENCE #undef PASS_THROUGH_REFERENCE } return ConcreteDeclRef(); } /// Enumerate each immediate child expression of this node, invoking the /// specific functor on it. This ignores statements and other non-expression /// children. void Expr:: forEachImmediateChildExpr(llvm::function_ref callback) { struct ChildWalker : ASTWalker { llvm::function_ref callback; Expr *ThisNode; /// Only walk the arguments of a macro, to represent the source as written. MacroWalking getMacroWalkingBehavior() const override { return MacroWalking::Arguments; } ChildWalker(llvm::function_ref callback, Expr *ThisNode) : callback(callback), ThisNode(ThisNode) {} PreWalkResult walkToExprPre(Expr *E) override { // When looking at the current node, of course we want to enter it. We // also don't want to enumerate it. if (E == ThisNode) return Action::Continue(E); // Otherwise we must be a child of our expression, enumerate it! E = callback(E); if (!E) return Action::Stop(); // We're only interested in the immediate children, so don't walk any // further. return Action::SkipNode(E); } PreWalkResult walkToStmtPre(Stmt *S) override { return Action::SkipNode(S); } PreWalkResult walkToPatternPre(Pattern *P) override { return Action::SkipNode(P); } PreWalkAction walkToDeclPre(Decl *D) override { return Action::SkipNode(); } PreWalkAction walkToTypeReprPre(TypeRepr *T) override { return Action::SkipNode(); } }; this->walk(ChildWalker(callback, this)); } /// Enumerate each immediate child expression of this node, invoking the /// specific functor on it. This ignores statements and other non-expression /// children. void Expr::forEachChildExpr(llvm::function_ref callback) { struct ChildWalker : ASTWalker { llvm::function_ref callback; /// Only walk the arguments of a macro, to represent the source as written. MacroWalking getMacroWalkingBehavior() const override { return MacroWalking::Arguments; } ChildWalker(llvm::function_ref callback) : callback(callback) {} PreWalkResult walkToExprPre(Expr *E) override { // Enumerate the node! E = callback(E); if (!E) return Action::Stop(); return Action::Continue(E); } PreWalkResult walkToStmtPre(Stmt *S) override { return Action::SkipNode(S); } PreWalkResult walkToPatternPre(Pattern *P) override { return Action::SkipNode(P); } PreWalkAction walkToDeclPre(Decl *D) override { return Action::SkipNode(); } PreWalkAction walkToTypeReprPre(TypeRepr *T) override { return Action::SkipNode(); } }; this->walk(ChildWalker(callback)); } bool Expr::isTypeReference(llvm::function_ref getType, llvm::function_ref getDecl) const { Expr *expr = const_cast(this); // If the result isn't a metatype, there's nothing else to do. if (!getType(expr)->is()) return false; do { // Skip syntax. expr = expr->getSemanticsProvidingExpr(); // Direct reference to a type. if (auto declRef = dyn_cast(expr)) if (isa(declRef->getDecl())) return true; if (isa(expr)) return true; // A "." expression that refers to a member. if (auto memberRef = dyn_cast(expr)) return isa(memberRef->getMember().getDecl()); // Any other expressions which might be referencing // a declaration e.g. not yet type-checked ones like // `UnresolvedDotExpr`. if (auto *decl = getDecl(expr)) return isa(decl); // When the base of a "." expression is ignored, look at the member. if (auto ignoredDot = dyn_cast(expr)) { expr = ignoredDot->getRHS(); continue; } if (auto *USE = dyn_cast(expr)) { expr = USE->getSubExpr(); continue; } // Anything else is not statically derived. return false; } while (true); } bool Expr::isStaticallyDerivedMetatype( llvm::function_ref getType, llvm::function_ref isTypeReference) const { // The expression must first be a type reference. if (!isTypeReference(const_cast(this))) return false; auto type = getType(const_cast(this)) ->castTo() ->getInstanceType(); // Archetypes are never statically derived. if (type->is()) return false; // Dynamic Self is never statically derived. if (type->is()) return false; // Everything else is statically derived. return true; } bool Expr::isSuperExpr() const { const Expr *expr = this; do { expr = expr->getSemanticsProvidingExpr(); if (isa(expr)) return true; if (auto derivedToBase = dyn_cast(expr)) { expr = derivedToBase->getSubExpr(); continue; } if (auto metatypeConversion = dyn_cast(expr)) { expr = metatypeConversion->getSubExpr(); continue; } return false; } while (true); } bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const { switch (getKind()) { case ExprKind::Error: case ExprKind::CodeCompletion: case ExprKind::LazyInitializer: return false; case ExprKind::NilLiteral: case ExprKind::IntegerLiteral: case ExprKind::FloatLiteral: case ExprKind::BooleanLiteral: case ExprKind::StringLiteral: case ExprKind::InterpolatedStringLiteral: case ExprKind::RegexLiteral: case ExprKind::MagicIdentifierLiteral: case ExprKind::ObjCSelector: case ExprKind::KeyPath: case ExprKind::SingleValueStmt: return true; case ExprKind::ObjectLiteral: return true; case ExprKind::DiscardAssignment: // Legal but pointless. return true; case ExprKind::DeclRef: return !cast(this)->getDecl()->isOperator(); case ExprKind::SuperRef: case ExprKind::OtherConstructorDeclRef: case ExprKind::DotSyntaxBaseIgnored: return true; case ExprKind::Type: return cast(this)->getTypeRepr()->isSimple(); case ExprKind::OverloadedDeclRef: { auto *overloadedExpr = cast(this); if (overloadedExpr->getDecls().empty()) return false; return !overloadedExpr->getDecls().front()->isOperator(); } case ExprKind::UnresolvedDeclRef: return cast(this)->getName().isOperator(); case ExprKind::MemberRef: case ExprKind::DynamicMemberRef: case ExprKind::DynamicSubscript: case ExprKind::UnresolvedSpecialize: case ExprKind::UnresolvedMember: case ExprKind::UnresolvedDot: case ExprKind::ExtractFunctionIsolation: return true; case ExprKind::Sequence: return false; case ExprKind::Paren: case ExprKind::DotSelf: case ExprKind::UnresolvedMemberChainResult: case ExprKind::Tuple: case ExprKind::Array: case ExprKind::Dictionary: case ExprKind::Subscript: case ExprKind::KeyPathApplication: case ExprKind::TupleElement: return true; case ExprKind::CaptureList: case ExprKind::Closure: case ExprKind::AutoClosure: return false; case ExprKind::DynamicType: return true; case ExprKind::Await: case ExprKind::Unsafe: case ExprKind::Consume: case ExprKind::Copy: case ExprKind::Borrow: case ExprKind::Try: case ExprKind::ForceTry: case ExprKind::OptionalTry: case ExprKind::InOut: return false; case ExprKind::RebindSelfInConstructor: case ExprKind::OpaqueValue: case ExprKind::PropertyWrapperValuePlaceholder: case ExprKind::AppliedPropertyWrapper: case ExprKind::DefaultArgument: case ExprKind::BindOptional: case ExprKind::OptionalEvaluation: return false; case ExprKind::ForceValue: return true; case ExprKind::OpenExistential: case ExprKind::MakeTemporarilyEscapable: case ExprKind::VarargExpansion: case ExprKind::PackExpansion: case ExprKind::PackElement: case ExprKind::MaterializePack: return false; case ExprKind::Call: case ExprKind::DotSyntaxCall: case ExprKind::ConstructorRefCall: return true; case ExprKind::PostfixUnary: return !appendingPostfixOperator; case ExprKind::PrefixUnary: case ExprKind::Binary: return false; case ExprKind::Load: case ExprKind::ABISafeConversion: case ExprKind::DestructureTuple: case ExprKind::FunctionConversion: case ExprKind::CovariantFunctionConversion: case ExprKind::CovariantReturnConversion: case ExprKind::MetatypeConversion: case ExprKind::CollectionUpcastConversion: case ExprKind::Erasure: case ExprKind::AnyHashableErasure: case ExprKind::DerivedToBase: case ExprKind::ArchetypeToSuper: case ExprKind::InjectIntoOptional: case ExprKind::ClassMetatypeToObject: case ExprKind::ExistentialMetatypeToObject: case ExprKind::ProtocolMetatypeToObject: case ExprKind::InOutToPointer: case ExprKind::ArrayToPointer: case ExprKind::StringToPointer: case ExprKind::PointerToPointer: case ExprKind::ForeignObjectConversion: case ExprKind::UnevaluatedInstance: case ExprKind::DifferentiableFunction: case ExprKind::LinearFunction: case ExprKind::DifferentiableFunctionExtractOriginal: case ExprKind::LinearFunctionExtractOriginal: case ExprKind::LinearToDifferentiableFunction: case ExprKind::EnumIsCase: case ExprKind::ConditionalBridgeFromObjC: case ExprKind::BridgeFromObjC: case ExprKind::BridgeToObjC: case ExprKind::UnderlyingToOpaque: case ExprKind::Unreachable: case ExprKind::ActorIsolationErasure: case ExprKind::UnsafeCast: case ExprKind::TypeValue: // Implicit conversion nodes have no syntax of their own; defer to the // subexpression. return cast(this)->getSubExpr() ->canAppendPostfixExpression(appendingPostfixOperator); case ExprKind::ForcedCheckedCast: case ExprKind::ConditionalCheckedCast: case ExprKind::Is: case ExprKind::Coerce: return false; case ExprKind::Arrow: case ExprKind::Ternary: case ExprKind::Assign: case ExprKind::UnresolvedPattern: case ExprKind::EditorPlaceholder: case ExprKind::KeyPathDot: case ExprKind::TypeJoin: return false; case ExprKind::Tap: return true; case ExprKind::MacroExpansion: case ExprKind::CurrentContextIsolation: return true; } llvm_unreachable("Unhandled ExprKind in switch."); } ArgumentList *Expr::getArgs() const { if (auto *AE = dyn_cast(this)) return AE->getArgs(); if (auto *SE = dyn_cast(this)) return SE->getArgs(); if (auto *DSE = dyn_cast(this)) return DSE->getArgs(); if (auto *OLE = dyn_cast(this)) return OLE->getArgs(); if (auto *ME = dyn_cast(this)) return ME->getArgs(); return nullptr; } DeclNameLoc Expr::getNameLoc() const { if (auto *DRE = dyn_cast(this)) return DRE->getNameLoc(); if (auto *UDRE = dyn_cast(this)) return UDRE->getNameLoc(); if (auto *ODRE = dyn_cast(this)) return ODRE->getNameLoc(); if (auto *UDE = dyn_cast(this)) return UDE->getNameLoc(); if (auto *UME = dyn_cast(this)) return UME->getNameLoc(); if (auto *MRE = dyn_cast(this)) return MRE->getNameLoc(); if (auto *DRME = dyn_cast(this)) return DRME->getNameLoc(); return DeclNameLoc(); } llvm::DenseMap Expr::getParentMap() { class RecordingTraversal : public ASTWalker { public: llvm::DenseMap &ParentMap; /// Walk everything that's available. MacroWalking getMacroWalkingBehavior() const override { return MacroWalking::ArgumentsAndExpansion; } explicit RecordingTraversal(llvm::DenseMap &parentMap) : ParentMap(parentMap) { } PreWalkResult walkToExprPre(Expr *E) override { if (auto parent = Parent.getAsExpr()) ParentMap[E] = parent; return Action::Continue(E); } }; llvm::DenseMap parentMap; RecordingTraversal traversal(parentMap); walk(traversal); return parentMap; } bool Expr::isValidParentOfTypeExpr(Expr *typeExpr) const { // Allow references to types as a part of: // - member references T.foo, T.Type, T.self, etc. // - constructor calls T() // - Subscripts T[] // // This is an exhaustive list of the accepted syntactic forms. switch (getKind()) { case ExprKind::Error: case ExprKind::DotSelf: case ExprKind::MemberRef: case ExprKind::UnresolvedMember: case ExprKind::DotSyntaxCall: case ExprKind::ConstructorRefCall: case ExprKind::UnresolvedDot: case ExprKind::DotSyntaxBaseIgnored: case ExprKind::UnresolvedSpecialize: case ExprKind::OpenExistential: case ExprKind::TypeValue: return true; // For these cases we need to ensure the type expr is the function or base. // We do not permit e.g 'foo(T)'. case ExprKind::Call: return cast(this)->getFn() == typeExpr; case ExprKind::Subscript: return cast(this)->getBase() == typeExpr; case ExprKind::NilLiteral: case ExprKind::BooleanLiteral: case ExprKind::IntegerLiteral: case ExprKind::FloatLiteral: case ExprKind::StringLiteral: case ExprKind::MagicIdentifierLiteral: case ExprKind::InterpolatedStringLiteral: case ExprKind::RegexLiteral: case ExprKind::ObjectLiteral: case ExprKind::DiscardAssignment: case ExprKind::DeclRef: case ExprKind::SuperRef: case ExprKind::Type: case ExprKind::OtherConstructorDeclRef: case ExprKind::OverloadedDeclRef: case ExprKind::UnresolvedDeclRef: case ExprKind::DynamicMemberRef: case ExprKind::DynamicSubscript: case ExprKind::Sequence: case ExprKind::Paren: case ExprKind::Await: case ExprKind::Unsafe: case ExprKind::Consume: case ExprKind::Copy: case ExprKind::Borrow: case ExprKind::UnresolvedMemberChainResult: case ExprKind::Try: case ExprKind::ForceTry: case ExprKind::OptionalTry: case ExprKind::Tuple: case ExprKind::Array: case ExprKind::Dictionary: case ExprKind::KeyPathApplication: case ExprKind::TupleElement: case ExprKind::CaptureList: case ExprKind::Closure: case ExprKind::AutoClosure: case ExprKind::InOut: case ExprKind::VarargExpansion: case ExprKind::PackExpansion: case ExprKind::PackElement: case ExprKind::MaterializePack: case ExprKind::DynamicType: case ExprKind::RebindSelfInConstructor: case ExprKind::OpaqueValue: case ExprKind::PropertyWrapperValuePlaceholder: case ExprKind::AppliedPropertyWrapper: case ExprKind::DefaultArgument: case ExprKind::BindOptional: case ExprKind::OptionalEvaluation: case ExprKind::ForceValue: case ExprKind::MakeTemporarilyEscapable: case ExprKind::PrefixUnary: case ExprKind::PostfixUnary: case ExprKind::Binary: case ExprKind::Load: case ExprKind::DestructureTuple: case ExprKind::ABISafeConversion: case ExprKind::FunctionConversion: case ExprKind::CovariantFunctionConversion: case ExprKind::CovariantReturnConversion: case ExprKind::MetatypeConversion: case ExprKind::CollectionUpcastConversion: case ExprKind::Erasure: case ExprKind::AnyHashableErasure: case ExprKind::BridgeToObjC: case ExprKind::BridgeFromObjC: case ExprKind::ConditionalBridgeFromObjC: case ExprKind::DerivedToBase: case ExprKind::ArchetypeToSuper: case ExprKind::InjectIntoOptional: case ExprKind::ClassMetatypeToObject: case ExprKind::ExistentialMetatypeToObject: case ExprKind::ProtocolMetatypeToObject: case ExprKind::InOutToPointer: case ExprKind::ArrayToPointer: case ExprKind::StringToPointer: case ExprKind::PointerToPointer: case ExprKind::ForeignObjectConversion: case ExprKind::UnevaluatedInstance: case ExprKind::UnderlyingToOpaque: case ExprKind::Unreachable: case ExprKind::DifferentiableFunction: case ExprKind::LinearFunction: case ExprKind::DifferentiableFunctionExtractOriginal: case ExprKind::LinearFunctionExtractOriginal: case ExprKind::LinearToDifferentiableFunction: case ExprKind::ForcedCheckedCast: case ExprKind::ConditionalCheckedCast: case ExprKind::Is: case ExprKind::Coerce: case ExprKind::Arrow: case ExprKind::Ternary: case ExprKind::EnumIsCase: case ExprKind::Assign: case ExprKind::CodeCompletion: case ExprKind::UnresolvedPattern: case ExprKind::LazyInitializer: case ExprKind::EditorPlaceholder: case ExprKind::ObjCSelector: case ExprKind::KeyPath: case ExprKind::KeyPathDot: case ExprKind::Tap: case ExprKind::SingleValueStmt: case ExprKind::TypeJoin: case ExprKind::MacroExpansion: case ExprKind::CurrentContextIsolation: case ExprKind::ActorIsolationErasure: case ExprKind::ExtractFunctionIsolation: case ExprKind::UnsafeCast: return false; } llvm_unreachable("Unhandled ExprKind in switch."); } //===----------------------------------------------------------------------===// // Support methods for Exprs. //===----------------------------------------------------------------------===// StringRef LiteralExpr::getLiteralKindDescription() const { switch (getKind()) { case ExprKind::IntegerLiteral: return "integer"; case ExprKind::FloatLiteral: return "floating-point"; case ExprKind::BooleanLiteral: return "boolean"; case ExprKind::StringLiteral: return "string"; case ExprKind::InterpolatedStringLiteral: return "string"; case ExprKind::RegexLiteral: return "regular expression"; case ExprKind::MagicIdentifierLiteral: return MagicIdentifierLiteralExpr::getKindString( cast(this)->getKind()); case ExprKind::NilLiteral: return "nil"; case ExprKind::ObjectLiteral: return "object"; // Define an unreachable case for all non-literal expressions. // This way, if a new literal is added in the future, the compiler // will warn that a case is missing from this switch. #define LITERAL_EXPR(Id, Parent) #define EXPR(Id, Parent) case ExprKind::Id: #include "swift/AST/ExprNodes.def" llvm_unreachable("Not a literal expression"); } llvm_unreachable("Unhandled literal"); } void BuiltinLiteralExpr::setBuiltinInitializer( ConcreteDeclRef builtinInitializer) { ASSERT(builtinInitializer); BuiltinInitializer = builtinInitializer; } IntegerLiteralExpr * IntegerLiteralExpr::createFromUnsigned( ASTContext &C, unsigned value, SourceLoc loc) { llvm::SmallString<8> Scratch; llvm::APInt(sizeof(unsigned)*8, value).toString(Scratch, 10, /*signed*/ false); auto Text = C.AllocateCopy(StringRef(Scratch)); return new (C) IntegerLiteralExpr(Text, loc, /*implicit*/ true); } APInt IntegerLiteralExpr::getRawValue() const { return BuiltinIntegerWidth::arbitrary().parse(getDigitsText(), /*radix*/0, isNegative()); } APInt IntegerLiteralExpr::getValue() const { assert(!getType().isNull() && "Semantic analysis has not completed"); assert(!getType()->hasError() && "Should have a valid type"); if (!getType()->is()) return getRawValue(); auto width = getType()->castTo()->getWidth(); return width.parse(getDigitsText(), /*radix*/ 0, isNegative()); } APInt BuiltinIntegerWidth::parse(StringRef text, unsigned radix, bool negate, bool *hadError) const { if (hadError) *hadError = false; // Parse an unsigned value from the string. APInt value; // Swift doesn't treat a leading zero as signifying octal, but // StringRef::getAsInteger does. Force decimal parsing in this case. if (radix == 0 && text.size() >= 2 && text[0] == '0' && isdigit(text[1])) radix = 10; bool error = text.getAsInteger(radix, value); if (error) { if (hadError) *hadError = true; return value; } // If we're producing an arbitrary-precision value, we don't need to do // much additional processing. if (isArbitraryWidth()) { // The parser above always produces a non-negative value, so if the sign // bit is set we need to give it some breathing room. if (value.isNegative()) value = value.zext(value.getBitWidth() + 1); assert(!value.isNegative()); // Now we can safely negate. if (negate) { value = -value; assert(value.isNegative() || value.isZero()); } // Truncate down to the minimum number of bits required to express // this value exactly. auto requiredBits = value.getSignificantBits(); if (value.getBitWidth() > requiredBits) value = value.trunc(requiredBits); // If we have a fixed-width type (including abstract ones), we need to do // fixed-width transformations, which can overflow. } else { unsigned width = getGreatestWidth(); // The overflow diagnostics in this case can't be fully correct because // we don't know whether we're supposed to be producing a signed number // or an unsigned one. if (hadError && value.getActiveBits() > width) *hadError = true; value = value.zextOrTrunc(width); if (negate) { value = -value; if (hadError && !value.isNegative()) *hadError = true; } assert(value.getBitWidth() == width); } return value; } static APFloat getFloatLiteralValue(bool IsNegative, StringRef Text, const llvm::fltSemantics &Semantics) { APFloat Val(Semantics); auto Res = Val.convertFromString(Text, llvm::APFloat::rmNearestTiesToEven); assert(Res && "Sema didn't reject invalid number"); consumeError(Res.takeError()); if (IsNegative) { auto NegVal = APFloat::getZero(Semantics, /*negative*/ true); Res = NegVal.subtract(Val, llvm::APFloat::rmNearestTiesToEven); assert(Res && "Sema didn't reject invalid number"); consumeError(Res.takeError()); return NegVal; } return Val; } APFloat FloatLiteralExpr::getValue(StringRef Text, const llvm::fltSemantics &Semantics, bool Negative) { return getFloatLiteralValue(Negative, Text, Semantics); } llvm::APFloat FloatLiteralExpr::getValue() const { assert(!getType().isNull() && "Semantic analysis has not completed"); assert(!getType()->hasError() && "Should have a valid type"); Type ty = getType(); if (!ty->is()) { assert(!getBuiltinType().isNull() && "Semantic analysis has not completed"); assert(!getBuiltinType()->hasError() && "Should have a valid type"); ty = getBuiltinType(); } return getFloatLiteralValue( isNegative(), getDigitsText(), ty->castTo()->getAPFloatSemantics()); } StringLiteralExpr::StringLiteralExpr(StringRef Val, SourceRange Range, bool Implicit) : BuiltinLiteralExpr(ExprKind::StringLiteral, Implicit), Val(Val), Range(Range) { Bits.StringLiteralExpr.Encoding = static_cast(UTF8); Bits.StringLiteralExpr.IsSingleUnicodeScalar = unicode::isSingleUnicodeScalar(Val); Bits.StringLiteralExpr.IsSingleExtendedGraphemeCluster = unicode::isSingleExtendedGraphemeCluster(Val); } ObjectLiteralExpr::ObjectLiteralExpr(SourceLoc poundLoc, LiteralKind litKind, ArgumentList *argList, bool implicit) : LiteralExpr(ExprKind::ObjectLiteral, implicit), ArgList(argList), PoundLoc(poundLoc) { assert(argList); Bits.ObjectLiteralExpr.LitKind = static_cast(litKind); assert(getLiteralKind() == litKind); } ObjectLiteralExpr * ObjectLiteralExpr::create(ASTContext &ctx, SourceLoc poundLoc, LiteralKind kind, ArgumentList *args, bool implicit) { return new (ctx) ObjectLiteralExpr(poundLoc, kind, args, implicit); } StringRef ObjectLiteralExpr::getLiteralKindRawName() const { switch (getLiteralKind()) { #define POUND_OBJECT_LITERAL(Name, Desc, Proto) case Name: return #Name; #include "swift/AST/TokenKinds.def" } llvm_unreachable("unspecified literal"); } StringRef ObjectLiteralExpr:: getLiteralKindPlainName(ObjectLiteralExpr::LiteralKind kind) { switch (kind) { #define POUND_OBJECT_LITERAL(Name, Desc, Proto) case Name: return Desc; #include "swift/AST/TokenKinds.def" } llvm_unreachable("unspecified literal"); } StringRef ObjectLiteralExpr::getLiteralKindPlainName() const { return ObjectLiteralExpr::getLiteralKindPlainName(getLiteralKind()); } ConstructorDecl *OtherConstructorDeclRefExpr::getDecl() const { return cast_or_null(Ctor.getDecl()); } MemberRefExpr::MemberRefExpr(Expr *base, SourceLoc dotLoc, ConcreteDeclRef member, DeclNameLoc nameLoc, bool Implicit, AccessSemantics semantics) : LookupExpr(ExprKind::MemberRef, base, member, Implicit), DotLoc(dotLoc), NameLoc(nameLoc) { Bits.MemberRefExpr.Semantics = (unsigned) semantics; } Type OverloadSetRefExpr::getBaseType() const { if (isa(this)) return Type(); llvm_unreachable("Unhandled overloaded set reference expression"); } bool OverloadSetRefExpr::hasBaseObject() const { if (Type BaseTy = getBaseType()) return !BaseTy->is(); return false; } InOutExpr::InOutExpr(SourceLoc operLoc, Expr *subExpr, Type baseType, bool isImplicit) : Expr(ExprKind::InOut, isImplicit, baseType.isNull() ? baseType : InOutType::get(baseType)), SubExpr(subExpr), OperLoc(operLoc) {} VarargExpansionExpr *VarargExpansionExpr::createParamExpansion(ASTContext &ctx, Expr *E) { assert(E->getType() && "Expansion must have fully-resolved type!"); return new (ctx) VarargExpansionExpr(E, /*implicit*/ true, E->getType()); } VarargExpansionExpr *VarargExpansionExpr::createArrayExpansion(ASTContext &ctx, ArrayExpr *AE) { assert(AE->getType() && "Expansion must have fully-resolved type!"); return new (ctx) VarargExpansionExpr(AE, /*implicit*/ true, AE->getType()); } PackExpansionExpr * PackExpansionExpr::create(ASTContext &ctx, SourceLoc repeatLoc, Expr *patternExpr, GenericEnvironment *environment, bool implicit, Type type) { return new (ctx) PackExpansionExpr(repeatLoc, patternExpr, environment, implicit, type); } PackElementExpr * PackElementExpr::create(ASTContext &ctx, SourceLoc eachLoc, Expr *packRefExpr, bool implicit, Type type) { return new (ctx) PackElementExpr(eachLoc, packRefExpr, implicit, type); } MaterializePackExpr * MaterializePackExpr::create(ASTContext &ctx, Expr *fromExpr, SourceLoc elementLoc, Type type, bool implicit) { return new (ctx) MaterializePackExpr(fromExpr, elementLoc, type, implicit); } SequenceExpr *SequenceExpr::create(ASTContext &ctx, ArrayRef elements) { assert(elements.size() & 1 && "even number of elements in sequence"); size_t bytes = totalSizeToAlloc(elements.size()); void *Buffer = ctx.Allocate(bytes, alignof(SequenceExpr)); return ::new (Buffer) SequenceExpr(elements); } ErasureExpr *ErasureExpr::create(ASTContext &ctx, Expr *subExpr, Type type, ArrayRef conformances, ArrayRef argConversions) { auto layout = type->getExistentialLayout(); assert(layout.getProtocols().size() == conformances.size()); auto size = totalSizeToAlloc(conformances.size(), argConversions.size()); auto mem = ctx.Allocate(size, alignof(ErasureExpr)); return ::new (mem) ErasureExpr(subExpr, type, conformances, argConversions); } UnresolvedSpecializeExpr *UnresolvedSpecializeExpr::create(ASTContext &ctx, Expr *SubExpr, SourceLoc LAngleLoc, ArrayRef UnresolvedParams, SourceLoc RAngleLoc) { auto size = totalSizeToAlloc(UnresolvedParams.size()); auto mem = ctx.Allocate(size, alignof(UnresolvedSpecializeExpr)); return ::new (mem) UnresolvedSpecializeExpr(SubExpr, LAngleLoc, UnresolvedParams, RAngleLoc); } CaptureListEntry::CaptureListEntry(PatternBindingDecl *PBD) : PBD(PBD) { assert(PBD); assert(PBD->getSingleVar() && "Capture lists only support single-var patterns"); } CaptureListEntry CaptureListEntry::createParsed( ASTContext &Ctx, ReferenceOwnership ownershipKind, SourceRange ownershipRange, Identifier name, SourceLoc nameLoc, SourceLoc equalLoc, Expr *initializer, DeclContext *DC) { bool forceVar = ownershipKind == ReferenceOwnership::Weak && !Ctx.LangOpts.hasFeature(Feature::ImmutableWeakCaptures); auto introducer = forceVar ? VarDecl::Introducer::Var : VarDecl::Introducer::Let; auto *VD = new (Ctx) VarDecl(/*isStatic==*/false, introducer, nameLoc, name, DC); if (ownershipKind != ReferenceOwnership::Strong) VD->addAttribute(new (Ctx) ReferenceOwnershipAttr(ownershipRange, ownershipKind)); auto *pattern = NamedPattern::createImplicit(Ctx, VD); auto *PBD = PatternBindingDecl::create(Ctx, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None, nameLoc, pattern, equalLoc, initializer, DC); CaptureListEntry CLE(PBD); if (CLE.isSimpleSelfCapture()) VD->setIsSelfParamCapture(); return CLE; } VarDecl *CaptureListEntry::getVar() const { return PBD->getSingleVar(); } bool CaptureListEntry::isSimpleSelfCapture(bool excludeWeakCaptures) const { auto *Var = getVar(); auto &ctx = Var->getASTContext(); if (Var->getName() != ctx.Id_self) return false; if (PBD->getPatternList().size() != 1) return false; auto *expr = PBD->getInit(0); if (auto *attr = Var->getAttrs().getAttribute()) { if (attr->get() == ReferenceOwnership::Weak && excludeWeakCaptures) { return false; } } // Look through any ImplicitConversionExpr that may contain the DRE if (auto conversion = dyn_cast_or_null(expr)) { expr = conversion->getSubExpr(); } if (auto *DRE = dyn_cast(expr)) { if (auto *VD = dyn_cast(DRE->getDecl())) { return VD->getName() == ctx.Id_self; } } if (auto *UDRE = dyn_cast(expr)) { return UDRE->getName().isSimpleName(ctx.Id_self); } return false; } CaptureListExpr *CaptureListExpr::create(ASTContext &ctx, ArrayRef captureList, AbstractClosureExpr *closureBody) { auto size = totalSizeToAlloc(captureList.size()); auto mem = ctx.Allocate(size, alignof(CaptureListExpr)); auto *expr = ::new(mem) CaptureListExpr(captureList, closureBody); for (auto capture : captureList) capture.getVar()->setParentCaptureList(expr); return expr; } DestructureTupleExpr * DestructureTupleExpr::create(ASTContext &ctx, ArrayRef destructuredElements, Expr *srcExpr, Expr *dstExpr, Type ty) { auto size = totalSizeToAlloc(destructuredElements.size()); auto mem = ctx.Allocate(size, alignof(DestructureTupleExpr)); return ::new(mem) DestructureTupleExpr(destructuredElements, srcExpr, dstExpr, ty); } SourceRange TupleExpr::getSourceRange() const { auto start = LParenLoc; if (start.isInvalid()) { // Scan forward for the first valid source loc. for (auto *expr : getElements()) { start = expr->getStartLoc(); if (start.isValid()) break; } } auto end = RParenLoc; if (end.isInvalid()) { // Scan backwards for a valid source loc. for (auto *expr : llvm::reverse(getElements())) { end = expr->getEndLoc(); if (end.isValid()) break; } } if (start.isInvalid() || end.isInvalid()) return SourceRange(); return SourceRange(start, end); } TupleExpr::TupleExpr(SourceLoc LParenLoc, SourceLoc RParenLoc, ArrayRef SubExprs, ArrayRef ElementNames, ArrayRef ElementNameLocs, bool Implicit, Type Ty) : Expr(ExprKind::Tuple, Implicit, Ty), LParenLoc(LParenLoc), RParenLoc(RParenLoc) { Bits.TupleExpr.HasElementNames = !ElementNames.empty(); Bits.TupleExpr.HasElementNameLocations = !ElementNameLocs.empty(); Bits.TupleExpr.NumElements = SubExprs.size(); assert(LParenLoc.isValid() == RParenLoc.isValid() && "Mismatched parenthesis location information validity"); assert(ElementNames.empty() || ElementNames.size() == SubExprs.size()); assert(ElementNameLocs.empty() || ElementNames.size() == ElementNameLocs.size()); // Copy elements. std::uninitialized_copy(SubExprs.begin(), SubExprs.end(), getTrailingObjects()); // Copy element names, if provided. if (hasElementNames()) { std::uninitialized_copy(ElementNames.begin(), ElementNames.end(), getTrailingObjects()); } // Copy element name locations, if provided. if (hasElementNameLocs()) { std::uninitialized_copy(ElementNameLocs.begin(), ElementNameLocs.end(), getTrailingObjects()); } } TupleExpr *TupleExpr::create(ASTContext &ctx, SourceLoc LParenLoc, ArrayRef SubExprs, ArrayRef ElementNames, ArrayRef ElementNameLocs, SourceLoc RParenLoc, bool Implicit, Type Ty) { assert(!Ty || isa(Ty.getPointer())); auto hasNonEmptyIdentifier = [](ArrayRef Ids) -> bool { for (auto ident : Ids) { if (!ident.empty()) return true; } return false; }; assert((Implicit || ElementNames.size() == ElementNameLocs.size() || (!hasNonEmptyIdentifier(ElementNames) && ElementNameLocs.empty())) && "trying to create non-implicit tuple-expr without name locations"); (void)hasNonEmptyIdentifier; size_t size = totalSizeToAlloc(SubExprs.size(), ElementNames.size(), ElementNameLocs.size()); void *mem = ctx.Allocate(size, alignof(TupleExpr)); return new (mem) TupleExpr(LParenLoc, RParenLoc, SubExprs, ElementNames, ElementNameLocs, Implicit, Ty); } TupleExpr *TupleExpr::createEmpty(ASTContext &ctx, SourceLoc LParenLoc, SourceLoc RParenLoc, bool Implicit) { return create(ctx, LParenLoc, {}, {}, {}, RParenLoc, Implicit, TupleType::getEmpty(ctx)); } TupleExpr *TupleExpr::createImplicit(ASTContext &ctx, ArrayRef SubExprs, ArrayRef ElementNames) { return create(ctx, SourceLoc(), SubExprs, ElementNames, {}, SourceLoc(), /*Implicit=*/true, Type()); } ArrayExpr *ArrayExpr::create(ASTContext &C, SourceLoc LBracketLoc, ArrayRef Elements, ArrayRef CommaLocs, SourceLoc RBracketLoc, Type Ty) { auto Size = totalSizeToAlloc(Elements.size(), CommaLocs.size()); auto Mem = C.Allocate(Size, alignof(ArrayExpr)); return new (Mem) ArrayExpr(LBracketLoc, Elements, CommaLocs, RBracketLoc, Ty); } Type ArrayExpr::getElementType() { auto init = getInitializer(); if (!init) return Type(); auto *decl = cast(init.getDecl()); return decl->getMethodInterfaceType() ->getAs() ->getParams()[0] .getPlainType() .subst(init.getSubstitutions()); } Type DictionaryExpr::getElementType() { auto init = getInitializer(); if (!init) return Type(); auto *decl = cast(init.getDecl()); return decl->getMethodInterfaceType() ->getAs() ->getParams()[0] .getPlainType() .subst(init.getSubstitutions()); } DictionaryExpr *DictionaryExpr::create(ASTContext &C, SourceLoc LBracketLoc, ArrayRef Elements, ArrayRef CommaLocs, SourceLoc RBracketLoc, Type Ty) { auto Size = totalSizeToAlloc(Elements.size(), CommaLocs.size()); auto Mem = C.Allocate(Size, alignof(DictionaryExpr)); return new (Mem) DictionaryExpr(LBracketLoc, Elements, CommaLocs, RBracketLoc, Ty); } static ValueDecl *getCalledValue(Expr *E, bool skipFunctionConversions) { if (auto *DRE = dyn_cast(E)) return DRE->getDecl(); if (auto *OCRE = dyn_cast(E)) return OCRE->getDecl(); // Look through SelfApplyExpr. if (auto *SAE = dyn_cast(E)) return SAE->getCalledValue(skipFunctionConversions); if (skipFunctionConversions) { if (auto fnConv = dyn_cast(E)) return getCalledValue(fnConv->getSubExpr(), skipFunctionConversions); if (auto *actorErasure = dyn_cast(E)) return getCalledValue(actorErasure->getSubExpr(), skipFunctionConversions); } Expr *E2 = E->getValueProvidingExpr(); if (E != E2) return getCalledValue(E2, skipFunctionConversions); return nullptr; } OpaqueValueExpr *OpaqueValueExpr::createImplicit(ASTContext &ctx, Type Ty, bool isPlaceholder, AllocationArena arena) { auto *mem = ctx.Allocate(sizeof(OpaqueValueExpr), alignof(OpaqueValueExpr), arena); return new (mem) OpaqueValueExpr( /*Range=*/SourceRange(), Ty, isPlaceholder); } PropertyWrapperValuePlaceholderExpr * PropertyWrapperValuePlaceholderExpr::create(ASTContext &ctx, SourceRange range, Type ty, Expr *wrappedValue, bool isAutoClosure) { OpaqueValueExpr *placeholder = nullptr; if (ty) placeholder = new (ctx) OpaqueValueExpr(range, ty, /*isPlaceholder=*/true); return new (ctx) PropertyWrapperValuePlaceholderExpr( range, ty, placeholder, wrappedValue, isAutoClosure); } AppliedPropertyWrapperExpr * AppliedPropertyWrapperExpr::create(ASTContext &ctx, ConcreteDeclRef callee, const ParamDecl *param, SourceLoc loc, Type Ty, Expr *value, AppliedPropertyWrapperExpr::ValueKind kind) { return new (ctx) AppliedPropertyWrapperExpr(callee, param, loc, Ty, value, kind); } const ParamDecl *DefaultArgumentExpr::getParamDecl() const { return getParameterAt(DefaultArgsOwner.getDecl(), ParamIndex); } bool DefaultArgumentExpr::isCallerSide() const { return getParamDecl()->hasCallerSideDefaultExpr(); } Expr *DefaultArgumentExpr::getCallerSideDefaultExpr() const { assert(isCallerSide()); auto &ctx = DefaultArgsOwner.getDecl()->getASTContext(); auto *mutableThis = const_cast(this); if (auto result = evaluateOrDefault(ctx.evaluator, CallerSideDefaultArgExprRequest{mutableThis}, nullptr)) return result; return new (ctx) ErrorExpr(getSourceRange(), getType()); } ActorIsolation DefaultArgumentExpr::getRequiredIsolation() const { return getParamDecl()->getInitializerIsolation(); } ValueDecl *ApplyExpr::getCalledValue(bool skipFunctionConversions) const { return ::getCalledValue(Fn, skipFunctionConversions); } SubscriptExpr::SubscriptExpr(Expr *base, ArgumentList *argList, ConcreteDeclRef decl, bool implicit, AccessSemantics semantics) : LookupExpr(ExprKind::Subscript, base, decl, implicit), ArgList(argList) { Bits.SubscriptExpr.Semantics = (unsigned) semantics; } SubscriptExpr *SubscriptExpr::create(ASTContext &ctx, Expr *base, ArgumentList *argList, ConcreteDeclRef decl, bool implicit, AccessSemantics semantics) { return new (ctx) SubscriptExpr(base, argList, decl, implicit, semantics); } DynamicSubscriptExpr::DynamicSubscriptExpr(Expr *base, ArgumentList *argList, ConcreteDeclRef member, bool implicit) : DynamicLookupExpr(ExprKind::DynamicSubscript, member, base), ArgList(argList) { if (implicit) setImplicit(implicit); } DynamicSubscriptExpr *DynamicSubscriptExpr::create(ASTContext &ctx, Expr *base, ArgumentList *argList, ConcreteDeclRef member, bool implicit) { return new (ctx) DynamicSubscriptExpr(base, argList, member, implicit); } CallExpr::CallExpr(Expr *fn, ArgumentList *argList, bool implicit, Type ty) : ApplyExpr(ExprKind::Call, fn, argList, implicit, ty) { #ifndef NDEBUG Expr *calleeFn = fn->getSemanticsProvidingExpr(); if (auto *calleeDRE = dyn_cast(calleeFn)) assert(!calleeDRE->getDecl()->isInstanceMember()); #endif } CallExpr *CallExpr::create(ASTContext &ctx, Expr *fn, ArgumentList *argList, bool implicit) { return new (ctx) CallExpr(fn, argList, implicit, Type()); } CallExpr *CallExpr::createImplicitEmpty(ASTContext &ctx, Expr *fn) { return createImplicit(ctx, fn, ArgumentList::createImplicit(ctx, {})); } Expr *CallExpr::getDirectCallee() const { auto fn = getFn(); while (true) { fn = fn->getSemanticsProvidingExpr(); if (auto force = dyn_cast(fn)) { fn = force->getSubExpr(); continue; } if (auto bind = dyn_cast(fn)) { fn = bind->getSubExpr(); continue; } if (auto ctorCall = dyn_cast(fn)) { fn = ctorCall->getFn(); continue; } // Explicit specializations are currently invalid for function calls, but // look through them for better recovery. if (auto *spec = dyn_cast(fn)) { fn = spec->getSubExpr(); continue; } return fn; } } PrefixUnaryExpr *PrefixUnaryExpr::create(ASTContext &ctx, Expr *fn, Expr *operand, Type ty) { auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {operand}); return new (ctx) PrefixUnaryExpr(fn, argList, ty); } PostfixUnaryExpr *PostfixUnaryExpr::create(ASTContext &ctx, Expr *fn, Expr *operand, Type ty) { auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {operand}); return new (ctx) PostfixUnaryExpr(fn, argList, ty); } BinaryExpr *BinaryExpr::create(ASTContext &ctx, Expr *lhs, Expr *fn, Expr *rhs, bool implicit, Type ty) { auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {lhs, rhs}); return new (ctx) BinaryExpr(fn, argList, implicit, ty); } DotSyntaxCallExpr *DotSyntaxCallExpr::create(ASTContext &ctx, Expr *fnExpr, SourceLoc dotLoc, Argument baseArg, Type ty) { assert(!baseArg.hasLabel()); auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {baseArg.getExpr()}); return new (ctx) DotSyntaxCallExpr(fnExpr, dotLoc, argList, ty); } SourceLoc DotSyntaxCallExpr::getLoc() const { if (isImplicit()) { SourceLoc baseLoc = getBase()->getLoc(); return baseLoc.isValid() ? baseLoc : getFn()->getLoc(); } return getFn()->getLoc(); } SourceLoc DotSyntaxCallExpr::getStartLoc() const { if (isImplicit()) { SourceLoc baseLoc = getBase()->getStartLoc(); return baseLoc.isValid() ? baseLoc : getFn()->getStartLoc(); } return getBase()->getStartLoc(); } SourceLoc DotSyntaxCallExpr::getEndLoc() const { if (isImplicit()) { SourceLoc fnLoc = getFn()->getEndLoc(); return fnLoc.isValid() ? fnLoc : getBase()->getEndLoc(); } return getFn()->getEndLoc(); } ConstructorRefCallExpr *ConstructorRefCallExpr::create(ASTContext &ctx, Expr *fnExpr, Expr *baseExpr, Type ty) { auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {baseExpr}); return new (ctx) ConstructorRefCallExpr(fnExpr, argList, ty); } void ExplicitCastExpr::setCastType(Type type) { CastTy->setType(MetatypeType::get(type)); } ForcedCheckedCastExpr *ForcedCheckedCastExpr::create(ASTContext &ctx, SourceLoc asLoc, SourceLoc exclaimLoc, TypeRepr *tyRepr) { return new (ctx) ForcedCheckedCastExpr(nullptr, asLoc, exclaimLoc, new (ctx) TypeExpr(tyRepr)); } ForcedCheckedCastExpr * ForcedCheckedCastExpr::createImplicit(ASTContext &ctx, Expr *sub, Type castTy) { auto *const expr = new (ctx) ForcedCheckedCastExpr( sub, SourceLoc(), SourceLoc(), TypeExpr::createImplicit(castTy, ctx)); expr->setType(castTy); expr->setImplicit(); return expr; } ConditionalCheckedCastExpr * ConditionalCheckedCastExpr::create(ASTContext &ctx, SourceLoc asLoc, SourceLoc questionLoc, TypeRepr *tyRepr) { return new (ctx) ConditionalCheckedCastExpr(nullptr, asLoc, questionLoc, new (ctx) TypeExpr(tyRepr)); } ConditionalCheckedCastExpr * ConditionalCheckedCastExpr::createImplicit(ASTContext &ctx, Expr *sub, Type castTy) { auto *const expr = new (ctx) ConditionalCheckedCastExpr( sub, SourceLoc(), SourceLoc(), TypeExpr::createImplicit(castTy, ctx)); expr->setType(OptionalType::get(castTy)); expr->setImplicit(); return expr; } IsExpr *IsExpr::create(ASTContext &ctx, SourceLoc isLoc, TypeRepr *tyRepr) { return new (ctx) IsExpr(nullptr, isLoc, new (ctx) TypeExpr(tyRepr)); } CoerceExpr *CoerceExpr::create(ASTContext &ctx, SourceLoc asLoc, TypeRepr *tyRepr) { return new (ctx) CoerceExpr(nullptr, asLoc, new (ctx) TypeExpr(tyRepr)); } CoerceExpr *CoerceExpr::createImplicit(ASTContext &ctx, Expr *sub, Type castTy) { auto *const expr = new (ctx) CoerceExpr(sub, SourceLoc(), TypeExpr::createImplicit(castTy, ctx)); expr->setType(castTy); expr->setImplicit(); return expr; } CoerceExpr *CoerceExpr::forLiteralInit(ASTContext &ctx, Expr *literal, SourceRange range, TypeRepr *literalTyRepr) { auto *const expr = new (ctx) CoerceExpr(range, literal, new (ctx) TypeExpr(literalTyRepr)); expr->setImplicit(); return expr; } RebindSelfInConstructorExpr::RebindSelfInConstructorExpr(Expr *SubExpr, VarDecl *Self) : Expr(ExprKind::RebindSelfInConstructor, /*Implicit=*/true, TupleType::getEmpty(Self->getASTContext())), SubExpr(SubExpr), Self(Self) {} OtherConstructorDeclRefExpr * RebindSelfInConstructorExpr::getCalledConstructor(bool &isChainToSuper) const { // Dig out the OtherConstructorDeclRefExpr. Note that this is the reverse // of what we do in pre-checking. Expr *candidate = getSubExpr(); while (true) { // Look through identity expressions. if (auto identity = dyn_cast(candidate)) { candidate = identity->getSubExpr(); continue; } // Look through force-value expressions. if (auto force = dyn_cast(candidate)) { candidate = force->getSubExpr(); continue; } // Look through all try expressions. if (auto tryExpr = dyn_cast(candidate)) { candidate = tryExpr->getSubExpr(); continue; } // Look through covariant return expressions. if (auto covariantExpr = dyn_cast(candidate)) { candidate = covariantExpr->getSubExpr(); continue; } // Look through inject into optional expressions if (auto injectIntoOptionalExpr = dyn_cast(candidate)) { candidate = injectIntoOptionalExpr->getSubExpr(); continue; } // Look through open existential expressions if (auto openExistentialExpr = dyn_cast(candidate)) { candidate = openExistentialExpr->getSubExpr(); continue; } break; } // We hit an application, find the constructor reference. OtherConstructorDeclRefExpr *otherCtorRef; const ApplyExpr *apply; do { apply = cast(candidate); candidate = apply->getFn(); auto candidateUnwrapped = candidate->getSemanticsProvidingExpr(); otherCtorRef = dyn_cast(candidateUnwrapped); } while (!otherCtorRef); auto *unaryArg = apply->getArgs()->getUnaryExpr(); assert(unaryArg); isChainToSuper = unaryArg->isSuperExpr(); return otherCtorRef; } unsigned AbstractClosureExpr::getDiscriminator() const { auto raw = getRawDiscriminator(); if (raw != InvalidDiscriminator) return raw; ASTContext &ctx = getASTContext(); evaluateOrDefault( ctx.evaluator, LocalDiscriminatorsRequest{getParent()}, 0); #if NDEBUG static constexpr bool useFallbackDiscriminator = true; #else static constexpr bool useFallbackDiscriminator = false; #endif // If we don't have a discriminator, and either // 1. We have ill-formed code and we're able to assign a discriminator, or // 2. We are in a macro expansion buffer // 3. We are within top-level code where there's nothing to anchor to // // then assign the next discriminator now. if (getRawDiscriminator() == InvalidDiscriminator && (ctx.Diags.hadAnyError() || getParentSourceFile()->getFulfilledMacroRole() != std::nullopt || getParent()->isModuleScopeContext() || useFallbackDiscriminator)) { auto discriminator = ctx.getNextDiscriminator(getParent()); ctx.setMaxAssignedDiscriminator(getParent(), discriminator + 1); const_cast(this)-> Bits.AbstractClosureExpr.Discriminator = discriminator; } if (getRawDiscriminator() == InvalidDiscriminator) { ABORT([&](auto &out) { out << "Closure does not have an assigned discriminator:\n"; this->dump(out); }); } return getRawDiscriminator(); } void AbstractClosureExpr::setParameterList(ParameterList *P) { parameterList = P; // Change the DeclContext of any parameters to be this closure. if (P) P->setDeclContextOfParamDecls(this); } BraceStmt * AbstractClosureExpr::getBody() const { if (const AutoClosureExpr *autocls = dyn_cast(this)) return autocls->getBody(); if (const ClosureExpr *cls = dyn_cast(this)) return cls->getBody(); llvm_unreachable("Unknown closure expression"); } BraceStmt *ClosureExpr::getExpandedBody() { auto &ctx = getASTContext(); // Expand a body macro, if there is one. BraceStmt *macroExpandedBody = nullptr; if (auto bufferID = evaluateOrDefault( ctx.evaluator, ExpandBodyMacroRequest{this}, std::nullopt)) { CharSourceRange bufferRange = ctx.SourceMgr.getRangeForBuffer(*bufferID); auto bufferStart = bufferRange.getStart(); auto module = getParentModule(); auto macroSourceFile = module->getSourceFileContainingLocation(bufferStart); if (macroSourceFile->getTopLevelItems().size() == 1) { auto stmt = macroSourceFile->getTopLevelItems()[0].dyn_cast(); macroExpandedBody = dyn_cast(stmt); } } return macroExpandedBody; } bool AbstractClosureExpr::bodyHasExplicitReturnStmt() const { return AnyFunctionRef(const_cast(this)) .bodyHasExplicitReturnStmt(); } void AbstractClosureExpr::getExplicitReturnStmts( SmallVectorImpl &results) const { AnyFunctionRef(const_cast(this)) .getExplicitReturnStmts(results); } Type AbstractClosureExpr::getResultType( llvm::function_ref getType) const { auto *E = const_cast(this); Type T = getType(E); if (!T || T->hasError()) return T; return T->castTo()->getResult(); } std::optional AbstractClosureExpr::getEffectiveThrownType() const { if (auto fnType = getType()->getAs()) return fnType->getEffectiveThrownErrorType(); return std::nullopt; } bool AbstractClosureExpr::isBodyThrowing() const { if (!getType() || getType()->hasError()) { // Scan the closure body to infer effects. if (auto closure = dyn_cast(this)) { return evaluateOrDefault( getASTContext().evaluator, ClosureEffectsRequest{const_cast(closure)}, FunctionType::ExtInfo()).isThrowing(); } return false; } return getType()->castTo()->getExtInfo().isThrowing(); } bool AbstractClosureExpr::isSendable() const { if (!getType() || getType()->hasError()) { // Scan the closure body to infer effects. if (auto closure = dyn_cast(this)) { return evaluateOrDefault( getASTContext().evaluator, ClosureEffectsRequest{const_cast(closure)}, FunctionType::ExtInfo()).isSendable(); } return false; } return getType()->castTo()->getExtInfo().isSendable(); } bool AbstractClosureExpr::isBodyAsync() const { if (!getType() || getType()->hasError()) { // Scan the closure body to infer effects. if (auto closure = dyn_cast(this)) { return evaluateOrDefault( getASTContext().evaluator, ClosureEffectsRequest{const_cast(closure)}, FunctionType::ExtInfo()).isAsync(); } return false; } return getType()->castTo()->getExtInfo().isAsync(); } bool AbstractClosureExpr::hasSingleExpressionBody() const { if (auto closure = dyn_cast(this)) return closure->hasSingleExpressionBody(); return true; } Expr *AbstractClosureExpr::getSingleExpressionBody() const { if (auto closure = dyn_cast(this)) return closure->getSingleExpressionBody(); else if (auto autoclosure = dyn_cast(this)) return autoclosure->getSingleExpressionBody(); return nullptr; } ActorIsolation swift::__AbstractClosureExpr_getActorIsolation(AbstractClosureExpr *CE) { return CE->getActorIsolation(); } #define FORWARD_SOURCE_LOCS_TO(CLASS, NODE) \ SourceRange CLASS::getSourceRange() const { \ if (!NODE) { return SourceRange(); } \ return (NODE)->getSourceRange(); \ } \ SourceLoc CLASS::getStartLoc() const { \ if (!NODE) { return SourceLoc(); } \ return (NODE)->getStartLoc(); \ } \ SourceLoc CLASS::getEndLoc() const { \ if (!NODE) { return SourceLoc(); } \ return (NODE)->getEndLoc(); \ } \ SourceLoc CLASS::getLoc() const { \ if (!NODE) { return SourceLoc(); } \ return (NODE)->getStartLoc(); \ } FORWARD_SOURCE_LOCS_TO(ClosureExpr, Body) Expr *ClosureExpr::getSingleExpressionBody() const { auto *body = getBody(); if (!body) return nullptr; // If we have a lone expression, use it. if (auto *E = body->getSingleActiveExpression()) return E; // Otherwise we must have a return of an expression. auto elt = body->getSingleActiveStatement(); if (!elt) return nullptr; // Any lone ReturnStmt, even explicit, is treated as a single expression body. auto *RS = dyn_cast(elt); if (!RS || !RS->hasResult()) return nullptr; return RS->getResult(); } bool ClosureExpr::hasEmptyBody() const { return getBody()->empty(); } Type ClosureExpr::getExplicitThrownType() const { if (getThrowsLoc().isInvalid()) return Type(); ASTContext &ctx = getASTContext(); auto mutableThis = const_cast(this); ExplicitCaughtTypeRequest request{&ctx, mutableThis}; return evaluateOrDefault(ctx.evaluator, request, Type()); } void ClosureExpr::setExplicitResultType(Type ty) { assert(ty && !ty->hasTypeVariable() && !ty->hasPlaceholder()); ExplicitResultTypeAndBodyState.getPointer() ->setType(MetatypeType::get(ty)); } FORWARD_SOURCE_LOCS_TO(AutoClosureExpr, Body) void AutoClosureExpr::setBody(Expr *E) { auto &Context = getASTContext(); auto *RS = ReturnStmt::createImplicit(Context, E); Body = BraceStmt::create(Context, E->getStartLoc(), { RS }, E->getEndLoc()); } Expr *AutoClosureExpr::getSingleExpressionBody() const { return cast(cast(Body->getLastElement()))->getResult(); } Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const { auto maybeUnwrapOpenExistential = [](Expr *expr) { if (auto *openExistential = dyn_cast(expr)) { expr = openExistential->getSubExpr()->getSemanticsProvidingExpr(); if (auto *ICE = dyn_cast(expr)) expr = ICE->getSyntacticSubExpr(); } return expr; }; auto maybeUnwrapOptionalEval = [](Expr *expr) { if (auto optEval = dyn_cast(expr)) expr = optEval->getSubExpr(); if (auto inject = dyn_cast(expr)) expr = inject->getSubExpr(); if (auto erasure = dyn_cast(expr)) expr = erasure->getSubExpr(); if (auto bind = dyn_cast(expr)) expr = bind->getSubExpr(); return expr; }; auto maybeUnwrapConversions = [](Expr *expr) { if (auto *covariantReturn = dyn_cast(expr)) expr = covariantReturn->getSubExpr(); if (auto *functionConversion = dyn_cast(expr)) expr = functionConversion->getSubExpr(); return expr; }; switch (getThunkKind()) { case AutoClosureExpr::Kind::None: case AutoClosureExpr::Kind::AsyncLet: break; case AutoClosureExpr::Kind::SingleCurryThunk: { auto *body = getSingleExpressionBody(); body = body->getSemanticsProvidingExpr(); body = maybeUnwrapOpenExistential(body); body = maybeUnwrapOptionalEval(body); body = maybeUnwrapConversions(body); if (auto *outerCall = dyn_cast(body)) { return outerCall->getFn(); } assert(false && "Malformed curry thunk?"); break; } case AutoClosureExpr::Kind::DoubleCurryThunk: { auto *body = getSingleExpressionBody(); if (auto *innerClosure = dyn_cast(body)) { assert(innerClosure->getThunkKind() == AutoClosureExpr::Kind::SingleCurryThunk); auto *innerBody = innerClosure->getSingleExpressionBody(); innerBody = innerBody->getSemanticsProvidingExpr(); innerBody = maybeUnwrapOpenExistential(innerBody); innerBody = maybeUnwrapOptionalEval(innerBody); innerBody = maybeUnwrapConversions(innerBody); if (auto *outerCall = dyn_cast(innerBody)) { auto outerFn = maybeUnwrapConversions(outerCall->getFn()); if (auto *innerCall = dyn_cast(outerFn)) { return innerCall->getFn(); } } } assert(false && "Malformed curry thunk?"); break; } } return nullptr; } FORWARD_SOURCE_LOCS_TO(UnresolvedPatternExpr, subPattern) TypeExpr::TypeExpr(TypeRepr *Repr) : Expr(ExprKind::Type, /*implicit*/false), Repr(Repr) {} TypeExpr *TypeExpr::createImplicit(Type Ty, ASTContext &C) { assert(Ty); auto *result = new (C) TypeExpr(nullptr); result->setType(MetatypeType::get(Ty, Ty->getASTContext())); result->setImplicit(); return result; } // The type of a TypeExpr is always a metatype type. Return the instance // type or null if not set yet. Type TypeExpr::getInstanceType() const { auto ty = getType(); if (!ty) return Type(); if (auto metaType = ty->getAs()) return metaType->getInstanceType(); return ErrorType::get(ty->getASTContext()); } TypeExpr *TypeExpr::createForDecl(DeclNameLoc Loc, TypeDecl *Decl, DeclContext *DC) { ASTContext &C = Decl->getASTContext(); assert(Loc.isValid()); auto *Repr = UnqualifiedIdentTypeRepr::create(C, Loc, Decl->createNameRef()); Repr->setValue(Decl, DC); return new (C) TypeExpr(Repr); } TypeExpr *TypeExpr::createImplicitForDecl(DeclNameLoc Loc, TypeDecl *Decl, DeclContext *DC, Type ty) { ASTContext &C = Decl->getASTContext(); auto *Repr = UnqualifiedIdentTypeRepr::create(C, Loc, Decl->createNameRef()); Repr->setValue(Decl, DC); auto result = new (C) TypeExpr(Repr); assert(ty && !ty->hasTypeParameter()); result->setType(ty); result->setImplicit(); return result; } TypeExpr *TypeExpr::createForMemberDecl(DeclNameLoc ParentNameLoc, TypeDecl *Parent, DeclNameLoc NameLoc, TypeDecl *Decl) { ASTContext &C = Decl->getASTContext(); assert(ParentNameLoc.isValid()); assert(NameLoc.isValid()); // The base is the parent type. auto *BaseTR = UnqualifiedIdentTypeRepr::create(C, ParentNameLoc, Parent->createNameRef()); BaseTR->setValue(Parent, nullptr); auto *QualIdentTR = QualifiedIdentTypeRepr::create(C, BaseTR, NameLoc, Decl->createNameRef()); QualIdentTR->setValue(Decl, nullptr); return new (C) TypeExpr(QualIdentTR); } TypeExpr *TypeExpr::createForMemberDecl(TypeRepr *ParentTR, DeclNameLoc NameLoc, TypeDecl *Decl) { ASTContext &C = Decl->getASTContext(); auto *QualIdentTR = QualifiedIdentTypeRepr::create(C, ParentTR, NameLoc, Decl->createNameRef()); QualIdentTR->setValue(Decl, nullptr); return new (C) TypeExpr(QualIdentTR); } TypeExpr *TypeExpr::createForSpecializedDecl(DeclRefTypeRepr *ParentTR, ArrayRef Args, SourceRange AngleLocs, ASTContext &C) { DeclRefTypeRepr *specializedTR = nullptr; auto *boundDecl = ParentTR->getBoundDecl(); if (!boundDecl || ParentTR->hasGenericArgList()) { return nullptr; } if (isa(ParentTR)) { specializedTR = UnqualifiedIdentTypeRepr::create( C, ParentTR->getNameLoc(), ParentTR->getNameRef(), Args, AngleLocs); specializedTR->setValue(boundDecl, ParentTR->getDeclContext()); } else { auto *const qualIdentTR = cast(ParentTR); specializedTR = QualifiedIdentTypeRepr::create( C, qualIdentTR->getBase(), ParentTR->getNameLoc(), ParentTR->getNameRef(), Args, AngleLocs); specializedTR->setValue(boundDecl, ParentTR->getDeclContext()); } return new (C) TypeExpr(specializedTR); } // Create an implicit TypeExpr, with location information even though it // shouldn't have one. This is presently used to work around other location // processing bugs. If you have an implicit location, use createImplicit. TypeExpr *TypeExpr::createImplicitHack(SourceLoc Loc, Type Ty, ASTContext &C) { // FIXME: This is horrible. assert(Ty); if (Loc.isInvalid()) return createImplicit(Ty, C); auto *Repr = new (C) FixedTypeRepr(Ty, Loc); auto *Res = new (C) TypeExpr(Repr); Res->setType(MetatypeType::get(Ty, C)); Res->setImplicit(); return Res; } SourceRange TypeExpr::getSourceRange() const { if (!getTypeRepr()) return SourceRange(); return getTypeRepr()->getSourceRange(); } bool Expr::isSelfExprOf(const AbstractFunctionDecl *AFD, bool sameBase) const { auto *E = getSemanticsProvidingExpr(); if (auto IOE = dyn_cast(E)) E = IOE->getSubExpr(); while (auto ICE = dyn_cast(E)) { if (sameBase && isa(ICE)) return false; E = ICE->getSubExpr(); } if (auto DRE = dyn_cast(E)) return DRE->getDecl() == AFD->getImplicitSelfDecl(); return false; } TypeValueExpr *TypeValueExpr::createForDecl(DeclNameLoc loc, TypeDecl *decl, DeclContext *dc) { auto &ctx = decl->getASTContext(); ASSERT(loc.isValid()); auto repr = UnqualifiedIdentTypeRepr::create(ctx, loc, decl->createNameRef()); repr->setValue(decl, dc); return new (ctx) TypeValueExpr(repr); } GenericTypeParamDecl *TypeValueExpr::getParamDecl() const { auto declRefRepr = cast(getRepr()); return cast(declRefRepr->getBoundDecl()); } SourceRange TypeValueExpr::getSourceRange() const { return getRepr()->getSourceRange(); } ExistentialArchetypeType *OpenExistentialExpr::getOpenedArchetype() const { auto type = getOpaqueValue()->getType()->getRValueType(); while (auto metaTy = type->getAs()) type = metaTy->getInstanceType(); return type->castTo(); } KeyPathExpr::KeyPathExpr(SourceLoc startLoc, Expr *parsedRoot, Expr *parsedPath, SourceLoc endLoc, bool hasLeadingDot, bool isObjC, bool isImplicit) : Expr(ExprKind::KeyPath, isImplicit), StartLoc(startLoc), EndLoc(endLoc), ParsedRoot(parsedRoot), ParsedPath(parsedPath), HasLeadingDot(hasLeadingDot) { assert(!(isObjC && (parsedRoot || parsedPath)) && "Obj-C key paths should only have components"); Bits.KeyPathExpr.IsObjC = isObjC; } KeyPathExpr::KeyPathExpr(SourceLoc backslashLoc, Expr *parsedRoot, Expr *parsedPath, bool hasLeadingDot, bool isImplicit) : KeyPathExpr(backslashLoc, parsedRoot, parsedPath, parsedPath ? parsedPath->getEndLoc() : parsedRoot->getEndLoc(), hasLeadingDot, /*isObjC*/ false, isImplicit) { assert((parsedRoot || parsedPath) && "Key path must have either root or path"); } KeyPathExpr::KeyPathExpr(ASTContext &ctx, SourceLoc startLoc, ArrayRef components, SourceLoc endLoc, bool isObjC, bool isImplicit) : KeyPathExpr(startLoc, /*parsedRoot*/ nullptr, /*parsedPath*/ nullptr, endLoc, /*hasLeadingDot*/ false, isObjC, isImplicit) { assert(!components.empty()); Components = ctx.AllocateCopy(components); } KeyPathExpr *KeyPathExpr::createParsedPoundKeyPath( ASTContext &ctx, SourceLoc keywordLoc, SourceLoc lParenLoc, ArrayRef components, SourceLoc rParenLoc) { return new (ctx) KeyPathExpr(ctx, keywordLoc, components, rParenLoc, /*isObjC*/ true, /*isImplicit*/ false); } KeyPathExpr *KeyPathExpr::createParsed(ASTContext &ctx, SourceLoc backslashLoc, Expr *parsedRoot, Expr *parsedPath, bool hasLeadingDot) { return new (ctx) KeyPathExpr(backslashLoc, parsedRoot, parsedPath, hasLeadingDot, /*isImplicit*/ false); } KeyPathExpr *KeyPathExpr::createImplicit(ASTContext &ctx, SourceLoc backslashLoc, ArrayRef components, SourceLoc endLoc) { return new (ctx) KeyPathExpr(ctx, backslashLoc, components, endLoc, /*isObjC*/ false, /*isImplicit*/ true); } KeyPathExpr *KeyPathExpr::createImplicit(ASTContext &ctx, SourceLoc backslashLoc, Expr *parsedRoot, Expr *parsedPath, bool hasLeadingDot) { return new (ctx) KeyPathExpr(backslashLoc, parsedRoot, parsedPath, hasLeadingDot, /*isImplicit*/ true); } void KeyPathExpr::setComponents(ASTContext &C, ArrayRef newComponents) { // Reallocate the components array if it needs to be. if (Components.size() < newComponents.size()) { Components = C.Allocate(newComponents.size()); for (unsigned i : indices(Components)) { ::new ((void*)&Components[i]) Component{}; } } for (unsigned i : indices(newComponents)) { Components[i] = newComponents[i]; } Components = Components.slice(0, newComponents.size()); } std::optional KeyPathExpr::findComponentWithSubscriptArg(Expr *arg) { for (auto idx : indices(getComponents())) { if (auto *args = getComponents()[idx].getArgs()) { if (args->findArgumentExpr(arg)) return idx; } } return std::nullopt; } BoundGenericType *KeyPathExpr::getKeyPathType() const { auto type = getType(); if (!type) return nullptr; if (auto *existentialTy = type->getAs()) { auto *sendableTy = existentialTy->getConstraintType()->castTo(); assert(sendableTy->getMembers().size() == 2); type = sendableTy->getExistentialLayout().explicitSuperclass; assert(type->isKeyPath() || type->isWritableKeyPath() || type->isReferenceWritableKeyPath()); } return type->castTo(); } Type KeyPathExpr::getRootType() const { auto keyPathTy = getKeyPathType(); assert(keyPathTy && "key path type has not been set yet"); return keyPathTy->getGenericArgs()[0]; } Type KeyPathExpr::getValueType() const { auto keyPathTy = getKeyPathType(); assert(keyPathTy && "key path type has not been set yet"); return keyPathTy->getGenericArgs()[1]; } KeyPathExpr::Component KeyPathExpr::Component::forSubscript( ASTContext &ctx, ConcreteDeclRef subscript, ArgumentList *argList, Type elementType, ArrayRef indexHashables) { return Component(subscript, argList, indexHashables, Kind::Subscript, elementType, argList->getLParenLoc()); } KeyPathExpr::Component KeyPathExpr::Component::forUnresolvedSubscript(ASTContext &ctx, ArgumentList *argList) { return Component({}, argList, {}, Kind::UnresolvedSubscript, Type(), argList->getLParenLoc()); } KeyPathExpr::Component::Component( DeclNameOrRef decl, ArgumentList *argList, ArrayRef indexHashables, Kind kind, Type type, SourceLoc loc) : Decl(decl), ArgList(argList), KindValue(kind), ComponentType(type), Loc(loc) { assert(kind == Kind::Subscript || kind == Kind::UnresolvedSubscript || kind == Kind::UnresolvedApply || kind == Kind::Apply); assert(argList); assert(argList->size() == indexHashables.size() || indexHashables.empty()); HashableConformancesData = indexHashables.empty() ? nullptr : indexHashables.data(); } SingleValueStmtExpr *SingleValueStmtExpr::create(ASTContext &ctx, Stmt *S, DeclContext *DC) { return new (ctx) SingleValueStmtExpr(S, DC); } SingleValueStmtExpr *SingleValueStmtExpr::createWithWrappedBranches( ASTContext &ctx, Stmt *S, DeclContext *DC, bool mustBeExpr) { assert(!(isa(S) || isa(S)) || ctx.LangOpts.hasFeature(Feature::DoExpressions)); auto *SVE = create(ctx, S, DC); // Attempt to wrap any branches that can be wrapped. SmallVector scratch; for (auto *branch : SVE->getBranches(scratch)) { auto *BS = dyn_cast(branch); if (!BS) continue; // Check to see if we can wrap an implicit last element of the brace. if (!isLastElementImplicitResult(BS, ctx, mustBeExpr)) continue; auto &result = BS->getElements().back(); assert(isa(result) || isa(result)); // Wrap a statement in a SingleValueStmtExpr. if (auto *S = result.dyn_cast()) { result = SingleValueStmtExpr::createWithWrappedBranches(ctx, S, DC, mustBeExpr); } // Wrap an expression in an implicit 'then '. if (auto *E = result.dyn_cast()) result = ThenStmt::createImplicit(ctx, E); } return SVE; } SingleValueStmtExpr * SingleValueStmtExpr::tryDigOutSingleValueStmtExpr(Expr *E) { class SVEFinder final : public ASTWalker { public: SingleValueStmtExpr *FoundSVE = nullptr; PreWalkResult walkToExprPre(Expr *E) override { if (auto *SVE = dyn_cast(E)) { FoundSVE = SVE; return Action::Stop(); } // Look through implicit exprs. if (E->isImplicit()) return Action::Continue(E); // Look through coercions. if (isa(E)) return Action::Continue(E); // Look through try/await/unsafe (this is invalid, but we'll error on // it in effect checking). if (isa(E) || isa(E) || isa(E)) return Action::Continue(E); return Action::Stop(); } PreWalkResult walkToStmtPre(Stmt *S) override { return Action::Stop(); } PreWalkAction walkToDeclPre(Decl *D) override { return Action::Stop(); } PreWalkResult walkToPatternPre(Pattern *P) override { return Action::Stop(); } PreWalkAction walkToTypeReprPre(TypeRepr *T) override { return Action::Stop(); } }; SVEFinder finder; E->walk(finder); return finder.FoundSVE; } bool SingleValueStmtExpr::isLastElementImplicitResult( BraceStmt *BS, ASTContext &ctx, bool mustBeSingleValueStmt) { if (BS->empty()) return false; // We must either be allowing implicit last expressions, or we must have a // single active element, which is guaranteed to be the last element. if (!ctx.LangOpts.hasFeature(Feature::ImplicitLastExprResults) && !BS->getSingleActiveElement()) { return false; } auto elt = BS->getLastElement(); // Expressions are always valid. if (isa(elt)) return true; if (auto *S = elt.dyn_cast()) { if (mustBeSingleValueStmt) { // If this must be a SingleValueStmtExpr, we can eagerly take any // exhaustive if, switch, and do statement. if (auto *IS = dyn_cast(S)) return IS->isSyntacticallyExhaustive(); // Guaranteed to be exhaustive. if (isa(S)) return true; if (ctx.LangOpts.hasFeature(Feature::DoExpressions)) { if (auto *DCS = dyn_cast(S)) return DCS->isSyntacticallyExhaustive(); if (isa(S)) return true; } return false; } // Otherwise do the semantic checking to verify the statement produces // a single value. return S->mayProduceSingleValue(ctx).isValid(); } return false; } ThenStmt *SingleValueStmtExpr::getThenStmtFrom(BraceStmt *BS) { if (BS->empty()) return nullptr; // Must be the last statement in the brace. return dyn_cast_or_null(BS->getLastElement().dyn_cast()); } SourceRange SingleValueStmtExpr::getSourceRange() const { return S->getSourceRange(); } SingleValueStmtExpr::Kind SingleValueStmtExpr::getStmtKind() const { switch (getStmt()->getKind()) { case StmtKind::If: return Kind::If; case StmtKind::Switch: return Kind::Switch; case StmtKind::Do: return Kind::Do; case StmtKind::DoCatch: return Kind::DoCatch; case StmtKind::ForEach: return Kind::For; default: llvm_unreachable("Unhandled kind!"); } } ArrayRef SingleValueStmtExpr::getBranches(SmallVectorImpl &scratch) const { assert(scratch.empty()); switch (getStmtKind()) { case Kind::If: return cast(getStmt())->getBranches(scratch); case Kind::Switch: return cast(getStmt())->getBranches(scratch); case Kind::Do: scratch.push_back(cast(getStmt())->getBody()); return scratch; case Kind::DoCatch: return cast(getStmt())->getBranches(scratch); case Kind::For: scratch.push_back(cast(getStmt())->getBody()); return scratch; } llvm_unreachable("Unhandled case in switch!"); } ArrayRef SingleValueStmtExpr::getThenStmts( SmallVectorImpl &scratch) const { assert(scratch.empty()); SmallVector stmtScratch; for (auto *branch : getBranches(stmtScratch)) { auto *BS = dyn_cast(branch); if (!BS) continue; if (auto *TS = getThenStmtFrom(BS)) scratch.push_back(TS); } return scratch; } ArrayRef SingleValueStmtExpr::getResultExprs( SmallVectorImpl &scratch) const { assert(scratch.empty()); SmallVector stmtScratch; for (auto *TS : getThenStmts(stmtScratch)) scratch.push_back(TS->getResult()); return scratch; } void InterpolatedStringLiteralExpr::forEachSegment(ASTContext &Ctx, llvm::function_ref callback) { auto appendingExpr = getAppendingExpr(); for (auto stmt : appendingExpr->getBody()->getElements()) { if (auto expr = stmt.dyn_cast()) { if (auto call = dyn_cast(expr)) { DeclName name; if (auto fn = call->getCalledValue()) { name = fn->getName(); } else if (auto unresolvedDot = dyn_cast(call->getFn())) { name = unresolvedDot->getName().getFullName(); } bool isInterpolation = (name.getBaseName() == Ctx.Id_appendInterpolation); callback(isInterpolation, call); } } } } TapExpr::TapExpr(Expr * SubExpr, BraceStmt *Body) : Expr(ExprKind::Tap, /*Implicit=*/true), SubExpr(SubExpr), Body(Body) { assert(Body); assert(!Body->empty() && Body->getFirstElement().isDecl(DeclKind::Var) && "First element of Body should be a variable to init with the subExpr"); } VarDecl * TapExpr::getVar() const { return dyn_cast(Body->getFirstElement().dyn_cast()); } SourceRange TapExpr::getSourceRange() const { if (!SubExpr) return Body->getSourceRange(); return SourceRange::combine(SubExpr->getSourceRange(), Body->getSourceRange()); } RegexLiteralExpr *RegexLiteralExpr::createParsed(ASTContext &ctx, SourceLoc loc, StringRef regexText) { return new (ctx) RegexLiteralExpr(&ctx, loc, regexText, /*implicit*/ false); } StringRef RegexLiteralExpr::getRegexToEmit() const { auto &eval = getASTContext().evaluator; return evaluateOrDefault(eval, RegexLiteralPatternInfoRequest{this}, {}) .RegexToEmit; } Type RegexLiteralExpr::getRegexType() const { auto &eval = getASTContext().evaluator; return evaluateOrDefault(eval, RegexLiteralPatternInfoRequest{this}, {}) .RegexType; } unsigned RegexLiteralExpr::getVersion() const { auto &eval = getASTContext().evaluator; return evaluateOrDefault(eval, RegexLiteralPatternInfoRequest{this}, {}) .Version; } ArrayRef RegexLiteralExpr::getPatternFeatures() const { auto &eval = getASTContext().evaluator; return evaluateOrDefault(eval, RegexLiteralPatternInfoRequest{this}, {}) .Features; } StringRef RegexLiteralPatternFeatureKind::getDescription(ASTContext &ctx) const { auto &eval = ctx.evaluator; return evaluateOrDefault( eval, RegexLiteralFeatureDescriptionRequest{*this, &ctx}, {}); } AvailabilityRange RegexLiteralPatternFeatureKind::getAvailability(ASTContext &ctx) const { auto &eval = ctx.evaluator; return evaluateOrDefault(eval, RegexLiteralFeatureAvailabilityRequest{*this, &ctx}, AvailabilityRange::alwaysAvailable()); } TypeJoinExpr::TypeJoinExpr(llvm::PointerUnion result, ArrayRef elements, SingleValueStmtExpr *SVE) : Expr(ExprKind::TypeJoin, /*implicit=*/true, Type()), Var(nullptr), SVE(SVE) { if (auto *varRef = result.dyn_cast()) { assert(varRef); Var = varRef; } else { auto joinType = Type(cast(result)); assert(joinType && "expected non-null type"); setType(joinType); } Bits.TypeJoinExpr.NumElements = elements.size(); // Copy elements. std::uninitialized_copy(elements.begin(), elements.end(), getTrailingObjects()); } TypeJoinExpr *TypeJoinExpr::createImpl( ASTContext &ctx, llvm::PointerUnion varOrType, ArrayRef elements, AllocationArena arena, SingleValueStmtExpr *SVE) { size_t size = totalSizeToAlloc(elements.size()); void *mem = ctx.Allocate(size, alignof(TypeJoinExpr), arena); return new (mem) TypeJoinExpr(varOrType, elements, SVE); } TypeJoinExpr * TypeJoinExpr::forBranchesOfSingleValueStmtExpr(ASTContext &ctx, Type joinType, SingleValueStmtExpr *SVE, AllocationArena arena) { return createImpl(ctx, joinType.getPointer(), /*elements*/ {}, arena, SVE); } MacroExpansionExpr *MacroExpansionExpr::create( DeclContext *dc, SourceLoc sigilLoc, DeclNameRef moduleName, DeclNameLoc moduleNameLoc, DeclNameRef macroName, DeclNameLoc macroNameLoc, SourceLoc leftAngleLoc, ArrayRef genericArgs, SourceLoc rightAngleLoc, ArgumentList *argList, MacroRoles roles, bool isImplicit, Type ty ) { ASTContext &ctx = dc->getASTContext(); MacroExpansionInfo *info = new (ctx) MacroExpansionInfo{ sigilLoc, moduleName, moduleNameLoc, macroName, macroNameLoc, leftAngleLoc, rightAngleLoc, genericArgs, argList ? argList : ArgumentList::createImplicit(ctx, {})}; return new (ctx) MacroExpansionExpr(dc, info, roles, isImplicit, ty); } MacroExpansionDecl *MacroExpansionExpr::createSubstituteDecl() { auto dc = DC; if (auto *tlcd = dyn_cast_or_null(dc->getAsDecl())) dc = tlcd->getDeclContext(); SubstituteDecl = new (DC->getASTContext()) MacroExpansionDecl(dc, getExpansionInfo()); return SubstituteDecl; } MacroExpansionDecl *MacroExpansionExpr::getSubstituteDecl() const { return SubstituteDecl; } void swift::simple_display(llvm::raw_ostream &out, const ClosureExpr *CE) { if (!CE) { out << "(null)"; return; } out << "closure"; } void swift::simple_display(llvm::raw_ostream &out, const DefaultArgumentExpr *expr) { if (!expr) { out << "(null)"; return; } out << "default arg for param "; out << "#" << expr->getParamIndex() + 1 << " "; out << "of "; simple_display(out, expr->getDefaultArgsOwner().getDecl()); } void swift::simple_display(llvm::raw_ostream &out, const Expr *expr) { out << "expression"; } SourceLoc swift::extractNearestSourceLoc(const ClosureExpr *expr) { return expr->getLoc(); } SourceLoc swift::extractNearestSourceLoc(const Expr *expr) { return expr->getLoc(); } // See swift/Basic/Statistic.h for declaration: this enables tracing Exprs, is // defined here to avoid too much layering violation / circular linkage // dependency. struct ExprTraceFormatter : public UnifiedStatsReporter::TraceFormatter { void traceName(const void *Entity, raw_ostream &OS) const override { if (!Entity) return; const Expr *E = static_cast(Entity); OS << Expr::getKindName(E->getKind()); } void traceLoc(const void *Entity, SourceManager *SM, clang::SourceManager *CSM, raw_ostream &OS) const override { if (!Entity) return; const Expr *E = static_cast(Entity); E->getSourceRange().print(OS, *SM, false); } }; static ExprTraceFormatter TF; template<> const UnifiedStatsReporter::TraceFormatter* FrontendStatsTracer::getTraceFormatter() { return &TF; } Expr *Expr::getAlwaysLeftFoldedSubExpr() const { if (auto *ATE = dyn_cast(this)) return ATE->getSubExpr(); if (auto *AE = dyn_cast(this)) return AE->getSubExpr(); if (auto *UE = dyn_cast(this)) return UE->getSubExpr(); return nullptr; } const Expr *Expr::findOriginalValue() const { auto *expr = this; do { expr = expr->getSemanticsProvidingExpr(); if (auto inout = dyn_cast(expr)) { expr = inout->getSubExpr(); continue; } if (auto ice = dyn_cast(expr)) { expr = ice->getSubExpr(); continue; } if (auto open = dyn_cast(expr)) { expr = open->getSubExpr(); continue; } break; } while (true); return expr; } Type Expr::findOriginalType() const { auto *expr = findOriginalValue(); return expr->getType()->getRValueType(); } ThrownErrorDestination ThrownErrorDestination::forConversion(OpaqueValueExpr *thrownError, Expr *conversion) { ASTContext &ctx = thrownError->getType()->getASTContext(); auto conversionStorage = ctx.Allocate(); conversionStorage->thrownError = thrownError; conversionStorage->conversion = conversion; return ThrownErrorDestination(conversionStorage); } Type ThrownErrorDestination::getThrownErrorType() const { if (!*this) return Type(); if (auto type = storage.dyn_cast()) return Type(type); auto conversion = cast(storage); return conversion->thrownError->getType(); } Type ThrownErrorDestination::getContextErrorType() const { if (!*this) return Type(); if (auto type = storage.dyn_cast()) return Type(type); auto conversion = cast(storage); return conversion->conversion->getType(); } void AbstractClosureExpr::getIsolationCrossing( SmallVectorImpl> &foundIsolationCrossings) { /// For each capture... for (auto pair : llvm::enumerate(getCaptureInfo().getCaptures())) { auto capture = pair.value(); // First check quickly if we have dynamic self metadata. This is Sendable // data so we don't care about it. if (capture.isDynamicSelfMetadata()) continue; auto declIsolation = swift::getActorIsolation(capture.getDecl()); // Assert that we do not have an opaque value capture. These only appear in // TypeLowering and should never appear in the AST itself. assert(!capture.getOpaqueValue() && "This should only be created in TypeLowering"); // If our decl is actor isolated... if (declIsolation.isActorIsolated()) { // And our closure is also actor isolated, then add the apply isolation // crossing if the actors are different. if (actorIsolation.isActorIsolated()) { if (declIsolation.getActor() == actorIsolation.getActor()) { continue; } foundIsolationCrossings.emplace_back( capture, pair.index(), ApplyIsolationCrossing(declIsolation, actorIsolation)); continue; } // Otherwise, our closure is not actor isolated but our decl is actor // isolated. Add it. foundIsolationCrossings.emplace_back( capture, pair.index(), ApplyIsolationCrossing(declIsolation, actorIsolation)); continue; } if (!actorIsolation.isActorIsolated()) { continue; } foundIsolationCrossings.emplace_back( capture, pair.index(), ApplyIsolationCrossing(declIsolation, actorIsolation)); } }