diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 9775f22a404..f103f2b0284 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -7894,6 +7894,8 @@ public: /// attribute. bool isTransparent() const; + bool isCoroutine() const; + // Expose our import as member status ImportAsMemberStatus getImportAsMemberStatus() const { return ImportAsMemberStatus(Bits.AbstractFunctionDecl.IAMStatus); diff --git a/include/swift/AST/DeclAttr.def b/include/swift/AST/DeclAttr.def index b85c52cdc2f..433608dd379 100644 --- a/include/swift/AST/DeclAttr.def +++ b/include/swift/AST/DeclAttr.def @@ -910,7 +910,12 @@ SIMPLE_DECL_ATTR(_unsafeSelfDependentResult, UnsafeSelfDependentResult, UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIBreakingToRemove | EquivalentInABIAttr, 173) -LAST_DECL_ATTR(UnsafeSelfDependentResult) +SIMPLE_DECL_ATTR(yield_once, Coroutine, + OnFunc, + UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | EquivalentInABIAttr, + 174) + +LAST_DECL_ATTR(Coroutine) #undef DECL_ATTR_ALIAS #undef CONTEXTUAL_DECL_ATTR_ALIAS diff --git a/include/swift/AST/ExtInfo.h b/include/swift/AST/ExtInfo.h index 28f30af1d87..55557d59023 100644 --- a/include/swift/AST/ExtInfo.h +++ b/include/swift/AST/ExtInfo.h @@ -323,7 +323,7 @@ enum class SILFunctionTypeRepresentation : uint8_t { CFunctionPointer = uint8_t(FunctionTypeRepresentation::CFunctionPointer), /// The value of the greatest AST function representation. - LastAST = CFunctionPointer, + LastAST = uint8_t(FunctionTypeRepresentation::Last), /// The value of the least SIL-only function representation. FirstSIL = 8, @@ -523,8 +523,8 @@ class ASTExtInfoBuilder { // If bits are added or removed, then TypeBase::NumAFTExtInfoBits // and NumMaskBits must be updated, and they must match. // - // |representation|noEscape|concurrent|async|throws|isolation|differentiability| SendingResult | - // | 0 .. 3 | 4 | 5 | 6 | 7 | 8 .. 10 | 11 .. 13 | 14 | + // |representation|noEscape|concurrent|async|throws|isolation|differentiability| SendingResult | InOutResult | coroutine | + // | 0 .. 3 | 4 | 5 | 6 | 7 | 8 .. 10 | 11 .. 13 | 14 | 15 | 16 | // enum : unsigned { RepresentationMask = 0xF << 0, @@ -538,7 +538,8 @@ class ASTExtInfoBuilder { DifferentiabilityMask = 0x7 << DifferentiabilityMaskOffset, SendingResultMask = 1 << 14, InOutResultMask = 1 << 15, - NumMaskBits = 16 + CoroutineMask = 1 << 16, + NumMaskBits = 17 }; static_assert(FunctionTypeIsolation::Mask == 0x7, "update mask manually"); @@ -617,6 +618,8 @@ public: constexpr bool hasSendingResult() const { return bits & SendingResultMask; } + constexpr bool isCoroutine() const { return bits & CoroutineMask; } + constexpr DifferentiabilityKind getDifferentiabilityKind() const { return DifferentiabilityKind((bits & DifferentiabilityMask) >> DifferentiabilityMaskOffset); @@ -735,6 +738,13 @@ public: clangTypeInfo, globalActor, thrownError, lifetimeDependencies); } + [[nodiscard]] + ASTExtInfoBuilder withCoroutine(bool coroutine = true) const { + return ASTExtInfoBuilder( + coroutine ? (bits | CoroutineMask) : (bits & ~CoroutineMask), + clangTypeInfo, globalActor, thrownError, lifetimeDependencies); + } + [[nodiscard]] ASTExtInfoBuilder withDifferentiabilityKind(DifferentiabilityKind differentiability) const { @@ -862,6 +872,8 @@ public: constexpr bool isThrowing() const { return builder.isThrowing(); } + constexpr bool isCoroutine() const { return builder.isCoroutine(); } + constexpr bool hasSendingResult() const { return builder.hasSendingResult(); } constexpr DifferentiabilityKind getDifferentiabilityKind() const { @@ -927,6 +939,14 @@ public: return builder.withThrows(true, Type()).build(); } + /// Helper method for changing only the coroutine field. + /// + /// Prefer using \c ASTExtInfoBuilder::withCoroutine for chaining. + [[nodiscard]] + ASTExtInfo withCoroutine(bool coroutine = true) const { + return builder.withCoroutine(coroutine).build(); + } + /// Helper method for changing only the async field. /// /// Prefer using \c ASTExtInfoBuilder::withAsync for chaining. diff --git a/include/swift/AST/TypeDifferenceVisitor.h b/include/swift/AST/TypeDifferenceVisitor.h index 04aade617a0..b839bfcfb63 100644 --- a/include/swift/AST/TypeDifferenceVisitor.h +++ b/include/swift/AST/TypeDifferenceVisitor.h @@ -187,6 +187,10 @@ public: type1->getElements(), type2->getElements()); } + bool visitYieldResultType(CanYieldResultType type1, CanYieldResultType type2) { + return asImpl().visit(type1.getResultType(), type2.getResultType()); + } + bool visitComponent(CanType type1, CanType type2, const TupleTypeElt &elt1, const TupleTypeElt &elt2) { if (elt1.getName() != elt2.getName()) diff --git a/include/swift/AST/TypeMatcher.h b/include/swift/AST/TypeMatcher.h index 5bf1b37bbb3..9c2f10d7fb0 100644 --- a/include/swift/AST/TypeMatcher.h +++ b/include/swift/AST/TypeMatcher.h @@ -147,6 +147,17 @@ private: return mismatch(firstTuple.getPointer(), secondType, sugaredFirstType); } + bool visitYieldResultType(CanYieldResultType firstType, Type secondType, + Type sugaredFirstType) { + if (auto secondYieldType = secondType->getAs()) + if (!this->visit(firstType.getResultType(), + secondYieldType->getResultType(), + sugaredFirstType->getAs()->getResultType())) + return false; + + return mismatch(firstType.getPointer(), secondType, sugaredFirstType); + } + bool visitSILPackType(CanSILPackType firstPack, Type secondType, Type sugaredFirstType) { if (auto secondPack = secondType->getAs()) { diff --git a/include/swift/AST/TypeNodes.def b/include/swift/AST/TypeNodes.def index b49e9958dd8..e92e90cccbb 100644 --- a/include/swift/AST/TypeNodes.def +++ b/include/swift/AST/TypeNodes.def @@ -207,6 +207,7 @@ TYPE(InOut, Type) TYPE(Pack, Type) TYPE(PackExpansion, Type) TYPE(PackElement, Type) +TYPE(YieldResult, Type) UNCHECKED_TYPE(TypeVariable, Type) UNCHECKED_TYPE(ErrorUnion, Type) TYPE(Integer, Type) diff --git a/include/swift/AST/TypeTransform.h b/include/swift/AST/TypeTransform.h index a1558d15a54..988a43bbee8 100644 --- a/include/swift/AST/TypeTransform.h +++ b/include/swift/AST/TypeTransform.h @@ -1038,6 +1038,16 @@ case TypeKind::Id: t : InOutType::get(objectTy); } + case TypeKind::YieldResult: { + auto yield = cast(base); + auto objectTy = doIt(yield->getResultType(), TypePosition::Invariant); + if (!objectTy || objectTy->hasError()) + return objectTy; + + return objectTy.getPointer() == yield->getResultType().getPointer() ? + t : YieldResultType::get(objectTy, yield->isInOut()); + } + case TypeKind::Existential: { auto *existential = cast(base); auto constraint = doIt(existential->getConstraintType(), pos); diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 1b4a9b2571b..ffa5945ebda 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -409,7 +409,7 @@ class alignas(1 << TypeAlignInBits) TypeBase } protected: - enum { NumAFTExtInfoBits = 16 }; + enum { NumAFTExtInfoBits = 17 }; enum { NumSILExtInfoBits = 14 }; // clang-format off @@ -1712,6 +1712,34 @@ public: } }; DEFINE_EMPTY_CAN_TYPE_WRAPPER(ErrorType, Type) + +class YieldResultType : public TypeBase { + Type ResultType; + bool InOut = false; + + YieldResultType(Type objectTy, bool InOut, const ASTContext *canonicalContext, + RecursiveTypeProperties properties) + : TypeBase(TypeKind::YieldResult, canonicalContext, properties), + ResultType(objectTy), InOut(InOut) {} + +public: + static YieldResultType *get(Type originalType, bool InOut); + + Type getResultType() const { return ResultType; } + bool isInOut() const { return InOut; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const TypeBase *T) { + return T->getKind() == TypeKind::YieldResult; + } +}; + +BEGIN_CAN_TYPE_WRAPPER(YieldResultType, Type) +PROXY_CAN_TYPE_SIMPLE_GETTER(getResultType) +static CanYieldResultType get(CanType type, bool InOut) { + return CanYieldResultType(YieldResultType::get(type, InOut)); +} +END_CAN_TYPE_WRAPPER(YieldResultType, Type) /// BuiltinType - An abstract class for all the builtin types. class BuiltinType : public TypeBase { @@ -3950,6 +3978,8 @@ public: bool isThrowing() const { return getExtInfo().isThrowing(); } + bool isCoroutine() const { return getExtInfo().isCoroutine(); } + bool hasSendingResult() const { return getExtInfo().hasSendingResult(); } bool hasEffect(EffectKind kind) const; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index a8836055571..eae68b4fe2f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -576,6 +576,8 @@ struct ASTContext::Implementation { llvm::DenseMap ReferenceStorageTypes; llvm::DenseMap LValueTypes; llvm::DenseMap InOutTypes; + llvm::DenseMap, + YieldResultType*> YieldResultTypes; llvm::DenseMap, DependentMemberType *> DependentMemberTypes; llvm::FoldingSet ErrorUnionTypes; @@ -3381,6 +3383,7 @@ size_t ASTContext::Implementation::Arena::getTotalMemory() const { llvm::capacity_in_bytes(ReferenceStorageTypes) + llvm::capacity_in_bytes(LValueTypes) + llvm::capacity_in_bytes(InOutTypes) + + llvm::capacity_in_bytes(YieldResultTypes) + llvm::capacity_in_bytes(DependentMemberTypes) + llvm::capacity_in_bytes(EnumTypes) + llvm::capacity_in_bytes(StructTypes) + @@ -3419,6 +3422,7 @@ void ASTContext::Implementation::Arena::dump(llvm::raw_ostream &os) const { SIZE_AND_BYTES(ReferenceStorageTypes); SIZE_AND_BYTES(LValueTypes); SIZE_AND_BYTES(InOutTypes); + SIZE_AND_BYTES(YieldResultTypes); SIZE_AND_BYTES(DependentMemberTypes); SIZE(ErrorUnionTypes); SIZE_AND_BYTES(PlaceholderTypes); @@ -5718,6 +5722,28 @@ InOutType *InOutType::get(Type objectTy) { properties); } +YieldResultType *YieldResultType::get(Type objectTy, bool InOut) { + auto properties = objectTy->getRecursiveProperties(); + if (InOut) { + assert(!objectTy->is() && !objectTy->is() && + "cannot have 'inout' or @lvalue wrapped inside an 'inout yield'"); + properties &= ~RecursiveTypeProperties::IsLValue; + } + + auto arena = getArena(properties); + + auto &C = objectTy->getASTContext(); + auto pair = llvm::PointerIntPair(objectTy.getPointer(), + InOut); + auto &entry = C.getImpl().getArena(arena).YieldResultTypes[pair]; + if (entry) + return entry; + + const ASTContext *canonicalContext = objectTy->isCanonical() ? &C : nullptr; + return entry = new (C, arena) YieldResultType(objectTy, InOut, canonicalContext, + properties); +} + DependentMemberType *DependentMemberType::get(Type base, Identifier name) { auto properties = base->getRecursiveProperties(); properties |= RecursiveTypeProperties::HasDependentMember; diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 104ddd8a3a8..e9f33104f6b 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -5028,6 +5028,7 @@ public: TRIVIAL_ATTR_PRINTER(CompilerInitialized, compiler_initialized) TRIVIAL_ATTR_PRINTER(Consuming, consuming) TRIVIAL_ATTR_PRINTER(Convenience, convenience) + TRIVIAL_ATTR_PRINTER(Coroutine, coroutine) TRIVIAL_ATTR_PRINTER(DiscardableResult, discardable_result) TRIVIAL_ATTR_PRINTER(DisfavoredOverload, disfavored_overload) TRIVIAL_ATTR_PRINTER(DistributedActor, distributed_actor) @@ -6129,6 +6130,13 @@ namespace { printFoot(); } + void visitYieldResultType(YieldResultType *T, Label label) { + printCommon("yield", label); + printFlag(T->isInOut(), "inout"); + printRec(T->getResultType(), Label::always("type")); + printFoot(); + } + void visitPlaceholderType(PlaceholderType *T, Label label) { printCommon("placeholder_type", label); auto originator = T->getOriginator(); @@ -6550,6 +6558,7 @@ namespace { printFlag(T->isAsync(), "async"); printFlag(T->isThrowing(), "throws"); printFlag(T->hasSendingResult(), "sending_result"); + printFlag(T->isCoroutine(), "@yield_once"); if (T->isDifferentiable()) { switch (T->getDifferentiabilityKind()) { default: diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index 2e8fd65c2c0..ff6206d9426 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -1894,6 +1894,11 @@ void ASTMangler::appendType(Type type, GenericSignature sig, return; } + case TypeKind::YieldResult: + appendType(cast(tybase)->getResultType(), sig, forDecl); + appendOperator("Yy"); + return; + case TypeKind::SILMoveOnlyWrapped: // If we hit this, we just mangle the underlying name and move on. llvm_unreachable("should never be mangled?"); @@ -3340,6 +3345,8 @@ void ASTMangler::appendFunctionType(AnyFunctionType *fn, GenericSignature sig, } else if (fn->isNoEscape()) { return appendOperator("XE"); } + if (fn->isCoroutine()) + return appendOperator("Xy"); return appendOperator("c"); case AnyFunctionType::Representation::CFunctionPointer: @@ -3595,7 +3602,10 @@ void ASTMangler::appendParameterTypeListElement( GenericSignature sig, const ValueDecl *forDecl) { if (auto *fnType = elementType->getAs()) appendFunctionType(fnType, sig, flags.isAutoClosure(), forDecl); - else + else if (auto *yieldType = elementType->getAs()) { + appendType(yieldType->getResultType(), sig, forDecl); + appendOperator("Yy"); + } else appendType(elementType, sig, forDecl); if (flags.isNoDerivative()) { diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 31f300f4aad..088e7a4b88b 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -6260,6 +6260,13 @@ public: Printer << "_"; } } + + void visitYieldResultType(YieldResultType *T, NonRecursivePrintOptions nrOption) { + if (T->isInOut()) + Printer << "inout "; + Printer << "@yields "; + visit(T->getResultType()); + } void visitErrorUnionType(ErrorUnionType *T, NonRecursivePrintOptions nrOptions) { @@ -6695,6 +6702,10 @@ public: Printer.printSimpleAttr("@Sendable") << " "; } + if (!Options.excludeAttrKind(TypeAttrKind::YieldOnce) && info.isCoroutine()) { + Printer.printSimpleAttr("@yield_once") << " "; + } + SmallString<64> buf; switch (Options.PrintFunctionRepresentationAttrs) { case PrintOptions::FunctionRepresentationMode::None: diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 7b6774729a8..c5dcfd90131 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -4146,6 +4146,7 @@ mapSignatureExtInfo(AnyFunctionType::ExtInfo info, .withAsync(info.isAsync()) .withThrows(info.isThrowing(), info.getThrownError()) .withClangFunctionType(info.getClangTypeInfo().getType()) + .withCoroutine(info.isCoroutine()) .build(); } diff --git a/lib/AST/ExistentialGeneralization.cpp b/lib/AST/ExistentialGeneralization.cpp index d12e2df63b3..3aee5d748fb 100644 --- a/lib/AST/ExistentialGeneralization.cpp +++ b/lib/AST/ExistentialGeneralization.cpp @@ -85,6 +85,12 @@ private: return type; } + // FIXME: Decide if we can generalize yield results at all + Type visitYieldResultType(CanYieldResultType origType) { + return YieldResultType::get(generalizeStructure(origType.getResultType()), + origType->isInOut()); + } + Type visitParameterizedProtocolType(CanParameterizedProtocolType origType) { // Generalize the argument types of parameterized protocols, // but don't generalize the base type. diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 26de2d02a11..d4d8b4423d8 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -277,6 +277,10 @@ bool CanType::isReferenceTypeImpl(CanType type, const GenericSignatureImpl *sig, #include "swift/AST/ReferenceStorage.def" return false; + case TypeKind::YieldResult: + return isReferenceTypeImpl(cast(type).getResultType(), + sig, functionsCount); + case TypeKind::GenericTypeParam: case TypeKind::DependentMember: assert(sig && "dependent types can't answer reference semantics query"); @@ -1859,6 +1863,13 @@ CanType TypeBase::computeCanonicalType() { break; } + case TypeKind::YieldResult: { + auto *ty = cast(this); + auto wrappedType = ty->getResultType()->getCanonicalType(); + Result = YieldResultType::get(wrappedType, ty->isInOut()); + break; + } + case TypeKind::Tuple: { TupleType *TT = cast(this); assert(TT->getNumElements() != 0 && "Empty tuples are always canonical"); @@ -4587,6 +4598,9 @@ ReferenceCounting TypeBase::getReferenceCounting() { ->getInnerType() ->getReferenceCounting(); + case TypeKind::YieldResult: + return cast(type)->getResultType()->getReferenceCounting(); + case TypeKind::PrimaryArchetype: case TypeKind::ExistentialArchetype: case TypeKind::OpaqueTypeArchetype: diff --git a/lib/AST/TypeWalker.cpp b/lib/AST/TypeWalker.cpp index e236dece275..b45c8bfe274 100644 --- a/lib/AST/TypeWalker.cpp +++ b/lib/AST/TypeWalker.cpp @@ -57,6 +57,10 @@ class Traversal : public TypeVisitor bool visitSILTokenType(SILTokenType *ty) { return false; } + bool visitYieldResultType(YieldResultType *ty) { + return doIt(ty->getResultType()); + } + bool visitPackType(PackType *ty) { for (auto elementTy : ty->getElementTypes()) if (doIt(elementTy)) diff --git a/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift b/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift index 171db1ef6dd..7e4e252a86e 100644 --- a/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift +++ b/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift @@ -210,6 +210,8 @@ extension ASTGenVisitor { return handle(self.generateSimpleDeclAttr(attribute: node, kind: .AtRethrows)) case .Concurrent: return handle(self.generateSimpleDeclAttr(attribute: node, kind: .Concurrent)) + case .Coroutine: + fatalError("unimplemented") case nil where attrName == "_unavailableInEmbedded": return handle(self.generateUnavailableInEmbeddedAttr(attribute: node)?.asDeclAttribute) diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 79d469ff558..8210c4507d0 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -2132,6 +2132,7 @@ private: VISIT(ExistentialType, recurse) NEVER_VISIT(LValueType) VISIT(InOutType, recurse) + NEVER_VISIT(YieldResultType) NEVER_VISIT(PackType) NEVER_VISIT(PackExpansionType) diff --git a/lib/IRGen/Fulfillment.cpp b/lib/IRGen/Fulfillment.cpp index 722ee4fa8b4..c3ae26dd26e 100644 --- a/lib/IRGen/Fulfillment.cpp +++ b/lib/IRGen/Fulfillment.cpp @@ -57,6 +57,7 @@ static bool isLeafTypeMetadata(CanType type) { case TypeKind::PackExpansion: case TypeKind::PackElement: case TypeKind::BuiltinTuple: + case TypeKind::YieldResult: llvm_unreachable("these types do not have metadata"); // All the builtin types are leaves. diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp index 51767c71566..146bc846f5e 100644 --- a/lib/IRGen/GenType.cpp +++ b/lib/IRGen/GenType.cpp @@ -2340,6 +2340,8 @@ const TypeInfo *TypeConverter::convertType(CanType ty) { return convertInOutType(cast(ty)); case TypeKind::Tuple: return convertTupleType(cast(ty)); + case TypeKind::YieldResult: + llvm_unreachable("AST YieldResultType should be lowered by SILGen"); case TypeKind::Function: case TypeKind::GenericFunction: llvm_unreachable("AST FunctionTypes should be lowered by SILGen"); diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 4fe84cf843b..7fb8c4c90f3 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -2354,6 +2354,7 @@ private: case TypeKind::BuiltinNonDefaultDistributedActorStorage: case TypeKind::SILMoveOnlyWrapped: case TypeKind::Integer: + case TypeKind::YieldResult: LLVM_DEBUG(llvm::dbgs() << "Unhandled type: "; DbgTy.getType()->dump(llvm::dbgs()); llvm::dbgs() << "\n"); MangledName = ""; diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index 92c10012361..a26303bc37b 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -2217,6 +2217,10 @@ namespace { DynamicMetadataRequest request) { llvm_unreachable("error type should not appear in IRGen"); } + MetadataResponse visitYieldResultType(CanYieldResultType type, + DynamicMetadataRequest request) { + llvm_unreachable("yields should have been lowered by SILGen"); + } MetadataResponse visitIntegerType(CanIntegerType type, DynamicMetadataRequest request) { diff --git a/lib/SIL/IR/TypeLowering.cpp b/lib/SIL/IR/TypeLowering.cpp index ffeb8a2fb92..2340a2bcff8 100644 --- a/lib/SIL/IR/TypeLowering.cpp +++ b/lib/SIL/IR/TypeLowering.cpp @@ -608,6 +608,11 @@ namespace { IsTypeExpansionSensitive_t) { llvm_unreachable("shouldn't get an inout type here"); } + RetTy visitYieldResultType(CanYieldResultType type, + AbstractionPattern origType, + IsTypeExpansionSensitive_t) { + llvm_unreachable("shouldn't get an yield here"); + } RetTy visitErrorType(CanErrorType type, AbstractionPattern origType, IsTypeExpansionSensitive_t isSensitive) { @@ -4196,6 +4201,7 @@ getAnyFunctionRefInterfaceType(TypeConverter &TC, .withIsolation(funcType->getIsolation()) .withLifetimeDependencies(funcType->getLifetimeDependencies()) .withSendingResult(funcType->hasSendingResult()) + .withCoroutine(funcType->isCoroutine()) .build(); return CanAnyFunctionType::get( diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index b0cd62eefe1..046cf59df57 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -7870,6 +7870,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType, #define TYPE(Name, Parent) #include "swift/AST/TypeNodes.def" case TypeKind::Error: + case TypeKind::YieldResult: case TypeKind::Module: case TypeKind::Enum: case TypeKind::Struct: @@ -7958,6 +7959,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType, case TypeKind::GenericFunction: case TypeKind::LValue: case TypeKind::InOut: + case TypeKind::YieldResult: case TypeKind::Pack: case TypeKind::PackExpansion: case TypeKind::PackElement: diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index f1f9ec638bf..8ffafe1b060 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -7468,6 +7468,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, #include "swift/AST/TypeNodes.def" case TypeKind::Error: + case TypeKind::YieldResult: return getTypeMatchFailure(locator); // BuiltinGenericType subclasses @@ -8503,6 +8504,7 @@ ConstraintSystem::simplifyConstructionConstraint( case TypeKind::Error: case TypeKind::Placeholder: + case TypeKind::YieldResult: return SolutionKind::Error; case TypeKind::GenericFunction: diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index acf377600d7..726c063a3bd 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -484,6 +484,7 @@ public: void visitAddressableForDependenciesAttr(AddressableForDependenciesAttr *attr); void visitUnsafeAttr(UnsafeAttr *attr); void visitUnsafeSelfDependentResultAttr(UnsafeSelfDependentResultAttr *attr); + void visitCoroutineAttr(CoroutineAttr *attr); }; } // end anonymous namespace @@ -2689,6 +2690,10 @@ void AttributeChecker::visitSILGenNameAttr(SILGenNameAttr *A) { } } +void AttributeChecker::visitCoroutineAttr(CoroutineAttr *attr) { + // FIXME: allow only on @differentiable for modify accessorts +} + void AttributeChecker::visitUsedAttr(UsedAttr *attr) { if (D->getDeclContext()->isLocalContext()) diagnose(attr->getLocation(), diag::attr_only_at_non_local_scope, attr); diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index 146590fc244..182f89d4ff9 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -1595,6 +1595,7 @@ namespace { UNINTERESTING_ATTR(CDecl) UNINTERESTING_ATTR(Concurrent) UNINTERESTING_ATTR(Consuming) + UNINTERESTING_ATTR(Coroutine) UNINTERESTING_ATTR(Documentation) UNINTERESTING_ATTR(Dynamic) UNINTERESTING_ATTR(DynamicCallable) diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index c7b48d53dc7..6b461775818 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -5730,6 +5730,10 @@ public: visitBuiltinTypeImpl(ty); } + void visitYieldResultType(const YieldResultType *) { + llvm_unreachable("implemented me"); + } + void visitTypeAliasType(const TypeAliasType *alias) { using namespace decls_block;