From c0ec6c3235a0db15863b2a3a00b3012b93a2224f Mon Sep 17 00:00:00 2001 From: David Zarzycki Date: Wed, 3 Mar 2021 10:20:56 -0500 Subject: [PATCH] [AST] NFC: Make ExtInfo param Optional<> While it is very convenient to default the ExtInfo state when creating new function types, it also make the intent unclear to those looking to extend ExtInfo state. For example, did a given call site intend to have the default ExtInfo state or does it just happen to work? This matters a lot because function types are regularly unpacked and rebuilt and it's really easy to accidentally drop ExtInfo state. By changing the ExtInfo state to an optional, we can track when it is actually needed. --- include/swift/AST/Types.h | 75 ++++++++++++------- lib/AST/ASTContext.cpp | 58 +++++++------- lib/AST/ASTMangler.cpp | 7 +- lib/AST/ASTPrinter.cpp | 32 +++++--- lib/AST/Builtins.cpp | 10 +-- lib/AST/Decl.cpp | 13 +++- lib/AST/Type.cpp | 27 +++++-- lib/ClangImporter/ImportDecl.cpp | 43 ++++++----- lib/ClangImporter/ImportType.cpp | 4 +- lib/IDE/ExprContextAnalysis.cpp | 4 +- lib/IRGen/MetadataRequest.cpp | 15 +++- lib/SIL/IR/TypeLowering.cpp | 28 +++++-- lib/SILGen/SILGenApply.cpp | 28 +++++-- .../Differentiation/LinearMapInfo.cpp | 14 +++- lib/Sema/CSApply.cpp | 33 +++++--- lib/Sema/CSGen.cpp | 6 +- lib/Sema/ConstraintSystem.cpp | 36 ++++++--- lib/Sema/TypeCheckAttr.cpp | 27 ++++--- lib/Sema/TypeCheckCodeCompletion.cpp | 5 +- lib/Sema/TypeCheckDecl.cpp | 40 ++++++---- lib/Sema/TypeCheckDeclOverride.cpp | 5 +- lib/Sema/TypeCheckProtocol.cpp | 30 ++++---- unittests/AST/TypeMatchTests.cpp | 58 ++++++++------ 23 files changed, 392 insertions(+), 206 deletions(-) diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index c6feb550e2e42..b7d8e8dcc6d69 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -37,6 +37,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerEmbeddedInt.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallBitVector.h" @@ -347,10 +348,11 @@ class alignas(1 << TypeAlignInBits) TypeBase { Flags : NumFlagBits ); - SWIFT_INLINE_BITFIELD_FULL(AnyFunctionType, TypeBase, NumAFTExtInfoBits+1+16, + SWIFT_INLINE_BITFIELD_FULL(AnyFunctionType, TypeBase, NumAFTExtInfoBits+1+1+16, /// Extra information which affects how the function is called, like /// regparm and the calling convention. ExtInfoBits : NumAFTExtInfoBits, + HasExtInfo : 1, HasClangTypeInfo : 1, : NumPadBits, NumParams : 16 @@ -2919,20 +2921,28 @@ class AnyFunctionType : public TypeBase { /// /// Subclasses are responsible for storing and retrieving the /// ClangTypeInfo value if one is present. - AnyFunctionType(TypeKind Kind, const ASTContext *CanTypeContext, - Type Output, RecursiveTypeProperties properties, - unsigned NumParams, ExtInfo Info) - : TypeBase(Kind, CanTypeContext, properties), Output(Output) { - Bits.AnyFunctionType.ExtInfoBits = Info.getBits(); - Bits.AnyFunctionType.HasClangTypeInfo = !Info.getClangTypeInfo().empty(); + AnyFunctionType(TypeKind Kind, const ASTContext *CanTypeContext, Type Output, + RecursiveTypeProperties properties, unsigned NumParams, + Optional Info) + : TypeBase(Kind, CanTypeContext, properties), Output(Output) { + if (Info.hasValue()) { + Bits.AnyFunctionType.HasExtInfo = true; + Bits.AnyFunctionType.ExtInfoBits = Info.getValue().getBits(); + Bits.AnyFunctionType.HasClangTypeInfo = + !Info.getValue().getClangTypeInfo().empty(); + // The use of both assert() and static_assert() is intentional. + assert(Bits.AnyFunctionType.ExtInfoBits == Info.getValue().getBits() && + "Bits were dropped!"); + static_assert( + ASTExtInfoBuilder::NumMaskBits == NumAFTExtInfoBits, + "ExtInfo and AnyFunctionTypeBitfields must agree on bit size"); + } else { + Bits.AnyFunctionType.HasExtInfo = false; + Bits.AnyFunctionType.HasClangTypeInfo = false; + Bits.AnyFunctionType.ExtInfoBits = 0; + } Bits.AnyFunctionType.NumParams = NumParams; assert(Bits.AnyFunctionType.NumParams == NumParams && "Params dropped!"); - // The use of both assert() and static_assert() is intentional. - assert(Bits.AnyFunctionType.ExtInfoBits == Info.getBits() && - "Bits were dropped!"); - static_assert( - ASTExtInfoBuilder::NumMaskBits == NumAFTExtInfoBits, - "ExtInfo and AnyFunctionTypeBitfields must agree on bit size"); } public: @@ -2993,7 +3003,10 @@ class AnyFunctionType : public TypeBase { /// outer function type's mangling doesn't need to duplicate that information. bool hasNonDerivableClangType(); + bool hasExtInfo() const { return Bits.AnyFunctionType.HasExtInfo; } + ExtInfo getExtInfo() const { + assert(hasExtInfo()); return ExtInfo(Bits.AnyFunctionType.ExtInfoBits, getClangTypeInfo()); } @@ -3002,6 +3015,7 @@ class AnyFunctionType : public TypeBase { /// The parameter useClangFunctionType is present only for staging purposes. /// In the future, we will always use the canonical clang function type. ExtInfo getCanonicalExtInfo(bool useClangFunctionType) const { + assert(hasExtInfo()); return ExtInfo(Bits.AnyFunctionType.ExtInfoBits, useClangFunctionType ? getCanonicalClangTypeInfo() : ClangTypeInfo()); @@ -3193,7 +3207,7 @@ BEGIN_CAN_TYPE_WRAPPER(AnyFunctionType, Type) static CanAnyFunctionType get(CanGenericSignature signature, CanParamArrayRef params, CanType result, - ExtInfo info = ExtInfo()); + Optional info = None); CanGenericSignature getOptGenericSignature() const; @@ -3234,7 +3248,7 @@ class FunctionType final public: /// 'Constructor' Factory Function static FunctionType *get(ArrayRef params, Type result, - ExtInfo info = ExtInfo()); + Optional info = None); // Retrieve the input parameters of this function type. ArrayRef getParams() const { @@ -3251,12 +3265,15 @@ class FunctionType final } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getParams(), getResult(), getExtInfo()); + Optional info = None; + if (hasExtInfo()) + info = getExtInfo(); + Profile(ID, getParams(), getResult(), info); } static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef params, Type result, - ExtInfo info); + Optional info); // Implement isa/cast/dyncast/etc. static bool classof(const TypeBase *T) { @@ -3264,12 +3281,12 @@ class FunctionType final } private: - FunctionType(ArrayRef params, Type result, ExtInfo info, + FunctionType(ArrayRef params, Type result, Optional info, const ASTContext *ctx, RecursiveTypeProperties properties); }; BEGIN_CAN_TYPE_WRAPPER(FunctionType, AnyFunctionType) static CanFunctionType get(CanParamArrayRef params, CanType result, - ExtInfo info = ExtInfo()) { + Optional info = None) { auto fnType = FunctionType::get(params.getOriginalArray(), result, info); return cast(fnType->getCanonicalType()); } @@ -3334,7 +3351,7 @@ class GenericFunctionType final : public AnyFunctionType, GenericFunctionType(GenericSignature sig, ArrayRef params, Type result, - ExtInfo info, + Optional info, const ASTContext *ctx, RecursiveTypeProperties properties); @@ -3343,7 +3360,7 @@ class GenericFunctionType final : public AnyFunctionType, static GenericFunctionType *get(GenericSignature sig, ArrayRef params, Type result, - ExtInfo info = ExtInfo()); + Optional info = None); // Retrieve the input parameters of this function type. ArrayRef getParams() const { @@ -3367,14 +3384,16 @@ class GenericFunctionType final : public AnyFunctionType, FunctionType *substGenericArgs(llvm::function_ref substFn) const; void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getGenericSignature(), getParams(), getResult(), - getExtInfo()); + Optional info = None; + if (hasExtInfo()) + info = getExtInfo(); + Profile(ID, getGenericSignature(), getParams(), getResult(), info); } static void Profile(llvm::FoldingSetNodeID &ID, GenericSignature sig, ArrayRef params, Type result, - ExtInfo info); + Optional info); // Implement isa/cast/dyncast/etc. static bool classof(const TypeBase *T) { @@ -3387,11 +3406,11 @@ BEGIN_CAN_TYPE_WRAPPER(GenericFunctionType, AnyFunctionType) static CanGenericFunctionType get(CanGenericSignature sig, CanParamArrayRef params, CanType result, - ExtInfo info = ExtInfo()) { + Optional info = None) { // Knowing that the argument types are independently canonical is // not sufficient to guarantee that the function type will be canonical. - auto fnType = GenericFunctionType::get(sig, params.getOriginalArray(), - result, info); + auto fnType = + GenericFunctionType::get(sig, params.getOriginalArray(), result, info); return cast(fnType->getCanonicalType()); } @@ -3413,7 +3432,7 @@ END_CAN_TYPE_WRAPPER(GenericFunctionType, AnyFunctionType) inline CanAnyFunctionType CanAnyFunctionType::get(CanGenericSignature signature, CanParamArrayRef params, - CanType result, ExtInfo extInfo) { + CanType result, Optional extInfo) { if (signature) { return CanGenericFunctionType::get(signature, params, result, extInfo); } else { diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index c67a149a5ab81..da09ed9d436e5 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -3245,18 +3245,19 @@ static void profileParams(llvm::FoldingSetNodeID &ID, } void FunctionType::Profile(llvm::FoldingSetNodeID &ID, - ArrayRef params, - Type result, - ExtInfo info) { + ArrayRef params, Type result, + Optional info) { profileParams(ID, params); ID.AddPointer(result.getPointer()); - auto infoKey = info.getFuncAttrKey(); - ID.AddInteger(infoKey.first); - ID.AddPointer(infoKey.second); + if (info.hasValue()) { + auto infoKey = info.getValue().getFuncAttrKey(); + ID.AddInteger(infoKey.first); + ID.AddPointer(infoKey.second); + } } FunctionType *FunctionType::get(ArrayRef params, - Type result, ExtInfo info) { + Type result, Optional info) { auto properties = getFunctionRecursiveProperties(params, result); auto arena = getArena(properties); @@ -3272,10 +3273,15 @@ FunctionType *FunctionType::get(ArrayRef params, return funcTy; } - auto clangTypeInfo = info.getClangTypeInfo(); + ClangTypeInfo clangTypeInfo; + if (info.hasValue()) + clangTypeInfo = info.getValue().getClangTypeInfo(); + + bool hasClangInfo = + info.hasValue() && !info.getValue().getClangTypeInfo().empty(); size_t allocSize = totalSizeToAlloc( - params.size(), clangTypeInfo.empty() ? 0 : 1); + params.size(), hasClangInfo ? 1 : 0); void *mem = ctx.Allocate(allocSize, alignof(FunctionType), arena); bool isCanonical = isFunctionTypeCanonical(params, result); @@ -3294,36 +3300,38 @@ FunctionType *FunctionType::get(ArrayRef params, } // If the input and result types are canonical, then so is the result. -FunctionType::FunctionType(ArrayRef params, - Type output, ExtInfo info, - const ASTContext *ctx, +FunctionType::FunctionType(ArrayRef params, Type output, + Optional info, const ASTContext *ctx, RecursiveTypeProperties properties) - : AnyFunctionType(TypeKind::Function, ctx, - output, properties, params.size(), info) { + : AnyFunctionType(TypeKind::Function, ctx, output, properties, + params.size(), info) { std::uninitialized_copy(params.begin(), params.end(), getTrailingObjects()); - auto clangTypeInfo = info.getClangTypeInfo(); - if (!clangTypeInfo.empty()) - *getTrailingObjects() = clangTypeInfo; + if (info.hasValue()) { + auto clangTypeInfo = info.getValue().getClangTypeInfo(); + if (!clangTypeInfo.empty()) + *getTrailingObjects() = clangTypeInfo; + } } void GenericFunctionType::Profile(llvm::FoldingSetNodeID &ID, GenericSignature sig, ArrayRef params, - Type result, - ExtInfo info) { + Type result, Optional info) { ID.AddPointer(sig.getPointer()); profileParams(ID, params); ID.AddPointer(result.getPointer()); - auto infoKey = info.getFuncAttrKey(); - ID.AddInteger(infoKey.first); - ID.AddPointer(infoKey.second); + if (info.hasValue()) { + auto infoKey = info.getValue().getFuncAttrKey(); + ID.AddInteger(infoKey.first); + ID.AddPointer(infoKey.second); + } } GenericFunctionType *GenericFunctionType::get(GenericSignature sig, ArrayRef params, Type result, - ExtInfo info) { + Optional info) { assert(sig && "no generic signature for generic function type?!"); assert(!result->hasTypeVariable()); assert(!result->hasPlaceholder()); @@ -3346,7 +3354,7 @@ GenericFunctionType *GenericFunctionType::get(GenericSignature sig, // point. bool isCanonical = isGenericFunctionTypeCanonical(sig, params, result); - assert(info.getClangTypeInfo().empty() && + assert((!info.hasValue() || info.getValue().getClangTypeInfo().empty()) && "Generic functions do not have Clang types at the moment."); if (auto funcTy @@ -3370,7 +3378,7 @@ GenericFunctionType::GenericFunctionType( GenericSignature sig, ArrayRef params, Type result, - ExtInfo info, + Optional info, const ASTContext *ctx, RecursiveTypeProperties properties) : AnyFunctionType(TypeKind::GenericFunction, ctx, result, diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index 12e9658b7842d..306c5f13d0243 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -2846,9 +2846,12 @@ CanType ASTMangler::getDeclTypeForMangling( auto &C = decl->getASTContext(); if (decl->isInvalid()) { - if (isa(decl)) + if (isa(decl)) { + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanFunctionType::ExtInfo info; return CanFunctionType::get({AnyFunctionType::Param(C.TheErrorType)}, - C.TheErrorType); + C.TheErrorType, info); + } return C.TheErrorType; } diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 62f88fc50afa5..4a9e254d23830 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -4474,6 +4474,10 @@ class TypePrinter : public TypeVisitor { } void printFunctionExtInfo(AnyFunctionType *fnType) { + if (!fnType->hasExtInfo()) { + Printer << "@_NO_EXTINFO "; + return; + } auto &ctx = fnType->getASTContext(); auto info = fnType->getExtInfo(); if (Options.SkipAttributes) @@ -4693,13 +4697,15 @@ class TypePrinter : public TypeVisitor { // If we're stripping argument labels from types, do it when printing. visitAnyFunctionTypeParams(T->getParams(), /*printLabels*/false); - if (T->isAsync()) { - Printer << " "; - Printer.printKeyword("async", Options); - } + if (T->hasExtInfo()) { + if (T->isAsync()) { + Printer << " "; + Printer.printKeyword("async", Options); + } - if (T->isThrowing()) - Printer << " " << tok::kw_throws; + if (T->isThrowing()) + Printer << " " << tok::kw_throws; + } Printer << " -> "; @@ -4738,13 +4744,15 @@ class TypePrinter : public TypeVisitor { visitAnyFunctionTypeParams(T->getParams(), /*printLabels*/true); - if (T->isAsync()) { - Printer << " "; - Printer.printKeyword("async", Options); - } + if (T->hasExtInfo()) { + if (T->isAsync()) { + Printer << " "; + Printer.printKeyword("async", Options); + } - if (T->isThrowing()) - Printer << " " << tok::kw_throws; + if (T->isThrowing()) + Printer << " " << tok::kw_throws; + } Printer << " -> "; Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType); diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index 6861075f30c54..9c8d6e4c8175a 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -1207,9 +1207,7 @@ static ValueDecl *getAutoDiffApplyDerivativeFunction( SmallVector params; for (auto ¶mGen : fnParamGens) params.push_back(FunctionType::Param(paramGen.build(builder))); - auto innerFunction = - FunctionType::get(params, fnResultGen.build(builder)); - return innerFunction->withExtInfo(extInfo); + return FunctionType::get(params, fnResultGen.build(builder), extInfo); }}; // Eagerly build the type of the first arg, then use that to compute the type // of the result. @@ -1274,8 +1272,10 @@ static ValueDecl *getAutoDiffApplyTransposeFunction( SmallVector params; for (auto ¶mGen : linearFnParamGens) params.push_back(FunctionType::Param(paramGen.build(builder))); - auto innerFunction = FunctionType::get(params, - linearFnResultGen.build(builder)); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + auto innerFunction = + FunctionType::get(params, linearFnResultGen.build(builder), info); return innerFunction->withExtInfo(extInfo); } }; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index f6cfb2141362f..491fdaff39930 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -7799,11 +7799,16 @@ Type ConstructorDecl::getInitializerInterfaceType() { // Constructors have an initializer type that takes an instance // instead of a metatype. auto initSelfParam = computeSelfParam(this, /*isInitializingCtor=*/true); + + // FIXME: Verify ExtInfo state is correct, not working by accident. Type initFuncTy; - if (auto sig = getGenericSignature()) - initFuncTy = GenericFunctionType::get(sig, {initSelfParam}, funcTy); - else - initFuncTy = FunctionType::get({initSelfParam}, funcTy); + if (auto sig = getGenericSignature()) { + GenericFunctionType::ExtInfo info; + initFuncTy = GenericFunctionType::get(sig, {initSelfParam}, funcTy, info); + } else { + FunctionType::ExtInfo info; + initFuncTy = FunctionType::get({initSelfParam}, funcTy, info); + } InitializerInterfaceType = initFuncTy; return InitializerInterfaceType; diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 71ebc471f5ff2..4c5911276b006 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -442,9 +442,13 @@ Type TypeBase::addCurriedSelfType(const DeclContext *dc) { auto selfTy = dc->getSelfInterfaceType(); auto selfParam = AnyFunctionType::Param(selfTy); - if (sig) - return GenericFunctionType::get(sig, {selfParam}, type); - return FunctionType::get({selfParam}, type); + // FIXME: Verify ExtInfo state is correct, not working by accident. + if (sig) { + GenericFunctionType::ExtInfo info; + return GenericFunctionType::get(sig, {selfParam}, type, info); + } + FunctionType::ExtInfo info; + return FunctionType::get({selfParam}, type, info); } void TypeBase::getTypeVariables( @@ -1264,7 +1268,9 @@ CanType TypeBase::computeCanonicalType() { getCanonicalParams(funcTy, genericSig, canParams); auto resultTy = funcTy->getResult()->getCanonicalType(genericSig); - auto extInfo = funcTy->getCanonicalExtInfo(useClangTypes(resultTy)); + Optional extInfo = None; + if (funcTy->hasExtInfo()) + extInfo = funcTy->getCanonicalExtInfo(useClangTypes(resultTy)); if (genericSig) { Result = GenericFunctionType::get(genericSig, canParams, resultTy, extInfo); @@ -4755,12 +4761,16 @@ case TypeKind::Id: if (isUnchanged) return *this; auto genericSig = genericFnType->getGenericSignature(); + if (!function->hasExtInfo()) + return GenericFunctionType::get(genericSig, substParams, resultTy); return GenericFunctionType::get(genericSig, substParams, resultTy, function->getExtInfo()); } if (isUnchanged) return *this; + if (!function->hasExtInfo()) + return FunctionType::get(substParams, resultTy); return FunctionType::get(substParams, resultTy, function->getExtInfo()); } @@ -5350,7 +5360,10 @@ AnyFunctionType::getAutoDiffDerivativeFunctionLinearMapType( } auto differentialResult = hasInoutDiffParameter ? Type(ctx.TheEmptyTupleType) : resultTanType; - linearMapType = FunctionType::get(differentialParams, differentialResult); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + linearMapType = + FunctionType::get(differentialParams, differentialResult, info); break; } case AutoDiffLinearMapKind::Pullback: { @@ -5399,7 +5412,9 @@ AnyFunctionType::getAutoDiffDerivativeFunctionLinearMapType( auto flags = ParameterTypeFlags().withInOut(hasInoutDiffParameter); auto pullbackParam = AnyFunctionType::Param(resultTanType, Identifier(), flags); - linearMapType = FunctionType::get({pullbackParam}, pullbackResult); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + linearMapType = FunctionType::get({pullbackParam}, pullbackResult, info); break; } } diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index b521ed49b0e5f..79b71d532feda 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -485,8 +485,10 @@ synthesizeEnumRawValueConstructorBody(AbstractFunctionDecl *afd, ConcreteDeclRef concreteDeclRef(reinterpretCast, subMap); auto reinterpretCastRef = new (ctx) DeclRefExpr(concreteDeclRef, DeclNameLoc(), /*implicit*/ true); - reinterpretCastRef->setType(FunctionType::get({FunctionType::Param(rawTy)}, - enumTy)); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + reinterpretCastRef->setType( + FunctionType::get({FunctionType::Param(rawTy)}, enumTy, info)); auto reinterpreted = CallExpr::createImplicit(ctx, reinterpretCastRef, { paramRef }, { Identifier() }); @@ -564,8 +566,10 @@ synthesizeEnumRawValueGetterBody(AbstractFunctionDecl *afd, void *context) { auto reinterpretCastRef = new (ctx) DeclRefExpr(concreteDeclRef, DeclNameLoc(), /*implicit*/ true); - reinterpretCastRef->setType(FunctionType::get({FunctionType::Param(enumTy)}, - rawTy)); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + reinterpretCastRef->setType( + FunctionType::get({FunctionType::Param(enumTy)}, rawTy, info)); auto reinterpreted = CallExpr::createImplicit(ctx, reinterpretCastRef, { selfRef }, { Identifier() }); @@ -924,10 +928,11 @@ synthesizeUnionFieldGetterBody(AbstractFunctionDecl *afd, void *context) { auto reinterpretCastRefExpr = new (ctx) DeclRefExpr(reinterpretCastRef, DeclNameLoc(), /*implicit*/ true); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; reinterpretCastRefExpr->setType( - FunctionType::get( - AnyFunctionType::Param(selfDecl->getInterfaceType()), - importedFieldDecl->getInterfaceType())); + FunctionType::get(AnyFunctionType::Param(selfDecl->getInterfaceType()), + importedFieldDecl->getInterfaceType(), info)); auto reinterpreted = CallExpr::createImplicit(ctx, reinterpretCastRefExpr, { selfRef }, @@ -970,12 +975,12 @@ synthesizeUnionFieldSetterBody(AbstractFunctionDecl *afd, void *context) { ArrayRef())); auto addressofFnRefExpr = new (ctx) DeclRefExpr(addressofFnRef, DeclNameLoc(), /*implicit*/ true); - addressofFnRefExpr->setType( - FunctionType::get( - AnyFunctionType::Param(inoutSelfDecl->getInterfaceType(), - Identifier(), + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo addressOfInfo; + addressofFnRefExpr->setType(FunctionType::get( + AnyFunctionType::Param(inoutSelfDecl->getInterfaceType(), Identifier(), ParameterTypeFlags().withInOut(true)), - ctx.TheRawPointerType)); + ctx.TheRawPointerType, addressOfInfo)); auto selfPointer = CallExpr::createImplicit(ctx, addressofFnRefExpr, { inoutSelf }, { Identifier() }); @@ -990,10 +995,12 @@ synthesizeUnionFieldSetterBody(AbstractFunctionDecl *afd, void *context) { ArrayRef())); auto initializeFnRefExpr = new (ctx) DeclRefExpr(initializeFnRef, DeclNameLoc(), /*implicit*/ true); - initializeFnRefExpr->setType( - FunctionType::get({AnyFunctionType::Param(newValueDecl->getInterfaceType()), - AnyFunctionType::Param(ctx.TheRawPointerType)}, - TupleType::getEmpty(ctx))); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo initializeInfo; + initializeFnRefExpr->setType(FunctionType::get( + {AnyFunctionType::Param(newValueDecl->getInterfaceType()), + AnyFunctionType::Param(ctx.TheRawPointerType)}, + TupleType::getEmpty(ctx), initializeInfo)); auto initialize = CallExpr::createImplicit(ctx, initializeFnRefExpr, { newValueRef, selfPointer }, { Identifier(), Identifier() }); @@ -1261,7 +1268,9 @@ synthesizeStructDefaultConstructorBody(AbstractFunctionDecl *afd, ConcreteDeclRef concreteDeclRef(zeroInitializerFunc, subMap); auto zeroInitializerRef = new (ctx) DeclRefExpr(concreteDeclRef, DeclNameLoc(), /*implicit*/ true); - zeroInitializerRef->setType(FunctionType::get({}, selfType)); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + zeroInitializerRef->setType(FunctionType::get({}, selfType, info)); auto call = CallExpr::createImplicit(ctx, zeroInitializerRef, {}, {}); call->setType(selfType); diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 0a894ce5f807d..d23383110fa8d 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -660,7 +660,9 @@ namespace { if (!resultTy) return Type(); - return FunctionType::get({}, resultTy); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + return FunctionType::get({}, resultTy, info); } ImportResult VisitParenType(const clang::ParenType *type) { diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index 8b872e03b95c5..5577b2f740b53 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -569,8 +569,10 @@ static void collectPossibleCalleesByQualifiedLookup( Type kpValueTy = kpTy->castTo()->getGenericArgs()[1]; kpTy = BoundGenericType::get(kpDecl, Type(), {baseTy, kpValueTy}); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; Type fnTy = FunctionType::get( - {AnyFunctionType::Param(kpTy, Ctx.Id_keyPath)}, kpValueTy); + {AnyFunctionType::Param(kpTy, Ctx.Id_keyPath)}, kpValueTy, info); candidates.emplace_back(fnTy->castTo(), nullptr); } } diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index 8a73f24c7cdc4..d9b38f488c17f 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -2950,10 +2950,14 @@ class EmitTypeMetadataRefForLayout // A thin function looks like a plain pointer. // FIXME: Except for extra inhabitants? return C.TheRawPointerType; - case SILFunctionType::Representation::Thick: + case SILFunctionType::Representation::Thick: { // All function types look like () -> (). // FIXME: It'd be nice not to have to call through the runtime here. - return CanFunctionType::get({}, C.TheEmptyTupleType); + // + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanFunctionType::ExtInfo info; + return CanFunctionType::get({}, C.TheEmptyTupleType, info); + } case SILFunctionType::Representation::Block: // All block types look like AnyObject. return C.getAnyObjectType(); @@ -3149,10 +3153,13 @@ namespace { // A thin function looks like a plain pointer. // FIXME: Except for extra inhabitants? return emitFromValueWitnessTable(C.TheRawPointerType); - case SILFunctionType::Representation::Thick: + case SILFunctionType::Representation::Thick: { // All function types look like () -> (). + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanFunctionType::ExtInfo info; return emitFromValueWitnessTable( - CanFunctionType::get({}, C.TheEmptyTupleType)); + CanFunctionType::get({}, C.TheEmptyTupleType, info)); + } case SILFunctionType::Representation::Block: // All block types look like AnyObject. return emitFromValueWitnessTable(C.getAnyObjectType()); diff --git a/lib/SIL/IR/TypeLowering.cpp b/lib/SIL/IR/TypeLowering.cpp index 916aa7a22eab8..5914bb96170ab 100644 --- a/lib/SIL/IR/TypeLowering.cpp +++ b/lib/SIL/IR/TypeLowering.cpp @@ -2364,7 +2364,9 @@ getCanonicalSignatureOrNull(GenericSignature sig) { /// Get the type of a global variable accessor function, () -> RawPointer. static CanAnyFunctionType getGlobalAccessorType(CanType varType) { ASTContext &C = varType->getASTContext(); - return CanFunctionType::get({}, C.TheRawPointerType); + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanFunctionType::ExtInfo info; + return CanFunctionType::get({}, C.TheRawPointerType, info); } /// Removes @noescape from the given type if it's a function type. Otherwise, @@ -2406,8 +2408,10 @@ static CanAnyFunctionType getDefaultArgGeneratorInterfaceType( } } - return CanAnyFunctionType::get(getCanonicalSignatureOrNull(sig), - {}, canResultTy); + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanAnyFunctionType::ExtInfo info; + return CanAnyFunctionType::get(getCanonicalSignatureOrNull(sig), {}, + canResultTy, info); } /// Get the type of a stored property initializer, () -> T. @@ -2432,8 +2436,10 @@ static CanAnyFunctionType getStoredPropertyInitializerInterfaceType( auto sig = DC->getGenericSignatureOfContext(); - return CanAnyFunctionType::get(getCanonicalSignatureOrNull(sig), - {}, resultTy); + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanAnyFunctionType::ExtInfo info; + return CanAnyFunctionType::get(getCanonicalSignatureOrNull(sig), {}, resultTy, + info); } /// Get the type of a property wrapper backing initializer, @@ -2453,8 +2459,10 @@ static CanAnyFunctionType getPropertyWrapperBackingInitializerInterfaceType( AnyFunctionType::Param param( inputType, Identifier(), ParameterTypeFlags().withValueOwnership(ValueOwnership::Owned)); + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanAnyFunctionType::ExtInfo info; return CanAnyFunctionType::get(getCanonicalSignatureOrNull(sig), {param}, - resultType); + resultType, info); } static CanAnyFunctionType getPropertyWrapperInitFromProjectedValueInterfaceType(TypeConverter &TC, @@ -2474,8 +2482,10 @@ static CanAnyFunctionType getPropertyWrapperInitFromProjectedValueInterfaceType( AnyFunctionType::Param param( inputType, Identifier(), ParameterTypeFlags().withValueOwnership(ValueOwnership::Owned)); + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanAnyFunctionType::ExtInfo info; return CanAnyFunctionType::get(getCanonicalSignatureOrNull(sig), {param}, - resultType); + resultType, info); } /// Get the type of a destructor function. @@ -2502,7 +2512,9 @@ static CanAnyFunctionType getDestructorInterfaceType(DestructorDecl *dd, CanType resultTy = (isDeallocating ? TupleType::getEmpty(C) : C.TheNativeObjectType); - CanType methodTy = CanFunctionType::get({}, resultTy); + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanFunctionType::ExtInfo info; + CanType methodTy = CanFunctionType::get({}, resultTy, info); auto sig = dd->getGenericSignatureOfContext(); FunctionType::Param args[] = {FunctionType::Param(classType)}; diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index c619ddf5f2946..f100615e8f3ac 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -1602,9 +1602,10 @@ class SILGenApply : public Lowering::ExprVisitor { ->getCanonicalType() .getOptionalObjectType()); auto substSelfType = dynamicMemberRef->getBase()->getType()->getCanonicalType(); + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanFunctionType::ExtInfo info; substFormalType = CanFunctionType::get( - {AnyFunctionType::Param(substSelfType)}, - substFormalType); + {AnyFunctionType::Param(substSelfType)}, substFormalType, info); setCallee(Callee::forDynamic(SGF, member, memberRef.getSubstitutions(), @@ -5861,7 +5862,9 @@ RValue SILGenFunction::emitDynamicMemberRefExpr(DynamicMemberRefExpr *e, FuncDecl *memberFunc; if (auto *VD = dyn_cast(e->getMember().getDecl())) { memberFunc = VD->getOpaqueAccessor(AccessorKind::Get); - memberMethodTy = FunctionType::get({}, memberMethodTy); + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanFunctionType::ExtInfo info; + memberMethodTy = FunctionType::get({}, memberMethodTy, info); } else memberFunc = cast(e->getMember().getDecl()); auto member = SILDeclRef(memberFunc, SILDeclRef::Kind::Func) @@ -5880,7 +5883,9 @@ RValue SILGenFunction::emitDynamicMemberRefExpr(DynamicMemberRefExpr *e, // For a computed variable, we want the getter. if (isa(e->getMember().getDecl())) { - methodTy = CanFunctionType::get({}, valueTy); + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanFunctionType::ExtInfo info; + methodTy = CanFunctionType::get({}, valueTy, info); } else { methodTy = cast(valueTy); } @@ -5891,9 +5896,11 @@ RValue SILGenFunction::emitDynamicMemberRefExpr(DynamicMemberRefExpr *e, auto foreignMethodTy = getPartialApplyOfDynamicMethodFormalType(SGM, member, e->getMember()); + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanFunctionType::ExtInfo info; FunctionType::Param arg(operand->getType().getASTType()); - auto memberFnTy = CanFunctionType::get({arg}, - memberMethodTy->getCanonicalType()); + auto memberFnTy = + CanFunctionType::get({arg}, memberMethodTy->getCanonicalType(), info); auto loweredMethodTy = getDynamicMethodLoweredType(SGM.M, member, memberFnTy); @@ -5984,13 +5991,18 @@ RValue SILGenFunction::emitDynamicSubscriptExpr(DynamicSubscriptExpr *e, auto valueTy = e->getType()->getCanonicalType().getOptionalObjectType(); // Objective-C subscripts only ever have a single parameter. + // + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanFunctionType::ExtInfo methodInfo; FunctionType::Param indexArg(e->getIndex()->getType()->getCanonicalType()); - auto methodTy = CanFunctionType::get({indexArg}, valueTy); + auto methodTy = CanFunctionType::get({indexArg}, valueTy, methodInfo); auto foreignMethodTy = getPartialApplyOfDynamicMethodFormalType(SGM, member, e->getMember()); + // FIXME: Verify ExtInfo state is correct, not working by accident. + CanFunctionType::ExtInfo functionInfo; FunctionType::Param baseArg(base->getType().getASTType()); - auto functionTy = CanFunctionType::get({baseArg}, methodTy); + auto functionTy = CanFunctionType::get({baseArg}, methodTy, functionInfo); auto loweredMethodTy = getDynamicMethodLoweredType(SGM.M, member, functionTy); SILValue memberArg = diff --git a/lib/SILOptimizer/Differentiation/LinearMapInfo.cpp b/lib/SILOptimizer/Differentiation/LinearMapInfo.cpp index 38bdd1cb47ba8..e9d53787f4fd3 100644 --- a/lib/SILOptimizer/Differentiation/LinearMapInfo.cpp +++ b/lib/SILOptimizer/Differentiation/LinearMapInfo.cpp @@ -230,13 +230,19 @@ VarDecl *LinearMapInfo::addLinearMapDecl(ApplyInst *ai, SILType linearMapType) { params.push_back( AnyFunctionType::Param(param.getInterfaceType(), Identifier(), flags)); } + AnyFunctionType *astFnTy; - if (auto genSig = silFnTy->getSubstGenericSignature()) + if (auto genSig = silFnTy->getSubstGenericSignature()) { + // FIXME: Verify ExtInfo state is correct, not working by accident. + GenericFunctionType::ExtInfo info; astFnTy = GenericFunctionType::get( - genSig, params, silFnTy->getAllResultsInterfaceType().getASTType()); - else + genSig, params, silFnTy->getAllResultsInterfaceType().getASTType(), + info); + } else { + FunctionType::ExtInfo info; astFnTy = FunctionType::get( - params, silFnTy->getAllResultsInterfaceType().getASTType()); + params, silFnTy->getAllResultsInterfaceType().getASTType(), info); + } auto *origBB = ai->getParent(); auto *linMapStruct = getLinearMapStruct(origBB); diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 8bd7b95cd7dab..4631c1b9b944e 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -1070,7 +1070,10 @@ namespace { args.push_back(paramRef); } - fnRef->setType(FunctionType::get(innerParamTypes, fnType->getResult())); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo fnInfo; + fnRef->setType( + FunctionType::get(innerParamTypes, fnType->getResult(), fnInfo)); cs.cacheType(fnRef); auto *fnCall = CallExpr::createImplicit(context, fnRef, args, argLabels); @@ -1079,7 +1082,11 @@ namespace { cs.cacheType(fnCall->getArg()); auto discriminator = AutoClosureExpr::InvalidDiscriminator; - auto *autoClosureType = FunctionType::get(outerParamTypes, fnType->getResult()); + + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo closureInfo; + auto *autoClosureType = + FunctionType::get(outerParamTypes, fnType->getResult(), closureInfo); auto *autoClosure = new (context) AutoClosureExpr(fnCall, autoClosureType, discriminator, cs.DC); autoClosure->setParameterList(outerParams); @@ -1179,7 +1186,10 @@ namespace { auto *closure = buildPropertyWrapperFnThunk(selfCall, calleeFnType, fnDecl, callee, appliedWrappers); - ref->setType(FunctionType::get(refTy->getParams(), selfCall->getType())); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + ref->setType( + FunctionType::get(refTy->getParams(), selfCall->getType(), info)); cs.cacheType(ref); // FIXME: There's more work to do. @@ -4916,8 +4926,11 @@ namespace { // The inner closure. // // let closure = "{ $0[keyPath: $kp$] }" + // + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo closureInfo; auto closureTy = - FunctionType::get({ FunctionType::Param(baseTy) }, leafTy); + FunctionType::get({FunctionType::Param(baseTy)}, leafTy, closureInfo); auto closure = new (ctx) AutoClosureExpr(/*set body later*/nullptr, leafTy, discriminator, cs.DC); @@ -4932,8 +4945,11 @@ namespace { // The outer closure. // // let outerClosure = "{ $kp$ in \(closure) }" - auto outerClosureTy = - FunctionType::get({ FunctionType::Param(keyPathTy) }, closureTy); + // + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo outerClosureInfo; + auto outerClosureTy = FunctionType::get({FunctionType::Param(keyPathTy)}, + closureTy, outerClosureInfo); auto outerClosure = new (ctx) AutoClosureExpr(/*set body later*/nullptr, closureTy, discriminator, cs.DC); @@ -6761,9 +6777,8 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType, fromEI.intoBuilder() .withDifferentiabilityKind(toEI.getDifferentiabilityKind()) .build(); - fromFunc = FunctionType::get(toFunc->getParams(), fromFunc->getResult()) - ->withExtInfo(newEI) - ->castTo(); + fromFunc = FunctionType::get(toFunc->getParams(), fromFunc->getResult(), + newEI); switch (toEI.getDifferentiabilityKind()) { // TODO: Ban `Normal` and `Forward` cases. case DifferentiabilityKind::Normal: diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 158f0033094f4..a851058db60f6 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -2433,7 +2433,11 @@ namespace { Type outputType = CS.createTypeVariable( CS.getConstraintLocator(locator), TVO_CanBindToNoEscape); - Type functionType = FunctionType::get(params, outputType); + // Equal constraints require ExtInfo comparison. + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + Type functionType = FunctionType::get(params, outputType, info); + // TODO: Convert to FunctionInput/FunctionResult constraints. CS.addConstraint( ConstraintKind::Equal, functionType, memberType, locator.withPathElement(LocatorPathElt::PatternMatch(pattern))); diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index ce11781c4f0e9..7617bc6a85aac 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1597,7 +1597,9 @@ ConstraintSystem::getTypeOfMemberReference( auto indices = subscript->getInterfaceType() ->castTo()->getParams(); - refType = FunctionType::get(indices, elementTy); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + refType = FunctionType::get(indices, elementTy, info); } else { refType = getUnopenedTypeOfReference(cast(value), baseTy, useDC, base, @@ -1618,10 +1620,13 @@ ConstraintSystem::getTypeOfMemberReference( // If the storage is generic, add a generic signature. FunctionType::Param selfParam(selfTy, Identifier(), selfFlags); + // FIXME: Verify ExtInfo state is correct, not working by accident. if (auto sig = innerDC->getGenericSignatureOfContext()) { - funcType = GenericFunctionType::get(sig, {selfParam}, refType); + GenericFunctionType::ExtInfo info; + funcType = GenericFunctionType::get(sig, {selfParam}, refType, info); } else { - funcType = FunctionType::get({selfParam}, refType); + FunctionType::ExtInfo info; + funcType = FunctionType::get({selfParam}, refType, info); } } @@ -1697,7 +1702,10 @@ ConstraintSystem::getTypeOfMemberReference( auto *functionType = fullFunctionType->getResult()->getAs(); functionType = unwrapPropertyWrapperParameterTypes(*this, funcDecl, functionRefKind, functionType, locator); - openedType = FunctionType::get(fullFunctionType->getParams(), functionType); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + openedType = + FunctionType::get(fullFunctionType->getParams(), functionType, info); } // Compute the type of the reference. @@ -1864,7 +1872,9 @@ Type ConstraintSystem::getEffectiveOverloadType(const OverloadChoice &overload, auto indices = subscript->getInterfaceType() ->castTo()->getParams(); - type = FunctionType::get(indices, elementTy); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + type = FunctionType::get(indices, elementTy, info); } else if (auto var = dyn_cast(decl)) { type = var->getValueInterfaceType(); if (doesStorageProduceLValue(var, overload.getBaseType(), useDC)) @@ -1975,7 +1985,9 @@ static std::pair getTypeOfReferenceWithSpecialTypeCheckingSemantics( CS.addConstraint( ConstraintKind::DynamicTypeOf, output, input, CS.getConstraintLocator(locator, ConstraintLocator::DynamicType)); - auto refType = FunctionType::get({inputArg}, output); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + auto refType = FunctionType::get({inputArg}, output, info); return {refType, refType}; } case DeclTypeCheckingSemantics::WithoutActuallyEscaping: { @@ -2644,8 +2656,10 @@ void ConstraintSystem::bindOverloadType( ConstraintLocator::FunctionResult), TVO_CanBindToLValue | TVO_CanBindToNoEscape); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; auto adjustedFnTy = - FunctionType::get(fnType->getParams(), subscriptResultTy); + FunctionType::get(fnType->getParams(), subscriptResultTy, info); ConstraintLocatorBuilder kpLocBuilder(keyPathLoc); addConstraint( @@ -2802,10 +2816,14 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator, FunctionType::Param indices[] = { FunctionType::Param(keyPathIndexTy, getASTContext().Id_keyPath), }; - auto subscriptTy = FunctionType::get(indices, elementTy); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo subscriptInfo; + auto subscriptTy = FunctionType::get(indices, elementTy, subscriptInfo); FunctionType::Param baseParam(choice.getBaseType()); - auto fullTy = FunctionType::get({baseParam}, subscriptTy); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo fullInfo; + auto fullTy = FunctionType::get({baseParam}, subscriptTy, fullInfo); openedFullType = fullTy; refType = subscriptTy; diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index f9ad680aff956..f2b86d85450b3 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -3222,14 +3222,18 @@ AttributeChecker::visitImplementationOnlyAttr(ImplementationOnlyAttr *attr) { // into a monomorphic function type. // FIXME: does this actually make sense, though? auto derivedInterfaceFuncTy = derivedInterfaceTy->castTo(); - derivedInterfaceTy = - FunctionType::get(derivedInterfaceFuncTy->getParams(), - derivedInterfaceFuncTy->getResult()); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo derivedInterfaceInfo; + derivedInterfaceTy = FunctionType::get(derivedInterfaceFuncTy->getParams(), + derivedInterfaceFuncTy->getResult(), + derivedInterfaceInfo); auto overrideInterfaceFuncTy = overrideInterfaceTy->castTo(); - overrideInterfaceTy = - FunctionType::get(overrideInterfaceFuncTy->getParams(), - overrideInterfaceFuncTy->getResult()); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo overrideInterfaceInfo; + overrideInterfaceTy = FunctionType::get( + overrideInterfaceFuncTy->getParams(), + overrideInterfaceFuncTy->getResult(), overrideInterfaceInfo); } if (!derivedInterfaceTy->isEqual(overrideInterfaceTy)) { @@ -4062,9 +4066,14 @@ static bool checkFunctionSignature( static AnyFunctionType * makeFunctionType(ArrayRef parameters, Type resultType, GenericSignature genericSignature) { - if (genericSignature) - return GenericFunctionType::get(genericSignature, parameters, resultType); - return FunctionType::get(parameters, resultType); + // FIXME: Verify ExtInfo state is correct, not working by accident. + if (genericSignature) { + GenericFunctionType::ExtInfo info; + return GenericFunctionType::get(genericSignature, parameters, resultType, + info); + } + FunctionType::ExtInfo info; + return FunctionType::get(parameters, resultType, info); } /// Computes the original function type corresponding to the given derivative diff --git a/lib/Sema/TypeCheckCodeCompletion.cpp b/lib/Sema/TypeCheckCodeCompletion.cpp index aedca3b125587..2e6efe8464b8a 100644 --- a/lib/Sema/TypeCheckCodeCompletion.cpp +++ b/lib/Sema/TypeCheckCodeCompletion.cpp @@ -524,7 +524,10 @@ getTypeOfCompletionOperatorImpl(DeclContext *DC, Expr *expr, argTypes.emplace_back(solution.simplifyType(CS.getType(arg))); } - return FunctionType::get(argTypes, solution.simplifyType(CS.getType(expr))); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + return FunctionType::get(argTypes, solution.simplifyType(CS.getType(expr)), + info); } /// Return the type of operator function for specified LHS, or a null diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 8395686ba31c3..020aa61eb5cbe 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -2400,10 +2400,14 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const { if (hasSelf) { // Substitute in our own 'self' parameter. auto selfParam = computeSelfParam(AFD); - if (sig) - funcTy = GenericFunctionType::get(sig, {selfParam}, funcTy); - else - funcTy = FunctionType::get({selfParam}, funcTy); + // FIXME: Verify ExtInfo state is correct, not working by accident. + if (sig) { + GenericFunctionType::ExtInfo info; + funcTy = GenericFunctionType::get(sig, {selfParam}, funcTy, info); + } else { + FunctionType::ExtInfo info; + funcTy = FunctionType::get({selfParam}, funcTy, info); + } } return funcTy; @@ -2418,10 +2422,14 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const { SD->getIndices()->getParams(argTy); Type funcTy; - if (auto sig = SD->getGenericSignature()) - funcTy = GenericFunctionType::get(sig, argTy, elementTy); - else - funcTy = FunctionType::get(argTy, elementTy); + // FIXME: Verify ExtInfo state is correct, not working by accident. + if (auto sig = SD->getGenericSignature()) { + GenericFunctionType::ExtInfo info; + funcTy = GenericFunctionType::get(sig, argTy, elementTy, info); + } else { + FunctionType::ExtInfo info; + funcTy = FunctionType::get(argTy, elementTy, info); + } return funcTy; } @@ -2441,13 +2449,19 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const { SmallVector argTy; PL->getParams(argTy); - resultTy = FunctionType::get(argTy, resultTy); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + resultTy = FunctionType::get(argTy, resultTy, info); } - if (auto genericSig = ED->getGenericSignature()) - resultTy = GenericFunctionType::get(genericSig, {selfTy}, resultTy); - else - resultTy = FunctionType::get({selfTy}, resultTy); + // FIXME: Verify ExtInfo state is correct, not working by accident. + if (auto genericSig = ED->getGenericSignature()) { + GenericFunctionType::ExtInfo info; + resultTy = GenericFunctionType::get(genericSig, {selfTy}, resultTy, info); + } else { + FunctionType::ExtInfo info; + resultTy = FunctionType::get({selfTy}, resultTy, info); + } return resultTy; } diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index 5bc9eb0db8830..2e9455bcdf883 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -95,7 +95,10 @@ Type swift::getMemberTypeForComparison(const ValueDecl *member, // For subscripts, we don't have a 'Self' type, but turn it // into a monomorphic function type. auto funcTy = memberType->castTo(); - memberType = FunctionType::get(funcTy->getParams(), funcTy->getResult()); + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; + memberType = + FunctionType::get(funcTy->getParams(), funcTy->getResult(), info); } else { // For properties, strip off ownership. memberType = memberType->getReferenceStorageReferent(); diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index ac18a1e83e990..fdccb3e4d040a 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -744,22 +744,24 @@ swift::matchWitness( } } - // If the witness is 'async', the requirement must be. - if (witnessFnType->getExtInfo().isAsync() && - !reqFnType->getExtInfo().isAsync()) { - return RequirementMatch(witness, MatchKind::AsyncConflict); - } + if (witnessFnType->hasExtInfo()) { + // If the witness is 'async', the requirement must be. + if (witnessFnType->getExtInfo().isAsync() && + !reqFnType->getExtInfo().isAsync()) { + return RequirementMatch(witness, MatchKind::AsyncConflict); + } - // If witness is sync, the requirement cannot be @objc and 'async' - if (!witnessFnType->getExtInfo().isAsync() && - (req->isObjC() && reqFnType->getExtInfo().isAsync())) { - return RequirementMatch(witness, MatchKind::AsyncConflict); - } + // If witness is sync, the requirement cannot be @objc and 'async' + if (!witnessFnType->getExtInfo().isAsync() && + (req->isObjC() && reqFnType->getExtInfo().isAsync())) { + return RequirementMatch(witness, MatchKind::AsyncConflict); + } - // If the witness is 'throws', the requirement must be. - if (witnessFnType->getExtInfo().isThrowing() && - !reqFnType->getExtInfo().isThrowing()) { - return RequirementMatch(witness, MatchKind::ThrowsConflict); + // If the witness is 'throws', the requirement must be. + if (witnessFnType->getExtInfo().isThrowing() && + !reqFnType->getExtInfo().isThrowing()) { + return RequirementMatch(witness, MatchKind::ThrowsConflict); + } } } else { auto reqTypeIsIUO = req->isImplicitlyUnwrappedOptional(); diff --git a/unittests/AST/TypeMatchTests.cpp b/unittests/AST/TypeMatchTests.cpp index 71154e43a899a..ca6a9059b6da3 100644 --- a/unittests/AST/TypeMatchTests.cpp +++ b/unittests/AST/TypeMatchTests.cpp @@ -46,6 +46,8 @@ TEST(TypeMatch, IdenticalTypes) { } TEST(TypeMatch, UnrelatedTypes) { + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; TestContext C; auto check = [](Type base, Type derived) { @@ -56,11 +58,11 @@ TEST(TypeMatch, UnrelatedTypes) { EXPECT_FALSE(check(C.Ctx.TheEmptyTupleType, C.Ctx.TheRawPointerType)); EXPECT_FALSE(check(C.Ctx.TheRawPointerType, C.Ctx.TheEmptyTupleType)); - Type voidToVoidFn = FunctionType::get({}, C.Ctx.TheEmptyTupleType); + Type voidToVoidFn = FunctionType::get({}, C.Ctx.TheEmptyTupleType, info); EXPECT_FALSE(check(voidToVoidFn, C.Ctx.TheEmptyTupleType)); EXPECT_FALSE(check(C.Ctx.TheEmptyTupleType, voidToVoidFn)); - Type ptrToPtrFn = FunctionType::get({}, C.Ctx.TheRawPointerType); + Type ptrToPtrFn = FunctionType::get({}, C.Ctx.TheRawPointerType, info); EXPECT_FALSE(check(ptrToPtrFn, voidToVoidFn)); EXPECT_FALSE(check(voidToVoidFn, ptrToPtrFn)); @@ -72,7 +74,7 @@ TEST(TypeMatch, UnrelatedTypes) { EXPECT_FALSE(check(voidToVoidFn, structTy)); Type structToStructFn = FunctionType::get( - FunctionType::Param(structTy), structTy); + FunctionType::Param(structTy), structTy, info); EXPECT_FALSE(check(structToStructFn, structTy)); EXPECT_FALSE(check(structTy, structToStructFn)); EXPECT_FALSE(check(structToStructFn, voidToVoidFn)); @@ -85,13 +87,13 @@ TEST(TypeMatch, UnrelatedTypes) { Type anotherStructToAnotherStructFn = FunctionType::get( FunctionType::Param(anotherStructTy), - anotherStructTy); + anotherStructTy, info); EXPECT_FALSE(check(anotherStructToAnotherStructFn, structToStructFn)); EXPECT_FALSE(check(structToStructFn, anotherStructToAnotherStructFn)); Type S2ASFn = FunctionType::get( FunctionType::Param(structTy), - anotherStructTy); + anotherStructTy, info); EXPECT_FALSE(check(S2ASFn, structToStructFn)); EXPECT_FALSE(check(structToStructFn, S2ASFn)); EXPECT_FALSE(check(S2ASFn, anotherStructToAnotherStructFn)); @@ -99,6 +101,8 @@ TEST(TypeMatch, UnrelatedTypes) { } TEST(TypeMatch, Classes) { + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; TestContext C; auto check = [](Type base, Type derived) { @@ -125,27 +129,29 @@ TEST(TypeMatch, Classes) { Type baseToVoid = FunctionType::get( FunctionType::Param(baseTy), - C.Ctx.TheEmptyTupleType); + C.Ctx.TheEmptyTupleType, info); Type subToVoid = FunctionType::get( FunctionType::Param(subTy), - C.Ctx.TheEmptyTupleType); + C.Ctx.TheEmptyTupleType, info); EXPECT_FALSE(check(baseToVoid, subToVoid)); EXPECT_TRUE(check(subToVoid, baseToVoid)); - Type voidToBase = FunctionType::get({}, baseTy); - Type voidToSub = FunctionType::get({}, subTy); + Type voidToBase = FunctionType::get({}, baseTy, info); + Type voidToSub = FunctionType::get({}, subTy, info); EXPECT_FALSE(check(voidToSub, voidToBase)); EXPECT_TRUE(check(voidToBase, voidToSub)); Type baseToBase = FunctionType::get( - FunctionType::Param(baseTy), baseTy); + FunctionType::Param(baseTy), baseTy, info); Type subToSub = FunctionType::get( - FunctionType::Param(subTy), subTy); + FunctionType::Param(subTy), subTy, info); EXPECT_FALSE(check(baseToBase, subToSub)); EXPECT_FALSE(check(subToSub, baseToBase)); } TEST(TypeMatch, Optionals) { + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; TestContext C{DeclareOptionalTypes}; auto check = [](Type base, Type derived) { @@ -162,29 +168,31 @@ TEST(TypeMatch, Optionals) { Type baseToVoid = FunctionType::get( FunctionType::Param(baseTy), - C.Ctx.TheEmptyTupleType); + C.Ctx.TheEmptyTupleType, info); Type optToVoid = FunctionType::get( FunctionType::Param(optTy), - C.Ctx.TheEmptyTupleType); + C.Ctx.TheEmptyTupleType, info); EXPECT_TRUE(check(baseToVoid, optToVoid)); EXPECT_FALSE(check(optToVoid, baseToVoid)); - Type voidToBase = FunctionType::get({}, baseTy); - Type voidToOpt = FunctionType::get({}, optTy); + Type voidToBase = FunctionType::get({}, baseTy, info); + Type voidToOpt = FunctionType::get({}, optTy, info); EXPECT_FALSE(check(voidToBase, voidToOpt)); EXPECT_TRUE(check(voidToOpt, voidToBase)); Type baseToBase = FunctionType::get( FunctionType::Param(baseTy), - baseTy); + baseTy, info); Type optToOpt = FunctionType::get( FunctionType::Param(optTy), - optTy); + optTy, info); EXPECT_FALSE(check(baseToBase, optToOpt)); EXPECT_FALSE(check(optToOpt, baseToBase)); } TEST(TypeMatch, OptionalMismatch) { + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; TestContext C{DeclareOptionalTypes}; auto check = [](Type base, Type derived) { @@ -207,10 +215,10 @@ TEST(TypeMatch, OptionalMismatch) { Type baseToVoid = FunctionType::get( FunctionType::Param(baseTy), - C.Ctx.TheEmptyTupleType); + C.Ctx.TheEmptyTupleType, info); Type optToVoid = FunctionType::get( FunctionType::Param(optTy), - C.Ctx.TheEmptyTupleType); + C.Ctx.TheEmptyTupleType, info); EXPECT_TRUE(check(baseToVoid, optToVoid)); EXPECT_TRUE(checkOpt(baseToVoid, optToVoid)); EXPECT_TRUE(checkOptOverride(baseToVoid, optToVoid)); @@ -218,8 +226,8 @@ TEST(TypeMatch, OptionalMismatch) { EXPECT_TRUE(checkOpt(optToVoid, baseToVoid)); EXPECT_TRUE(checkOptOverride(optToVoid, baseToVoid)); - Type voidToBase = FunctionType::get({}, baseTy); - Type voidToOpt = FunctionType::get({}, optTy); + Type voidToBase = FunctionType::get({}, baseTy, info); + Type voidToOpt = FunctionType::get({}, optTy, info); EXPECT_FALSE(check(voidToBase, voidToOpt)); EXPECT_TRUE(checkOpt(voidToBase, voidToOpt)); EXPECT_TRUE(checkOptOverride(voidToBase, voidToOpt)); @@ -229,10 +237,10 @@ TEST(TypeMatch, OptionalMismatch) { Type baseToBase = FunctionType::get( FunctionType::Param(baseTy), - baseTy); + baseTy, info); Type optToOpt = FunctionType::get( FunctionType::Param(optTy), - optTy); + optTy, info); EXPECT_FALSE(check(baseToBase, optToOpt)); EXPECT_TRUE(checkOpt(baseToBase, optToOpt)); EXPECT_TRUE(checkOptOverride(baseToBase, optToOpt)); @@ -348,6 +356,8 @@ TEST(TypeMatch, OptionalMismatchFunctions) { } TEST(TypeMatch, NoEscapeMismatchFunctions) { + // FIXME: Verify ExtInfo state is correct, not working by accident. + FunctionType::ExtInfo info; TestContext C{DeclareOptionalTypes}; // Note the reversed names here: parameters must be contravariant for the @@ -361,7 +371,7 @@ TEST(TypeMatch, NoEscapeMismatchFunctions) { TypeMatchFlags::IgnoreNonEscapingForOptionalFunctionParam); }; - Type voidToVoidFn = FunctionType::get({}, C.Ctx.TheEmptyTupleType); + Type voidToVoidFn = FunctionType::get({}, C.Ctx.TheEmptyTupleType, info); Type nonescapingVoidToVoidFn = FunctionType::get({}, C.Ctx.TheEmptyTupleType, FunctionType::ExtInfo().withNoEscape());