diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index 4eded2f8c2525..e3745be52d7b2 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -590,13 +590,9 @@ class ASTContext final { /// /// \param params The function parameters. /// \param resultTy The Swift result type. - /// \param incompleteExtInfo Used to convey escaping and throwing - /// information, in case it is needed. /// \param trueRep The actual calling convention, which must be C-compatible. - /// The calling convention in \p incompleteExtInfo is ignored. const clang::Type * getClangFunctionType(ArrayRef params, Type resultTy, - const FunctionType::ExtInfo incompleteExtInfo, FunctionTypeRepresentation trueRep); /// Get the Swift declaration that a Clang declaration was exported from, diff --git a/include/swift/AST/ExtInfo.h b/include/swift/AST/ExtInfo.h new file mode 100644 index 0000000000000..374ea18174c5f --- /dev/null +++ b/include/swift/AST/ExtInfo.h @@ -0,0 +1,724 @@ +//===--- ExtInfo.h - Extended information for function types ----*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2020 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 +// +//===----------------------------------------------------------------------===// +// +// Defines the ASTExtInfo and SILExtInfo classes, which are used to store +// the calling convention and related information for function types in the AST +// and SIL respectively. These types are lightweight and immutable; they are +// constructed using builder-pattern style APIs to enforce invariants. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_EXTINFO_H +#define SWIFT_EXTINFO_H + +#include "swift/AST/AutoDiff.h" +#include "swift/AST/ClangModuleLoader.h" + +#include "llvm/ADT/Optional.h" +#include "llvm/Support/raw_ostream.h" + +#include + +namespace clang { +class Type; +} // namespace clang + +namespace swift { +class AnyFunctionType; +class ASTExtInfo; +class ASTExtInfoBuilder; +class FunctionType; +class SILExtInfo; +class SILExtInfoBuilder; +class SILFunctionType; +} // namespace swift + +namespace swift { + +// MARK: - ClangTypeInfo +/// Wrapper class for storing a clang::Type in an (AST|SIL)ExtInfo. +class ClangTypeInfo { + friend AnyFunctionType; + friend FunctionType; + friend SILFunctionType; + friend ASTExtInfoBuilder; + friend SILExtInfoBuilder; + + // We preserve a full clang::Type *, not a clang::FunctionType * as: + // 1. We need to keep sugar in case we need to present an error to the user + // (for AnyFunctionType). + // 2. The actual type being stored is [ignoring sugar] either a + // clang::PointerType, a clang::BlockPointerType, or a + // clang::ReferenceType which points to a clang::FunctionType. + // + // When used as a part of SILFunctionType, the type is canonical. + const clang::Type *type; + + constexpr ClangTypeInfo() : type(nullptr) {} + constexpr ClangTypeInfo(const clang::Type *type) : type(type) {} + + friend bool operator==(ClangTypeInfo lhs, ClangTypeInfo rhs); + ClangTypeInfo getCanonical() const; + +public: + constexpr const clang::Type *getType() const { return type; } + + constexpr bool empty() const { return !type; } + + /// Use the ClangModuleLoader to print the Clang type as a string. + void printType(ClangModuleLoader *cml, llvm::raw_ostream &os) const; + + void dump(llvm::raw_ostream &os) const; +}; + +// MARK: - FunctionTypeRepresentation +/// The representation form of a function. +enum class FunctionTypeRepresentation : uint8_t { + /// A "thick" function that carries a context pointer to reference captured + /// state. The default native function representation. + Swift = 0, + + /// A thick function that is represented as an Objective-C block. + Block, + + /// A "thin" function that needs no context. + Thin, + + /// A C function pointer (or reference), which is thin and also uses the C + /// calling convention. + CFunctionPointer, + + /// The value of the greatest AST function representation. + Last = CFunctionPointer, +}; + +// MARK: - SILFunctionTypeRepresentation + +/// The representation form of a SIL function. +/// +/// This is a superset of FunctionTypeRepresentation. The common representations +/// must share an enum value. +/// +/// TODO: The overlap of SILFunctionTypeRepresentation and +/// FunctionTypeRepresentation is a total hack necessitated by the way SIL +/// TypeLowering is currently written. We ought to refactor TypeLowering so that +/// it is not necessary to distinguish these cases. +enum class SILFunctionTypeRepresentation : uint8_t { + /// A freestanding thick function. + Thick = uint8_t(FunctionTypeRepresentation::Swift), + + /// A thick function that is represented as an Objective-C block. + Block = uint8_t(FunctionTypeRepresentation::Block), + + /// A freestanding thin function that needs no context. + Thin = uint8_t(FunctionTypeRepresentation::Thin), + + /// A C function pointer, which is thin and also uses the C calling + /// convention. + CFunctionPointer = uint8_t(FunctionTypeRepresentation::CFunctionPointer), + + /// The value of the greatest AST function representation. + LastAST = CFunctionPointer, + + /// The value of the least SIL-only function representation. + FirstSIL = 8, + + /// A Swift instance method. + Method = FirstSIL, + + /// An Objective-C method. + ObjCMethod, + + /// A Swift protocol witness. + WitnessMethod, + + /// A closure invocation function that has not been bound to a context. + Closure, +}; + +/// Can this calling convention result in a function being called indirectly +/// through the runtime. +constexpr bool canBeCalledIndirectly(SILFunctionTypeRepresentation rep) { + switch (rep) { + case SILFunctionTypeRepresentation::Thick: + case SILFunctionTypeRepresentation::Thin: + case SILFunctionTypeRepresentation::CFunctionPointer: + case SILFunctionTypeRepresentation::Block: + case SILFunctionTypeRepresentation::Closure: + return false; + case SILFunctionTypeRepresentation::ObjCMethod: + case SILFunctionTypeRepresentation::Method: + case SILFunctionTypeRepresentation::WitnessMethod: + return true; + } + + llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch."); +} + +// MARK: - ASTExtInfoBuilder +/// A builder type for creating an \c ASTExtInfo. +/// +/// The main API public includes the \c withXYZ and \p build() methods. +class ASTExtInfoBuilder { + friend AnyFunctionType; + friend ASTExtInfo; + + // If bits are added or removed, then TypeBase::AnyFunctionTypeBits + // and NumMaskBits must be updated, and they must match. + // + // |representation|noEscape|async|throws|differentiability| + // | 0 .. 3 | 4 | 5 | 6 | 7 .. 8 | + // + enum : unsigned { + RepresentationMask = 0xF << 0, + NoEscapeMask = 1 << 4, + AsyncMask = 1 << 5, + ThrowsMask = 1 << 6, + DifferentiabilityMaskOffset = 7, + DifferentiabilityMask = 0x3 << DifferentiabilityMaskOffset, + NumMaskBits = 9 + }; + + unsigned bits; // Naturally sized for speed. + + ClangTypeInfo clangTypeInfo; + + using Representation = FunctionTypeRepresentation; + + static void assertIsFunctionType(const clang::Type *); + + ASTExtInfoBuilder(unsigned bits, ClangTypeInfo clangTypeInfo) + : bits(bits), clangTypeInfo(clangTypeInfo) { + // TODO: [clang-function-type-serialization] Once we start serializing + // the Clang type, we should also assert that the pointer is non-null. + auto Rep = Representation(bits & RepresentationMask); + if ((Rep == Representation::CFunctionPointer) && clangTypeInfo.type) + assertIsFunctionType(clangTypeInfo.type); + } + +public: + // Constructor with all defaults. + ASTExtInfoBuilder() + : ASTExtInfoBuilder(Representation::Swift, false, false, + DifferentiabilityKind::NonDifferentiable, nullptr) {} + + // Constructor for polymorphic type. + ASTExtInfoBuilder(Representation rep, bool throws) + : ASTExtInfoBuilder(rep, false, throws, + DifferentiabilityKind::NonDifferentiable, nullptr) {} + + // Constructor with no defaults. + ASTExtInfoBuilder(Representation rep, bool isNoEscape, bool throws, + DifferentiabilityKind diffKind, const clang::Type *type) + : ASTExtInfoBuilder( + ((unsigned)rep) | (isNoEscape ? NoEscapeMask : 0) | + (throws ? ThrowsMask : 0) | + (((unsigned)diffKind << DifferentiabilityMaskOffset) & + DifferentiabilityMask), + ClangTypeInfo(type)) {} + + void checkInvariants() const; + + /// Check if \c this is well-formed and create an ExtInfo. + ASTExtInfo build() const; + + constexpr Representation getRepresentation() const { + unsigned rawRep = bits & RepresentationMask; + assert(rawRep <= unsigned(Representation::Last) && + "unexpected SIL representation"); + return Representation(rawRep); + } + + constexpr bool isNoEscape() const { return bits & NoEscapeMask; } + + constexpr bool async() const { return bits & AsyncMask; } + + constexpr bool throws() const { return bits & ThrowsMask; } + + constexpr DifferentiabilityKind getDifferentiabilityKind() const { + return DifferentiabilityKind((bits & DifferentiabilityMask) >> + DifferentiabilityMaskOffset); + } + + constexpr bool isDifferentiable() const { + return getDifferentiabilityKind() > + DifferentiabilityKind::NonDifferentiable; + } + + /// Get the underlying ClangTypeInfo value if it is not the default value. + Optional getClangTypeInfo() const { + return clangTypeInfo.empty() ? Optional() : clangTypeInfo; + } + + constexpr SILFunctionTypeRepresentation getSILRepresentation() const { + unsigned rawRep = bits & RepresentationMask; + return SILFunctionTypeRepresentation(rawRep); + } + + constexpr bool hasSelfParam() const { + switch (getSILRepresentation()) { + case SILFunctionTypeRepresentation::Thick: + case SILFunctionTypeRepresentation::Block: + case SILFunctionTypeRepresentation::Thin: + case SILFunctionTypeRepresentation::CFunctionPointer: + case SILFunctionTypeRepresentation::Closure: + return false; + case SILFunctionTypeRepresentation::ObjCMethod: + case SILFunctionTypeRepresentation::Method: + case SILFunctionTypeRepresentation::WitnessMethod: + return true; + } + llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch."); + } + + /// True if the function representation carries context. + constexpr bool hasContext() const { + switch (getSILRepresentation()) { + case SILFunctionTypeRepresentation::Thick: + case SILFunctionTypeRepresentation::Block: + return true; + case SILFunctionTypeRepresentation::Thin: + case SILFunctionTypeRepresentation::Method: + case SILFunctionTypeRepresentation::ObjCMethod: + case SILFunctionTypeRepresentation::WitnessMethod: + case SILFunctionTypeRepresentation::CFunctionPointer: + case SILFunctionTypeRepresentation::Closure: + return false; + } + llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch."); + } + + // Note that we don't have setters. That is by design, use + // the following with methods instead of mutating these objects. + LLVM_NODISCARD + ASTExtInfoBuilder withRepresentation(Representation rep) const { + return ASTExtInfoBuilder((bits & ~RepresentationMask) | (unsigned)rep, + clangTypeInfo); + } + LLVM_NODISCARD + ASTExtInfoBuilder withNoEscape(bool noEscape = true) const { + return ASTExtInfoBuilder(noEscape ? (bits | NoEscapeMask) + : (bits & ~NoEscapeMask), + clangTypeInfo); + } + LLVM_NODISCARD + ASTExtInfoBuilder withAsync(bool async = true) const { + return ASTExtInfoBuilder(async ? (bits | AsyncMask) + : (bits & ~AsyncMask), + clangTypeInfo); + } + LLVM_NODISCARD + ASTExtInfoBuilder withThrows(bool throws = true) const { + return ASTExtInfoBuilder( + throws ? (bits | ThrowsMask) : (bits & ~ThrowsMask), clangTypeInfo); + } + LLVM_NODISCARD + ASTExtInfoBuilder + withDifferentiabilityKind(DifferentiabilityKind differentiability) const { + return ASTExtInfoBuilder( + (bits & ~DifferentiabilityMask) | + ((unsigned)differentiability << DifferentiabilityMaskOffset), + clangTypeInfo); + } + LLVM_NODISCARD + ASTExtInfoBuilder withClangFunctionType(const clang::Type *type) const { + return ASTExtInfoBuilder(bits, ClangTypeInfo(type)); + } + + /// Put a SIL representation in the ExtInfo. + /// + /// SIL type lowering transiently generates AST function types with SIL + /// representations. However, they shouldn't persist in the AST, and + /// don't need to be parsed, printed, or serialized. + LLVM_NODISCARD + ASTExtInfoBuilder + withSILRepresentation(SILFunctionTypeRepresentation rep) const { + return ASTExtInfoBuilder((bits & ~RepresentationMask) | (unsigned)rep, + clangTypeInfo); + } + + bool isEqualTo(ASTExtInfoBuilder other, bool useClangTypes) const { + return bits == other.bits && + (useClangTypes ? (clangTypeInfo == other.clangTypeInfo) : true); + } + + constexpr std::pair getFuncAttrKey() const { + return std::make_pair(bits, clangTypeInfo.getType()); + } +}; // end ASTExtInfoBuilder + +// MARK: - ASTExtInfo +/// Calling convention and related information for AnyFunctionType + subclasses. +/// +/// New instances can be made from existing instances via \c ASTExtInfoBuilder, +/// typically using a code pattern like: +/// \code +/// extInfo.intoBuilder().withX(x).withY(y).build() +/// \endcode +class ASTExtInfo { + friend ASTExtInfoBuilder; + friend AnyFunctionType; + + ASTExtInfoBuilder builder; + + ASTExtInfo(ASTExtInfoBuilder builder) : builder(builder) {} + ASTExtInfo(unsigned bits, ClangTypeInfo clangTypeInfo) + : builder(bits, clangTypeInfo){}; + +public: + ASTExtInfo() : builder(){}; + + /// Create a builder with the same state as \c this. + ASTExtInfoBuilder intoBuilder() const { return builder; } + +private: + constexpr unsigned getBits() const { return builder.bits; } + +public: + constexpr FunctionTypeRepresentation getRepresentation() const { + return builder.getRepresentation(); + } + + constexpr SILFunctionTypeRepresentation getSILRepresentation() const { + return builder.getSILRepresentation(); + } + + constexpr bool isNoEscape() const { return builder.isNoEscape(); } + + constexpr bool async() const { return builder.async(); } + + constexpr bool throws() const { return builder.throws(); } + + constexpr DifferentiabilityKind getDifferentiabilityKind() const { + return builder.getDifferentiabilityKind(); + } + + constexpr bool isDifferentiable() const { return builder.isDifferentiable(); } + + Optional getClangTypeInfo() const { + return builder.getClangTypeInfo(); + } + + constexpr bool hasSelfParam() const { return builder.hasSelfParam(); } + + constexpr bool hasContext() const { return builder.hasContext(); } + + /// Helper method for changing the representation. + /// + /// Prefer using \c ASTExtInfoBuilder::withRepresentation for chaining. + LLVM_NODISCARD + ASTExtInfo withRepresentation(ASTExtInfoBuilder::Representation rep) const { + return builder.withRepresentation(rep).build(); + } + + /// Helper method for changing only the noEscape field. + /// + /// Prefer using \c ASTExtInfoBuilder::withNoEscape for chaining. + LLVM_NODISCARD + ASTExtInfo withNoEscape(bool noEscape = true) const { + return builder.withNoEscape(noEscape).build(); + } + + /// Helper method for changing only the throws field. + /// + /// Prefer using \c ASTExtInfoBuilder::withThrows for chaining. + LLVM_NODISCARD + ASTExtInfo withThrows(bool throws = true) const { + return builder.withThrows(throws).build(); + } + + bool isEqualTo(ASTExtInfo other, bool useClangTypes) const { + return builder.isEqualTo(other.builder, useClangTypes); + } + + constexpr std::pair getFuncAttrKey() const { + return builder.getFuncAttrKey(); + } +}; // end ASTExtInfo + +// MARK: - SILFunctionLanguage + +/// A language-level calling convention. +enum class SILFunctionLanguage : uint8_t { + /// A variation of the Swift calling convention. + Swift = 0, + + /// A variation of the C calling convention. + C, +}; + +/// Map a SIL function representation to the base language calling convention +/// it uses. +constexpr +SILFunctionLanguage getSILFunctionLanguage(SILFunctionTypeRepresentation rep) { + switch (rep) { + case SILFunctionTypeRepresentation::ObjCMethod: + case SILFunctionTypeRepresentation::CFunctionPointer: + case SILFunctionTypeRepresentation::Block: + return SILFunctionLanguage::C; + case SILFunctionTypeRepresentation::Thick: + case SILFunctionTypeRepresentation::Thin: + case SILFunctionTypeRepresentation::Method: + case SILFunctionTypeRepresentation::WitnessMethod: + case SILFunctionTypeRepresentation::Closure: + return SILFunctionLanguage::Swift; + } + + llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch."); +} + +// MARK: - SILExtInfoBuilder +/// A builder type for creating an \c SILExtInfo. +/// +/// The main API public includes the \c withXYZ and \p build() methods. +class SILExtInfoBuilder { + friend SILExtInfo; + friend SILFunctionType; + + // If bits are added or removed, then TypeBase::SILFunctionTypeBits + // and NumMaskBits must be updated, and they must match. + + // |representation|pseudogeneric| noescape |differentiability| + // | 0 .. 3 | 4 | 5 | 6 .. 7 | + // + enum : unsigned { + RepresentationMask = 0xF << 0, + PseudogenericMask = 1 << 4, + NoEscapeMask = 1 << 5, + DifferentiabilityMaskOffset = 6, + DifferentiabilityMask = 0x3 << DifferentiabilityMaskOffset, + NumMaskBits = 8 + }; + + unsigned bits; // Naturally sized for speed. + + ClangTypeInfo clangTypeInfo; + + using Language = SILFunctionLanguage; + using Representation = SILFunctionTypeRepresentation; + + SILExtInfoBuilder(unsigned bits, ClangTypeInfo clangTypeInfo) + : bits(bits), clangTypeInfo(clangTypeInfo) {} + +public: + // Constructor with all defaults. + SILExtInfoBuilder() : bits(0), clangTypeInfo(ClangTypeInfo(nullptr)) {} + + // Constructor for polymorphic type. + SILExtInfoBuilder(Representation rep, bool isPseudogeneric, bool isNoEscape, + DifferentiabilityKind diffKind, const clang::Type *type) + : SILExtInfoBuilder( + ((unsigned)rep) | (isPseudogeneric ? PseudogenericMask : 0) | + (isNoEscape ? NoEscapeMask : 0) | + (((unsigned)diffKind << DifferentiabilityMaskOffset) & + DifferentiabilityMask), + ClangTypeInfo(type)) {} + + void checkInvariants() const; + + /// Check if \c this is well-formed and create an ExtInfo. + SILExtInfo build() const; + + /// What is the abstract representation of this function value? + constexpr Representation getRepresentation() const { + return Representation(bits & RepresentationMask); + } + + constexpr Language getLanguage() const { + return getSILFunctionLanguage(getRepresentation()); + } + + /// Is this function pseudo-generic? A pseudo-generic function + /// is not permitted to dynamically depend on its type arguments. + constexpr bool isPseudogeneric() const { return bits & PseudogenericMask; } + + // Is this function guaranteed to be no-escape by the type system? + constexpr bool isNoEscape() const { return bits & NoEscapeMask; } + + constexpr DifferentiabilityKind getDifferentiabilityKind() const { + return DifferentiabilityKind((bits & DifferentiabilityMask) >> + DifferentiabilityMaskOffset); + } + + constexpr bool isDifferentiable() const { + return getDifferentiabilityKind() != + DifferentiabilityKind::NonDifferentiable; + } + + /// Get the underlying ClangTypeInfo value if it is not the default value. + Optional getClangTypeInfo() const { + return clangTypeInfo.empty() ? Optional() : clangTypeInfo; + } + + constexpr bool hasSelfParam() const { + switch (getRepresentation()) { + case Representation::Thick: + case Representation::Block: + case Representation::Thin: + case Representation::CFunctionPointer: + case Representation::Closure: + return false; + case Representation::ObjCMethod: + case Representation::Method: + case Representation::WitnessMethod: + return true; + } + llvm_unreachable("Unhandled Representation in switch."); + } + + /// True if the function representation carries context. + constexpr bool hasContext() const { + switch (getRepresentation()) { + case Representation::Thick: + case Representation::Block: + return true; + case Representation::Thin: + case Representation::CFunctionPointer: + case Representation::ObjCMethod: + case Representation::Method: + case Representation::WitnessMethod: + case Representation::Closure: + return false; + } + llvm_unreachable("Unhandled Representation in switch."); + } + + // Note that we don't have setters. That is by design, use + // the following with methods instead of mutating these objects. + SILExtInfoBuilder withRepresentation(Representation rep) const { + return SILExtInfoBuilder((bits & ~RepresentationMask) | (unsigned)rep, + clangTypeInfo); + } + SILExtInfoBuilder withIsPseudogeneric(bool isPseudogeneric = true) const { + return SILExtInfoBuilder(isPseudogeneric ? (bits | PseudogenericMask) + : (bits & ~PseudogenericMask), + clangTypeInfo); + } + SILExtInfoBuilder withNoEscape(bool noEscape = true) const { + return SILExtInfoBuilder(noEscape ? (bits | NoEscapeMask) + : (bits & ~NoEscapeMask), + clangTypeInfo); + } + SILExtInfoBuilder + withDifferentiabilityKind(DifferentiabilityKind differentiability) const { + return SILExtInfoBuilder( + (bits & ~DifferentiabilityMask) | + ((unsigned)differentiability << DifferentiabilityMaskOffset), + clangTypeInfo); + } + + bool isEqualTo(SILExtInfoBuilder other, bool useClangTypes) const { + return bits == other.bits && + (useClangTypes ? (clangTypeInfo == other.clangTypeInfo) : true); + } + + constexpr std::pair getFuncAttrKey() const { + return std::make_pair(bits, clangTypeInfo.getType()); + } +}; // end SILExtInfoBuilder + +// MARK: - SILExtInfo +/// Calling convention information for SILFunctionType. +/// +/// New instances can be made from existing instances via \c SILExtInfoBuilder, +/// typically using a code pattern like: +/// \code +/// extInfo.intoBuilder().withX(x).withY(y).build() +/// \endcode +class SILExtInfo { + friend SILExtInfoBuilder; + friend SILFunctionType; + + SILExtInfoBuilder builder; + + SILExtInfo(SILExtInfoBuilder builder) : builder(builder) {} + SILExtInfo(unsigned bits, ClangTypeInfo clangTypeInfo) + : builder(bits, clangTypeInfo){}; + +public: + SILExtInfo() : builder(){}; + + static SILExtInfo getThin() { + return SILExtInfoBuilder(SILExtInfoBuilder::Representation::Thin, false, + false, DifferentiabilityKind::NonDifferentiable, + nullptr) + .build(); + } + + /// Create a builder with the same state as \c this. + SILExtInfoBuilder intoBuilder() const { return builder; } + +private: + constexpr unsigned getBits() const { return builder.bits; } + +public: + constexpr SILFunctionTypeRepresentation getRepresentation() const { + return builder.getRepresentation(); + } + + constexpr SILFunctionLanguage getLanguage() const { + return builder.getLanguage(); + } + + constexpr bool isPseudogeneric() const { return builder.isPseudogeneric(); } + + constexpr bool isNoEscape() const { return builder.isNoEscape(); } + + constexpr DifferentiabilityKind getDifferentiabilityKind() const { + return builder.getDifferentiabilityKind(); + } + + constexpr bool isDifferentiable() const { return builder.isDifferentiable(); } + + Optional getClangTypeInfo() const { + return builder.getClangTypeInfo(); + } + + constexpr bool hasSelfParam() const { return builder.hasSelfParam(); } + + constexpr bool hasContext() const { return builder.hasContext(); } + + /// Helper method for changing the Representation. + /// + /// Prefer using \c SILExtInfoBuilder::withRepresentation for chaining. + SILExtInfo withRepresentation(SILExtInfoBuilder::Representation rep) const { + return builder.withRepresentation(rep).build(); + } + + /// Helper method for changing only the NoEscape field. + /// + /// Prefer using \c SILExtInfoBuilder::withNoEscape for chaining. + SILExtInfo withNoEscape(bool noEscape = true) const { + return builder.withNoEscape(noEscape).build(); + } + + bool isEqualTo(SILExtInfo other, bool useClangTypes) const { + return builder.isEqualTo(other.builder, useClangTypes); + } + + constexpr std::pair getFuncAttrKey() const { + return builder.getFuncAttrKey(); + } +}; + +/// Helper function to obtain the useClangTypes parameter for checking equality +/// of ExtInfos. +/// +/// Typically, the argument will be a function type which was used to obtain one +/// of the ExtInfos. +template bool useClangTypes(HasContext hasContext) { + return hasContext->getASTContext().LangOpts.UseClangFunctionTypes; +} + +} // end namespace swift + +#endif // SWIFT_EXTINFO_H diff --git a/include/swift/AST/TypeDifferenceVisitor.h b/include/swift/AST/TypeDifferenceVisitor.h index 3492c33151e46..bdad0415948bc 100644 --- a/include/swift/AST/TypeDifferenceVisitor.h +++ b/include/swift/AST/TypeDifferenceVisitor.h @@ -214,7 +214,7 @@ class CanTypeDifferenceVisitor : public CanTypePairVisitor { bool visitAnyFunctionType(CanAnyFunctionType type1, CanAnyFunctionType type2) { - if (type1->getExtInfo() != type2->getExtInfo()) + if (!type1->hasSameExtInfoAs(type2)) return asImpl().visitDifferentTypeStructure(type1, type2); if (asImpl().visit(type1.getResult(), type2.getResult())) @@ -242,10 +242,10 @@ class CanTypeDifferenceVisitor : public CanTypePairVisitor { bool visitSILFunctionTypeStructure(CanSILFunctionType type1, CanSILFunctionType type2) { - if (type1->getExtInfo() != type2->getExtInfo() || + if (!type1->hasSameExtInfoAs(type2) || type1->getCoroutineKind() != type2->getCoroutineKind() || - type1->getInvocationGenericSignature() - != type2->getInvocationGenericSignature()) + type1->getInvocationGenericSignature() != + type2->getInvocationGenericSignature()) return asImpl().visitDifferentTypeStructure(type1, type2); return false; } diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index f93494515d928..82f72daf9e644 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -20,6 +20,7 @@ #include "swift/AST/AutoDiff.h" #include "swift/AST/DeclContext.h" +#include "swift/AST/ExtInfo.h" #include "swift/AST/GenericParamKey.h" #include "swift/AST/Identifier.h" #include "swift/AST/Ownership.h" @@ -43,11 +44,6 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TrailingObjects.h" -namespace clang { -class Type; -class FunctionType; -} // namespace clang - namespace llvm { struct fltSemantics; } // namespace llvm @@ -2688,116 +2684,6 @@ BEGIN_CAN_TYPE_WRAPPER(DynamicSelfType, Type) } END_CAN_TYPE_WRAPPER(DynamicSelfType, Type) -/// A language-level calling convention. -enum class SILFunctionLanguage : uint8_t { - /// A variation of the Swift calling convention. - Swift = 0, - - /// A variation of the C calling convention. - C, -}; - -/// The representation form of a function. -enum class FunctionTypeRepresentation : uint8_t { - /// A "thick" function that carries a context pointer to reference captured - /// state. The default native function representation. - Swift = 0, - - /// A thick function that is represented as an Objective-C block. - Block, - - /// A "thin" function that needs no context. - Thin, - - /// A C function pointer (or reference), which is thin and also uses the C - /// calling convention. - CFunctionPointer, - - /// The value of the greatest AST function representation. - Last = CFunctionPointer, -}; - -/// The representation form of a SIL function. -/// -/// This is a superset of FunctionTypeRepresentation. The common representations -/// must share an enum value. -/// -/// TODO: The overlap of SILFunctionTypeRepresentation and -/// FunctionTypeRepresentation is a total hack necessitated by the way SIL -/// TypeLowering is currently written. We ought to refactor TypeLowering so that -/// it is not necessary to distinguish these cases. -enum class SILFunctionTypeRepresentation : uint8_t { - /// A freestanding thick function. - Thick = uint8_t(FunctionTypeRepresentation::Swift), - - /// A thick function that is represented as an Objective-C block. - Block = uint8_t(FunctionTypeRepresentation::Block), - - /// A freestanding thin function that needs no context. - Thin = uint8_t(FunctionTypeRepresentation::Thin), - - /// A C function pointer, which is thin and also uses the C calling - /// convention. - CFunctionPointer = uint8_t(FunctionTypeRepresentation::CFunctionPointer), - - /// The value of the greatest AST function representation. - LastAST = CFunctionPointer, - - /// The value of the least SIL-only function representation. - FirstSIL = 8, - - /// A Swift instance method. - Method = FirstSIL, - - /// An Objective-C method. - ObjCMethod, - - /// A Swift protocol witness. - WitnessMethod, - - /// A closure invocation function that has not been bound to a context. - Closure, -}; - -/// Can this calling convention result in a function being called indirectly -/// through the runtime. -inline bool canBeCalledIndirectly(SILFunctionTypeRepresentation rep) { - switch (rep) { - case SILFunctionTypeRepresentation::Thick: - case SILFunctionTypeRepresentation::Thin: - case SILFunctionTypeRepresentation::CFunctionPointer: - case SILFunctionTypeRepresentation::Block: - case SILFunctionTypeRepresentation::Closure: - return false; - case SILFunctionTypeRepresentation::ObjCMethod: - case SILFunctionTypeRepresentation::Method: - case SILFunctionTypeRepresentation::WitnessMethod: - return true; - } - - llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch."); -} - -/// Map a SIL function representation to the base language calling convention -/// it uses. -inline SILFunctionLanguage -getSILFunctionLanguage(SILFunctionTypeRepresentation rep) { - switch (rep) { - case SILFunctionTypeRepresentation::ObjCMethod: - case SILFunctionTypeRepresentation::CFunctionPointer: - case SILFunctionTypeRepresentation::Block: - return SILFunctionLanguage::C; - case SILFunctionTypeRepresentation::Thick: - case SILFunctionTypeRepresentation::Thin: - case SILFunctionTypeRepresentation::Method: - case SILFunctionTypeRepresentation::WitnessMethod: - case SILFunctionTypeRepresentation::Closure: - return SILFunctionLanguage::Swift; - } - - llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch."); -} - /// AnyFunctionType - A function type has zero or more input parameters and a /// single result. The result type may be a tuple. For example: /// "(int) -> int" or "(a : int, b : int) -> (int, int)". @@ -2914,6 +2800,8 @@ class AnyFunctionType : public TypeBase { } }; + using ExtInfo = swift::ASTExtInfo; + using ExtInfoBuilder = swift::ASTExtInfoBuilder; using CanParamArrayRef = ArrayRefView; @@ -2969,226 +2857,25 @@ class AnyFunctionType : public TypeBase { } }; - /// A class which abstracts out some details necessary for - /// making a call. - class ExtInfo { - // If bits are added or removed, then TypeBase::NumAFTExtInfoBits - // and NumMaskBits must be updated, and they must match. - // - // |representation|noEscape|throws|differentiability| - // | 0 .. 3 | 4 | 5 | 6 .. 7 | - // - enum : unsigned { - RepresentationMask = 0xF << 0, - NoEscapeMask = 1 << 4, - AsyncMask = 1 << 5, - ThrowsMask = 1 << 6, - DifferentiabilityMaskOffset = 7, - DifferentiabilityMask = 0x3 << DifferentiabilityMaskOffset, - NumMaskBits = 9 - }; - - unsigned Bits; // Naturally sized for speed. - - public: - class ClangTypeInfo { - friend ExtInfo; - friend class AnyFunctionType; - friend class FunctionType; - // We preserve a full clang::Type *, not a clang::FunctionType * as: - // 1. We need to keep sugar in case we need to present an error to the user. - // 2. The actual type being stored is [ignoring sugar] either a - // clang::PointerType, a clang::BlockPointerType, or a - // clang::ReferenceType which points to a clang::FunctionType. - const clang::Type *type; - - bool empty() const { return !type; } - ClangTypeInfo(const clang::Type *type) : type(type) {} - - public: - /// Use the ClangModuleLoader to print the Clang type as a string. - void printType(ClangModuleLoader *cml, llvm::raw_ostream &os) const; - }; - - private: - ClangTypeInfo Other; - - static void assertIsFunctionType(const clang::Type *); - - ExtInfo(unsigned Bits, ClangTypeInfo Other) : Bits(Bits), Other(Other) { - // [TODO: Clang-type-plumbing] Assert that the pointer is non-null. - auto Rep = Representation(Bits & RepresentationMask); - if ((Rep == Representation::CFunctionPointer) && Other.type) - assertIsFunctionType(Other.type); - } - - friend AnyFunctionType; - friend class FunctionType; - - public: - // Constructor with all defaults. - ExtInfo() - : ExtInfo(Representation::Swift, false, false, - DifferentiabilityKind::NonDifferentiable, - nullptr) { - } - - // Constructor for polymorphic type. - ExtInfo(Representation Rep, bool Throws) - : ExtInfo(Rep, false, Throws, DifferentiabilityKind::NonDifferentiable, - nullptr) { - } - - // Constructor with no defaults. - ExtInfo(Representation Rep, bool IsNoEscape, bool Throws, - DifferentiabilityKind DiffKind, - const clang::Type *type) - : ExtInfo(((unsigned) Rep) - | (IsNoEscape ? NoEscapeMask : 0) - | (Throws ? ThrowsMask : 0) - | (((unsigned)DiffKind << DifferentiabilityMaskOffset) - & DifferentiabilityMask), - ClangTypeInfo(type)) { - } - - bool isNoEscape() const { return Bits & NoEscapeMask; } - bool async() const { return Bits & AsyncMask; } - bool throws() const { return Bits & ThrowsMask; } - bool isDifferentiable() const { - return getDifferentiabilityKind() > - DifferentiabilityKind::NonDifferentiable; - } - DifferentiabilityKind getDifferentiabilityKind() const { - return DifferentiabilityKind((Bits & DifferentiabilityMask) >> - DifferentiabilityMaskOffset); - } - Representation getRepresentation() const { - unsigned rawRep = Bits & RepresentationMask; - assert(rawRep <= unsigned(Representation::Last) - && "unexpected SIL representation"); - return Representation(rawRep); - } - - /// Get the underlying ClangTypeInfo value if it is not the default value. - Optional getClangTypeInfo() const { - return Other.empty() ? Optional() : Other; - } - - bool hasSelfParam() const { - switch (getSILRepresentation()) { - case SILFunctionTypeRepresentation::Thick: - case SILFunctionTypeRepresentation::Block: - case SILFunctionTypeRepresentation::Thin: - case SILFunctionTypeRepresentation::CFunctionPointer: - case SILFunctionTypeRepresentation::Closure: - return false; - case SILFunctionTypeRepresentation::ObjCMethod: - case SILFunctionTypeRepresentation::Method: - case SILFunctionTypeRepresentation::WitnessMethod: - return true; - } - - llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch."); - } - - /// True if the function representation carries context. - bool hasContext() const { - switch (getSILRepresentation()) { - case SILFunctionTypeRepresentation::Thick: - case SILFunctionTypeRepresentation::Block: - return true; - case SILFunctionTypeRepresentation::Thin: - case SILFunctionTypeRepresentation::Method: - case SILFunctionTypeRepresentation::ObjCMethod: - case SILFunctionTypeRepresentation::WitnessMethod: - case SILFunctionTypeRepresentation::CFunctionPointer: - case SILFunctionTypeRepresentation::Closure: - return false; - } - - llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch."); - } - - // Note that we don't have setters. That is by design, use - // the following with methods instead of mutating these objects. - LLVM_NODISCARD - ExtInfo withRepresentation(Representation Rep) const { - return ExtInfo((Bits & ~RepresentationMask) - | (unsigned)Rep, Other); - } - LLVM_NODISCARD - ExtInfo withNoEscape(bool NoEscape = true) const { - return ExtInfo(NoEscape ? (Bits | NoEscapeMask) : (Bits & ~NoEscapeMask), - Other); - } - LLVM_NODISCARD - ExtInfo withAsync(bool Async = true) const { - return ExtInfo(Async ? (Bits | AsyncMask) : (Bits & ~AsyncMask), - Other); - } - LLVM_NODISCARD - ExtInfo withThrows(bool Throws = true) const { - return ExtInfo(Throws ? (Bits | ThrowsMask) : (Bits & ~ThrowsMask), - Other); - } - LLVM_NODISCARD - ExtInfo withClangFunctionType(const clang::Type *type) const { - return ExtInfo(Bits, ClangTypeInfo(type)); - } - LLVM_NODISCARD - ExtInfo - withDifferentiabilityKind(DifferentiabilityKind differentiability) const { - return ExtInfo( - (Bits & ~DifferentiabilityMask) | - ((unsigned)differentiability << DifferentiabilityMaskOffset), - Other); - } - - std::pair getFuncAttrKey() const { - return std::make_pair(Bits, Other.type); - } - - /// Put a SIL representation in the ExtInfo. - /// - /// SIL type lowering transiently generates AST function types with SIL - /// representations. However, they shouldn't persist in the AST, and - /// don't need to be parsed, printed, or serialized. - ExtInfo withSILRepresentation(SILFunctionTypeRepresentation Rep) const { - return ExtInfo((Bits & ~RepresentationMask) - | (unsigned)Rep, Other); - } - - SILFunctionTypeRepresentation getSILRepresentation() const { - unsigned rawRep = Bits & RepresentationMask; - return SILFunctionTypeRepresentation(rawRep); - } - - bool operator==(ExtInfo Other) const { - return Bits == Other.Bits; - } - bool operator!=(ExtInfo Other) const { - return Bits != Other.Bits; - } - }; - protected: /// Create an AnyFunctionType. /// /// Subclasses are responsible for storing and retrieving the - /// ExtInfo::ClangTypeInfo value if one is present. + /// 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.Bits; + Bits.AnyFunctionType.ExtInfoBits = Info.getBits(); Bits.AnyFunctionType.HasClangTypeInfo = Info.getClangTypeInfo().hasValue(); 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.Bits - && "Bits were dropped!"); - static_assert(ExtInfo::NumMaskBits == NumAFTExtInfoBits, - "ExtInfo and AnyFunctionTypeBitfields must agree on bit size"); + assert(Bits.AnyFunctionType.ExtInfoBits == Info.getBits() && + "Bits were dropped!"); + static_assert( + ASTExtInfoBuilder::NumMaskBits == NumAFTExtInfoBits, + "ExtInfo and AnyFunctionTypeBitfields must agree on bit size"); } public: @@ -3224,15 +2911,15 @@ class AnyFunctionType : public TypeBase { GenericSignature getOptGenericSignature() const; - bool hasClangFunctionType() const { + bool hasClangTypeInfo() const { return Bits.AnyFunctionType.HasClangTypeInfo; } - const clang::Type *getClangFunctionType() const; - const clang::Type *getCanonicalClangFunctionType() const; + ClangTypeInfo getClangTypeInfo() const; + ClangTypeInfo getCanonicalClangTypeInfo() const; ExtInfo getExtInfo() const { - return ExtInfo(Bits.AnyFunctionType.ExtInfoBits, getClangFunctionType()); + return ExtInfo(Bits.AnyFunctionType.ExtInfoBits, getClangTypeInfo()); } /// Get the canonical ExtInfo for the function type. @@ -3241,10 +2928,12 @@ class AnyFunctionType : public TypeBase { /// In the future, we will always use the canonical clang function type. ExtInfo getCanonicalExtInfo(bool useClangFunctionType) const { return ExtInfo(Bits.AnyFunctionType.ExtInfoBits, - useClangFunctionType ? getCanonicalClangFunctionType() - : nullptr); + useClangFunctionType ? getCanonicalClangTypeInfo() + : ClangTypeInfo()); } + bool hasSameExtInfoAs(const AnyFunctionType *otherFn); + /// Get the representation of the function type. Representation getRepresentation() const { return getExtInfo().getRepresentation(); @@ -3418,6 +3107,7 @@ class AnyFunctionType : public TypeBase { }; BEGIN_CAN_TYPE_WRAPPER(AnyFunctionType, Type) using ExtInfo = AnyFunctionType::ExtInfo; + using ExtInfoBuilder = AnyFunctionType::ExtInfoBuilder; using CanParamArrayRef = AnyFunctionType::CanParamArrayRef; static CanAnyFunctionType get(CanGenericSignature signature, @@ -3445,19 +3135,20 @@ inline AnyFunctionType::CanYield AnyFunctionType::Yield::getCanonical() const { /// /// For example: /// let x : (Float, Int) -> Int -class FunctionType final : public AnyFunctionType, - public llvm::FoldingSetNode, - private llvm::TrailingObjects { +class FunctionType final + : public AnyFunctionType, + public llvm::FoldingSetNode, + private llvm::TrailingObjects { friend TrailingObjects; - + size_t numTrailingObjects(OverloadToken) const { return getNumParams(); } - size_t numTrailingObjects(OverloadToken) const { - return hasClangFunctionType() ? 1 : 0; + size_t numTrailingObjects(OverloadToken) const { + return hasClangTypeInfo() ? 1 : 0; } public: @@ -3470,12 +3161,13 @@ class FunctionType final : public AnyFunctionType, return {getTrailingObjects(), getNumParams()}; } - const clang::Type *getClangFunctionType() const { - if (!hasClangFunctionType()) - return nullptr; - auto *type = getTrailingObjects()->type; - assert(type && "If the pointer was null, we shouldn't have stored it."); - return type; + ClangTypeInfo getClangTypeInfo() const { + if (!hasClangTypeInfo()) + return ClangTypeInfo(); + auto *info = getTrailingObjects(); + assert(!info->empty() && + "If the ClangTypeInfo was empty, we shouldn't have stored it."); + return *info; } void Profile(llvm::FoldingSetNodeID &ID) { @@ -4185,10 +3877,12 @@ namespace Lowering { /// This type is defined by the AST library because it must be capable /// of appearing in secondary positions, e.g. within tuple and /// function parameter and result types. -class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, - private llvm::TrailingObjects { +class SILFunctionType final + : public TypeBase, + public llvm::FoldingSetNode, + private llvm::TrailingObjects { friend TrailingObjects; size_t numTrailingObjects(OverloadToken) const { @@ -4208,177 +3902,15 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, } size_t numTrailingObjects(OverloadToken) const { - return size_t(hasPatternSubstitutions()) - + size_t(hasInvocationSubstitutions()); + return size_t(hasPatternSubstitutions()) + + size_t(hasInvocationSubstitutions()); } public: - using Language = SILFunctionLanguage; - using Representation = SILFunctionTypeRepresentation; - - /// A class which abstracts out some details necessary for - /// making a call. - class ExtInfo { - // If bits are added or removed, then TypeBase::SILFunctionTypeBits - // and NumMaskBits must be updated, and they must match. - - // |representation|pseudogeneric|noescape|differentiability| - // | 0 .. 3 | 4 | 5 | 6 .. 7 | - // - enum : unsigned { - RepresentationMask = 0xF << 0, - PseudogenericMask = 1 << 4, - NoEscapeMask = 1 << 5, - DifferentiabilityMaskOffset = 6, - DifferentiabilityMask = 0x3 << DifferentiabilityMaskOffset, - NumMaskBits = 8 - }; - - unsigned Bits; // Naturally sized for speed. - - class ClangTypeInfo { - friend ExtInfo; - friend class SILFunctionType; - - // Invariant: The FunctionType is canonical. - // We store a clang::FunctionType * instead of a clang::CanQualType to - // avoid depending on the Clang AST in this header. - const clang::FunctionType *ClangFunctionType; - - bool empty() const { return !ClangFunctionType; } - ClangTypeInfo(const clang::FunctionType *type) : ClangFunctionType(type) {} - - public: - /// Analog of AnyFunctionType::ExtInfo::ClangTypeInfo::printType. - void printType(ClangModuleLoader *cml, llvm::raw_ostream &os) const; - }; - - ClangTypeInfo Other; - - ExtInfo(unsigned Bits, ClangTypeInfo Other) : Bits(Bits), Other(Other) {} - - friend class SILFunctionType; - public: - // Constructor with all defaults. - ExtInfo() : Bits(0), Other(ClangTypeInfo(nullptr)) { } - - // Constructor for polymorphic type. - ExtInfo(Representation rep, bool isPseudogeneric, bool isNoEscape, - DifferentiabilityKind diffKind, - const clang::FunctionType *type) - : ExtInfo(((unsigned) rep) - | (isPseudogeneric ? PseudogenericMask : 0) - | (isNoEscape ? NoEscapeMask : 0) - | (((unsigned)diffKind << DifferentiabilityMaskOffset) - & DifferentiabilityMask), - ClangTypeInfo(type)) { - } - - static ExtInfo getThin() { - return ExtInfo(Representation::Thin, false, false, - DifferentiabilityKind::NonDifferentiable, nullptr); - } - - /// Is this function pseudo-generic? A pseudo-generic function - /// is not permitted to dynamically depend on its type arguments. - bool isPseudogeneric() const { return Bits & PseudogenericMask; } - - // Is this function guaranteed to be no-escape by the type system? - bool isNoEscape() const { return Bits & NoEscapeMask; } - - bool isDifferentiable() const { - return getDifferentiabilityKind() != - DifferentiabilityKind::NonDifferentiable; - } - - DifferentiabilityKind getDifferentiabilityKind() const { - return DifferentiabilityKind((Bits & DifferentiabilityMask) >> - DifferentiabilityMaskOffset); - } - - /// What is the abstract representation of this function value? - Representation getRepresentation() const { - return Representation(Bits & RepresentationMask); - } - Language getLanguage() const { - return getSILFunctionLanguage(getRepresentation()); - } - - /// Get the underlying ClangTypeInfo value if it is not the default value. - Optional getClangTypeInfo() const { - return Other.empty() ? Optional() : Other; - } - - bool hasSelfParam() const { - switch (getRepresentation()) { - case Representation::Thick: - case Representation::Block: - case Representation::Thin: - case Representation::CFunctionPointer: - case Representation::Closure: - return false; - case Representation::ObjCMethod: - case Representation::Method: - case Representation::WitnessMethod: - return true; - } - - llvm_unreachable("Unhandled Representation in switch."); - } - - /// True if the function representation carries context. - bool hasContext() const { - switch (getRepresentation()) { - case Representation::Thick: - case Representation::Block: - return true; - case Representation::Thin: - case Representation::CFunctionPointer: - case Representation::ObjCMethod: - case Representation::Method: - case Representation::WitnessMethod: - case Representation::Closure: - return false; - } - - llvm_unreachable("Unhandled Representation in switch."); - } - - // Note that we don't have setters. That is by design, use - // the following with methods instead of mutating these objects. - ExtInfo withRepresentation(Representation Rep) const { - return ExtInfo((Bits & ~RepresentationMask) - | (unsigned)Rep, Other); - } - ExtInfo withIsPseudogeneric(bool isPseudogeneric = true) const { - return ExtInfo(isPseudogeneric - ? (Bits | PseudogenericMask) - : (Bits & ~PseudogenericMask), - Other); - } - ExtInfo withNoEscape(bool NoEscape = true) const { - return ExtInfo(NoEscape ? (Bits | NoEscapeMask) : (Bits & ~NoEscapeMask), - Other); - } - ExtInfo - withDifferentiabilityKind(DifferentiabilityKind differentiability) const { - return ExtInfo( - (Bits & ~DifferentiabilityMask) | - ((unsigned)differentiability << DifferentiabilityMaskOffset), - Other); - } - - std::pair getFuncAttrKey() const { - return std::make_pair(Bits, Other.ClangFunctionType); - } - - bool operator==(ExtInfo Other) const { - return Bits == Other.Bits; - } - bool operator!=(ExtInfo Other) const { - return Bits != Other.Bits; - } - }; + using ExtInfo = SILExtInfo; + using ExtInfoBuilder = SILExtInfoBuilder; + using Language = SILExtInfoBuilder::Language; + using Representation = SILExtInfoBuilder::Representation; private: unsigned NumParameters; @@ -4763,7 +4295,9 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, return WitnessMethodConformance; } - const clang::FunctionType *getClangFunctionType() const; + ClangTypeInfo getClangTypeInfo() const; + + bool hasSameExtInfoAs(const SILFunctionType *otherFn); /// Given that `this` is a `@differentiable` or `@differentiable(linear)` /// function type, returns an `IndexSubset` corresponding to the @@ -4911,7 +4445,7 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, CanGenericSignature transposeFunctionGenericSignature = nullptr); ExtInfo getExtInfo() const { - return ExtInfo(Bits.SILFunctionType.ExtInfoBits, getClangFunctionType()); + return ExtInfo(Bits.SILFunctionType.ExtInfoBits, getClangTypeInfo()); } /// Returns the language-level calling convention of the function. diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h index 42db005ea3bdf..65776fb4ab641 100644 --- a/include/swift/SIL/TypeLowering.h +++ b/include/swift/SIL/TypeLowering.h @@ -57,7 +57,8 @@ CanAnyFunctionType adjustFunctionType(CanAnyFunctionType type, /// Change the given function type's representation. inline CanAnyFunctionType adjustFunctionType(CanAnyFunctionType t, SILFunctionType::Representation rep) { - auto extInfo = t->getExtInfo().withSILRepresentation(rep); + auto extInfo = + t->getExtInfo().intoBuilder().withSILRepresentation(rep).build(); return adjustFunctionType(t, extInfo); } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 9c249574aa6f5..e0212c3812926 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -3113,10 +3113,9 @@ FunctionType *FunctionType::get(ArrayRef params, return funcTy; } - Optional clangTypeInfo = info.getClangTypeInfo(); + Optional clangTypeInfo = info.getClangTypeInfo(); - size_t allocSize = - totalSizeToAlloc( + size_t allocSize = totalSizeToAlloc( params.size(), clangTypeInfo.hasValue() ? 1 : 0); void *mem = ctx.Allocate(allocSize, alignof(FunctionType), arena); @@ -3146,7 +3145,7 @@ FunctionType::FunctionType(ArrayRef params, getTrailingObjects()); auto clangTypeInfo = info.getClangTypeInfo(); if (clangTypeInfo.hasValue()) - *getTrailingObjects() = clangTypeInfo.getValue(); + *getTrailingObjects() = clangTypeInfo.getValue(); } void GenericFunctionType::Profile(llvm::FoldingSetNodeID &ID, @@ -3239,11 +3238,6 @@ ArrayRef GenericFunctionType::getRequirements() const { return Signature->getRequirements(); } -void SILFunctionType::ExtInfo::ClangTypeInfo::printType( - ClangModuleLoader *cml, llvm::raw_ostream &os) const { - cml->printClangType(ClangFunctionType, os); -} - void SILFunctionType::Profile( llvm::FoldingSetNodeID &id, GenericSignature genericParams, @@ -3302,13 +3296,14 @@ SILFunctionType::SILFunctionType( WitnessMethodConformance(witnessMethodConformance) { Bits.SILFunctionType.HasErrorResult = errorResult.hasValue(); - Bits.SILFunctionType.ExtInfoBits = ext.Bits; + Bits.SILFunctionType.ExtInfoBits = ext.getBits(); Bits.SILFunctionType.HasClangTypeInfo = false; Bits.SILFunctionType.HasPatternSubs = (bool) patternSubs; Bits.SILFunctionType.HasInvocationSubs = (bool) invocationSubs; // The use of both assert() and static_assert() below is intentional. - assert(Bits.SILFunctionType.ExtInfoBits == ext.Bits && "Bits were dropped!"); - static_assert(ExtInfo::NumMaskBits == NumSILExtInfoBits, + assert(Bits.SILFunctionType.ExtInfoBits == ext.getBits() && + "Bits were dropped!"); + static_assert(SILExtInfoBuilder::NumMaskBits == NumSILExtInfoBits, "ExtInfo and SILFunctionTypeBitfields must agree on bit size"); Bits.SILFunctionType.CoroutineKind = unsigned(coroutineKind); NumParameters = params.size(); @@ -4446,7 +4441,6 @@ Type ASTContext::getBridgedToObjC(const DeclContext *dc, Type type, const clang::Type * ASTContext::getClangFunctionType(ArrayRef params, Type resultTy, - FunctionType::ExtInfo incompleteExtInfo, FunctionTypeRepresentation trueRep) { auto &impl = getImpl(); if (!impl.Converter) { diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 329bb830fa91f..49ebc14091a3c 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -400,19 +400,16 @@ Type ASTBuilder::createFunctionType( || representation == FunctionTypeRepresentation::Block) && !flags.isEscaping(); - FunctionType::ExtInfo incompleteExtInfo( - FunctionTypeRepresentation::Swift, - noescape, flags.throws(), diffKind, /*clangFunctionType*/nullptr); - const clang::Type *clangFunctionType = nullptr; if (representation == FunctionTypeRepresentation::CFunctionPointer) clangFunctionType = Ctx.getClangFunctionType(funcParams, output, - incompleteExtInfo, representation); - auto einfo = incompleteExtInfo.withRepresentation(representation) - .withAsync(flags.async()) - .withClangFunctionType(clangFunctionType); + auto einfo = + FunctionType::ExtInfoBuilder(representation, noescape, flags.throws(), + diffKind, clangFunctionType) + .withAsync(flags.async()) + .build(); return FunctionType::get(funcParams, output, einfo); } @@ -532,9 +529,10 @@ Type ASTBuilder::createImplFunctionType( } // [TODO: Store-SIL-Clang-type] - auto einfo = SILFunctionType::ExtInfo(representation, flags.isPseudogeneric(), - !flags.isEscaping(), diffKind, - /*clangFunctionType*/ nullptr); + auto einfo = SILExtInfoBuilder(representation, flags.isPseudogeneric(), + !flags.isEscaping(), diffKind, + /*clangFunctionType*/ nullptr) + .build(); llvm::SmallVector funcParams; llvm::SmallVector funcYields; diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index ec90fd41200eb..2387fe822bf88 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -3760,10 +3760,10 @@ namespace { OS << "\n"; Indent += 2; - if (auto *cty = T->getClangFunctionType()) { + if (!T->getClangTypeInfo().empty()) { std::string s; llvm::raw_string_ostream os(s); - cty->dump(os); + T->getClangTypeInfo().dump(os); printField("clang_type", os.str()); } printAnyFunctionParams(T->getParams(), "input"); diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index f0d427c582b63..70c74a09e5686 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -1036,22 +1036,23 @@ static ValueDecl *getAutoDiffApplyDerivativeFunction( fnParamGens.push_back(T); } // Generator for the first argument, i.e. the `@differentiable` function. - BuiltinFunctionBuilder::LambdaGenerator firstArgGen { - // Generator for the function type at the argument position, i.e. the - // function being differentiated. - [=, &fnParamGens](BuiltinFunctionBuilder &builder) -> Type { - FunctionType::ExtInfo ext; - auto extInfo = FunctionType::ExtInfo() - .withDifferentiabilityKind(DifferentiabilityKind::Normal) - .withNoEscape().withThrows(throws); - 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); - } - }; + BuiltinFunctionBuilder::LambdaGenerator firstArgGen{ + // Generator for the function type at the argument position, i.e. the + // function being differentiated. + [=, &fnParamGens](BuiltinFunctionBuilder &builder) -> Type { + auto extInfo = + FunctionType::ExtInfoBuilder() + .withDifferentiabilityKind(DifferentiabilityKind::Normal) + .withNoEscape() + .withThrows(throws) + .build(); + 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); + }}; // Eagerly build the type of the first arg, then use that to compute the type // of the result. auto *diffFnType = @@ -1106,9 +1107,12 @@ static ValueDecl *getAutoDiffApplyTransposeFunction( // function being differentiated. [=, &linearFnParamGens](BuiltinFunctionBuilder &builder) -> Type { FunctionType::ExtInfo ext; - auto extInfo = FunctionType::ExtInfo() - .withDifferentiabilityKind(DifferentiabilityKind::Linear) - .withNoEscape().withThrows(throws); + auto extInfo = + FunctionType::ExtInfoBuilder() + .withDifferentiabilityKind(DifferentiabilityKind::Linear) + .withNoEscape() + .withThrows(throws) + .build(); SmallVector params; for (auto ¶mGen : linearFnParamGens) params.push_back(FunctionType::Param(paramGen.build(builder))); @@ -1164,8 +1168,9 @@ static ValueDecl *getDifferentiableFunctionConstructor( for (auto ¶mGen : fnArgGens) params.push_back(FunctionType::Param(paramGen.build(builder))); return FunctionType::get(params, origResultGen.build(builder)) - ->withExtInfo( - FunctionType::ExtInfo(FunctionTypeRepresentation::Swift, throws)); + ->withExtInfo(FunctionType::ExtInfoBuilder( + FunctionTypeRepresentation::Swift, throws) + .build()); } }; @@ -1189,8 +1194,9 @@ static ValueDecl *getDifferentiableFunctionConstructor( {TupleTypeElt(origResultType, Context.Id_value), TupleTypeElt(differentialType, Context.Id_differential)}, Context); return FunctionType::get(params, jvpResultType) - ->withExtInfo( - FunctionType::ExtInfo(FunctionTypeRepresentation::Swift, throws)); + ->withExtInfo(FunctionType::ExtInfoBuilder( + FunctionTypeRepresentation::Swift, throws) + .build()); } }; @@ -1217,8 +1223,9 @@ static ValueDecl *getDifferentiableFunctionConstructor( {TupleTypeElt(origResultType, Context.Id_value), TupleTypeElt(pullbackType, Context.Id_pullback)}, Context); return FunctionType::get(params, vjpResultType) - ->withExtInfo( - FunctionType::ExtInfo(FunctionTypeRepresentation::Swift, throws)); + ->withExtInfo(FunctionType::ExtInfoBuilder( + FunctionTypeRepresentation::Swift, throws) + .build()); } }; @@ -1227,7 +1234,9 @@ static ValueDecl *getDifferentiableFunctionConstructor( auto origFnType = origFnGen.build(builder)->castTo(); return origFnType->withExtInfo( origFnType->getExtInfo() - .withDifferentiabilityKind(DifferentiabilityKind::Normal)); + .intoBuilder() + .withDifferentiabilityKind(DifferentiabilityKind::Normal) + .build()); } }; @@ -1266,8 +1275,9 @@ static ValueDecl *getLinearFunctionConstructor( for (auto ¶mGen : fnArgGens) params.push_back(FunctionType::Param(paramGen.build(builder))); return FunctionType::get(params, origResultGen.build(builder)) - ->withExtInfo( - FunctionType::ExtInfo(FunctionTypeRepresentation::Swift, throws)); + ->withExtInfo(FunctionType::ExtInfoBuilder( + FunctionTypeRepresentation::Swift, throws) + .build()); } }; @@ -1290,7 +1300,9 @@ static ValueDecl *getLinearFunctionConstructor( auto origFnType = origFnGen.build(builder)->castTo(); return origFnType->withExtInfo( origFnType->getExtInfo() - .withDifferentiabilityKind(DifferentiabilityKind::Linear)); + .intoBuilder() + .withDifferentiabilityKind(DifferentiabilityKind::Linear) + .build()); } }; @@ -1540,8 +1552,10 @@ static ValueDecl *getOnceOperation(ASTContext &Context, auto HandleTy = Context.TheRawPointerType; auto VoidTy = Context.TheEmptyTupleType; - auto Thin = FunctionType::ExtInfo(FunctionTypeRepresentation::CFunctionPointer, - /*throws*/ false); + auto Thin = + FunctionType::ExtInfoBuilder(FunctionTypeRepresentation::CFunctionPointer, + /*throws*/ false) + .build(); if (withContext) { auto ContextTy = Context.TheRawPointerType; auto ContextArg = FunctionType::Param(ContextTy); diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 07e999bac7ad1..71a1cfa05c1ea 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -44,6 +44,7 @@ add_swift_host_library(swiftAST STATIC DocComment.cpp Evaluator.cpp Expr.cpp + ExtInfo.cpp FineGrainedDependencies.cpp FineGrainedDependencyFormat.cpp FrontendSourceFileDepGraphFactory.cpp diff --git a/lib/AST/ClangTypeConverter.cpp b/lib/AST/ClangTypeConverter.cpp index a0c7e71393b7e..d4ccea512f069 100644 --- a/lib/AST/ClangTypeConverter.cpp +++ b/lib/AST/ClangTypeConverter.cpp @@ -572,7 +572,7 @@ clang::QualType ClangTypeConverter::visitEnumType(EnumType *type) { clang::QualType ClangTypeConverter::visitFunctionType(FunctionType *type) { // We must've already computed it before if applicable. - return clang::QualType(type->getClangFunctionType(), 0); + return clang::QualType(type->getClangTypeInfo().getType(), 0); } clang::QualType ClangTypeConverter::visitSILFunctionType(SILFunctionType *type) { diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index b3916373a69eb..62813a4d88b4e 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2576,10 +2576,11 @@ mapSignatureExtInfo(AnyFunctionType::ExtInfo info, bool topLevelFunction) { if (topLevelFunction) return AnyFunctionType::ExtInfo(); - return AnyFunctionType::ExtInfo() + return AnyFunctionType::ExtInfoBuilder() .withRepresentation(info.getRepresentation()) .withAsync(info.async()) - .withThrows(info.throws()); + .withThrows(info.throws()) + .build(); } /// Map a function's type to the type used for computing signatures, diff --git a/lib/AST/ExtInfo.cpp b/lib/AST/ExtInfo.cpp new file mode 100644 index 0000000000000..a75a3ff1d9f5e --- /dev/null +++ b/lib/AST/ExtInfo.cpp @@ -0,0 +1,93 @@ +//===--- ExtInfo.cpp - Extended information for function types ------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2020 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 ASTExtInfo, SILExtInfo and related classes. +// +//===----------------------------------------------------------------------===// + +#include "swift/AST/ClangModuleLoader.h" +#include "swift/AST/ExtInfo.h" + +#include "clang/AST/Type.h" + +namespace swift { + +// MARK: - ClangTypeInfo + +bool operator==(ClangTypeInfo lhs, ClangTypeInfo rhs) { + if (lhs.type == rhs.type) + return true; + if (lhs.type && rhs.type) + return lhs.type->getCanonicalTypeInternal() == + rhs.type->getCanonicalTypeInternal(); + return false; +} + +ClangTypeInfo ClangTypeInfo::getCanonical() const { + if (!type) + return ClangTypeInfo(); + return ClangTypeInfo(type->getCanonicalTypeInternal().getTypePtr()); +} + +void ClangTypeInfo::printType(ClangModuleLoader *cml, + llvm::raw_ostream &os) const { + cml->printClangType(type, os); +} + +void ClangTypeInfo::dump(llvm::raw_ostream &os) const { + if (type) { + type->dump(os); + } else { + os << ""; + } +} + +// MARK: - ASTExtInfoBuilder + +void ASTExtInfoBuilder::assertIsFunctionType(const clang::Type *type) { +#ifndef NDEBUG + if (!(type->isFunctionPointerType() || type->isBlockPointerType() || + type->isFunctionReferenceType())) { + SmallString<256> buf; + llvm::raw_svector_ostream os(buf); + os << "Expected a Clang function type wrapped in a pointer type or " + << "a block pointer type but found:\n"; + type->dump(os); + llvm_unreachable(os.str().data()); + } +#endif + return; +} + +void ASTExtInfoBuilder::checkInvariants() const { + // TODO: Add validation checks here while making sure things don't blow up. +} + +// MARK: - ASTExtInfo + +ASTExtInfo ASTExtInfoBuilder::build() const { + checkInvariants(); + return ASTExtInfo(*this); +} + +// MARK: - SILExtInfoBuilder + +void SILExtInfoBuilder::checkInvariants() const { + // TODO: Add validation checks here while making sure things don't blow up. +} + +SILExtInfo SILExtInfoBuilder::build() const { + checkInvariants(); + return SILExtInfo(*this); +} + +} // end namespace swift diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 5396f55bf2c2e..0cf4acb296fae 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1243,9 +1243,7 @@ CanType TypeBase::computeCanonicalType() { getCanonicalParams(funcTy, genericSig, canParams); auto resultTy = funcTy->getResult()->getCanonicalType(genericSig); - bool useClangFunctionType = - resultTy->getASTContext().LangOpts.UseClangFunctionTypes; - auto extInfo = funcTy->getCanonicalExtInfo(useClangFunctionType); + auto extInfo = funcTy->getCanonicalExtInfo(useClangTypes(resultTy)); if (genericSig) { Result = GenericFunctionType::get(genericSig, canParams, resultTy, extInfo); @@ -1783,7 +1781,7 @@ class IsBindableVisitor CanType visitFunctionType(FunctionType *func, CanType subst, ArchetypeType*, ArrayRef) { if (auto substFunc = dyn_cast(subst)) { - if (func->getExtInfo() != substFunc->getExtInfo()) + if (!func->hasSameExtInfoAs(substFunc)) return CanType(); if (func->getParams().size() != substFunc->getParams().size()) @@ -1822,7 +1820,7 @@ class IsBindableVisitor CanType visitSILFunctionType(SILFunctionType *func, CanType subst, ArchetypeType*, ArrayRef) { if (auto substFunc = dyn_cast(subst)) { - if (func->getExtInfo() != substFunc->getExtInfo()) + if (!func->hasSameExtInfoAs(substFunc)) return CanType(); if (func->getInvocationGenericSignature() @@ -2618,7 +2616,7 @@ static bool matchesFunctionType(CanAnyFunctionType fn1, CanAnyFunctionType fn2, if (!ext2.isNoEscape()) ext1 = ext1.withNoEscape(false); } - if (ext1 != ext2) + if (!ext1.isEqualTo(ext2, useClangTypes(fn1))) return false; return paramsAndResultMatch(); @@ -3411,47 +3409,33 @@ Type ProtocolCompositionType::get(const ASTContext &C, return build(C, CanTypes, HasExplicitAnyObject); } -void AnyFunctionType::ExtInfo::ClangTypeInfo::printType( - ClangModuleLoader *cml, llvm::raw_ostream &os) const { - cml->printClangType(type, os); -} - -void -AnyFunctionType::ExtInfo::assertIsFunctionType(const clang::Type *type) { -#ifndef NDEBUG - if (!(type->isFunctionPointerType() || type->isBlockPointerType() || - type->isFunctionReferenceType())) { - SmallString<256> buf; - llvm::raw_svector_ostream os(buf); - os << "Expected a Clang function type wrapped in a pointer type or " - << "a block pointer type but found:\n"; - type->dump(os); - llvm_unreachable(os.str().data()); - } -#endif - return; -} - -const clang::Type *AnyFunctionType::getClangFunctionType() const { +ClangTypeInfo AnyFunctionType::getClangTypeInfo() const { switch (getKind()) { case TypeKind::Function: - return cast(this)->getClangFunctionType(); + return cast(this)->getClangTypeInfo(); case TypeKind::GenericFunction: // Generic functions do not have C types. - return nullptr; + return ClangTypeInfo(); default: llvm_unreachable("Illegal type kind for AnyFunctionType."); } } -const clang::Type *AnyFunctionType::getCanonicalClangFunctionType() const { - auto *ty = getClangFunctionType(); - return ty ? ty->getCanonicalTypeInternal().getTypePtr() : nullptr; +ClangTypeInfo AnyFunctionType::getCanonicalClangTypeInfo() const { + return getClangTypeInfo().getCanonical(); +} + +bool AnyFunctionType::hasSameExtInfoAs(const AnyFunctionType *otherFn) { + return getExtInfo().isEqualTo(otherFn->getExtInfo(), useClangTypes(this)); } // [TODO: Store-SIL-Clang-type] -const clang::FunctionType *SILFunctionType::getClangFunctionType() const { - return nullptr; +ClangTypeInfo SILFunctionType::getClangTypeInfo() const { + return ClangTypeInfo(); +} + +bool SILFunctionType::hasSameExtInfoAs(const SILFunctionType *otherFn) { + return getExtInfo().isEqualTo(otherFn->getExtInfo(), useClangTypes(this)); } FunctionType * @@ -5099,8 +5083,11 @@ AnyFunctionType *AnyFunctionType::getWithoutDifferentiability() const { param.getParameterFlags().withNoDerivative(false)); newParams.push_back(newParam); } - auto nonDiffExtInfo = getExtInfo() - .withDifferentiabilityKind(DifferentiabilityKind::NonDifferentiable); + auto nonDiffExtInfo = + getExtInfo() + .intoBuilder() + .withDifferentiabilityKind(DifferentiabilityKind::NonDifferentiable) + .build(); if (isa(this)) return FunctionType::get(newParams, getResult(), nonDiffExtInfo); assert(isa(this)); diff --git a/lib/AST/TypeJoinMeet.cpp b/lib/AST/TypeJoinMeet.cpp index a1af594424502..a5609f8b669fb 100644 --- a/lib/AST/TypeJoinMeet.cpp +++ b/lib/AST/TypeJoinMeet.cpp @@ -314,7 +314,7 @@ CanType TypeJoin::visitFunctionType(CanType second) { auto secondExtInfo = secondFnTy->getExtInfo(); // FIXME: Properly handle these attributes. - if (firstExtInfo != secondExtInfo) + if (!firstExtInfo.isEqualTo(secondExtInfo, useClangTypes(First))) return Unimplemented; if (!AnyFunctionType::equalParams(firstFnTy->getParams(), diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 206f8879baa5f..20e0c42a3bcf4 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -167,11 +167,13 @@ namespace { return {FunctionType::get( funcTy->getParams(), funcTy->getResult(), funcTy->getExtInfo() + .intoBuilder() .withRepresentation( AnyFunctionType::Representation::CFunctionPointer) - .withClangFunctionType(&type)), + .withClangFunctionType(&type) + .build()), type.isReferenceType() ? ImportHint::None - : ImportHint::CFunctionPointer}; + : ImportHint::CFunctionPointer}; } static ImportResult importOverAlignedFunctionPointerLikeType( diff --git a/lib/SIL/IR/Bridging.cpp b/lib/SIL/IR/Bridging.cpp index c5760f1805eda..053a00de71c7a 100644 --- a/lib/SIL/IR/Bridging.cpp +++ b/lib/SIL/IR/Bridging.cpp @@ -205,9 +205,12 @@ Type TypeConverter::getLoweredCBridgedType(AbstractionPattern pattern, bridging, /*non-optional*/false); - return FunctionType::get(newParams, newResult, - funTy->getExtInfo().withSILRepresentation( - SILFunctionType::Representation::Block)); + return FunctionType::get( + newParams, newResult, + funTy->getExtInfo() + .intoBuilder() + .withSILRepresentation(SILFunctionType::Representation::Block) + .build()); } } } diff --git a/lib/SIL/IR/SILBuilder.cpp b/lib/SIL/IR/SILBuilder.cpp index 037bfc9b3e6ec..c925cc83bb737 100644 --- a/lib/SIL/IR/SILBuilder.cpp +++ b/lib/SIL/IR/SILBuilder.cpp @@ -62,11 +62,14 @@ SILType SILBuilder::getPartialApplyResultType( auto params = FTI->getParameters(); auto newParams = params.slice(0, params.size() - argCount); - auto extInfo = FTI->getExtInfo() - .withRepresentation(SILFunctionType::Representation::Thick) - .withIsPseudogeneric(false); + auto extInfoBuilder = + FTI->getExtInfo() + .intoBuilder() + .withRepresentation(SILFunctionType::Representation::Thick) + .withIsPseudogeneric(false); if (onStack) - extInfo = extInfo.withNoEscape(); + extInfoBuilder = extInfoBuilder.withNoEscape(); + auto extInfo = extInfoBuilder.build(); // If the original method has an @unowned_inner_pointer return, the partial // application thunk will lifetime-extend 'self' for us, converting the diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index b18402a549b7c..e681d599d4712 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -268,7 +268,8 @@ SILFunctionType::getWithDifferentiability(DifferentiabilityKind kind, ? SILResultDifferentiability::DifferentiableOrNotApplicable : SILResultDifferentiability::NotDifferentiable)); } - auto newExtInfo = getExtInfo().withDifferentiabilityKind(kind); + auto newExtInfo = + getExtInfo().intoBuilder().withDifferentiabilityKind(kind).build(); return get(getInvocationGenericSignature(), newExtInfo, getCoroutineKind(), getCalleeConvention(), newParameters, getYields(), newResults, getOptionalErrorResult(), getPatternSubstitutions(), @@ -279,8 +280,11 @@ SILFunctionType::getWithDifferentiability(DifferentiabilityKind kind, CanSILFunctionType SILFunctionType::getWithoutDifferentiability() { if (!isDifferentiable()) return CanSILFunctionType(this); - auto nondiffExtInfo = getExtInfo().withDifferentiabilityKind( - DifferentiabilityKind::NonDifferentiable); + auto nondiffExtInfo = + getExtInfo() + .intoBuilder() + .withDifferentiabilityKind(DifferentiabilityKind::NonDifferentiable) + .build(); SmallVector newParams; for (auto ¶m : getParameters()) newParams.push_back(param.getWithDifferentiability( @@ -928,7 +932,7 @@ static CanType getKnownType(Optional &cacheSlot, ASTContext &C, CanAnyFunctionType Lowering::adjustFunctionType(CanAnyFunctionType t, AnyFunctionType::ExtInfo extInfo) { - if (t->getExtInfo() == extInfo) + if (t->getExtInfo().isEqualTo(extInfo, useClangTypes(t))) return t; return CanAnyFunctionType(t->withExtInfo(extInfo)); } @@ -939,7 +943,8 @@ Lowering::adjustFunctionType(CanSILFunctionType type, SILFunctionType::ExtInfo extInfo, ParameterConvention callee, ProtocolConformanceRef witnessMethodConformance) { - if (type->getExtInfo() == extInfo && type->getCalleeConvention() == callee && + if (type->getExtInfo().isEqualTo(extInfo, useClangTypes(type)) && + type->getCalleeConvention() == callee && type->getWitnessMethodConformanceOrInvalid() == witnessMethodConformance) return type; @@ -961,7 +966,7 @@ SILFunctionType::getWithRepresentation(Representation repr) { CanSILFunctionType SILFunctionType::getWithExtInfo(ExtInfo newExt) { auto oldExt = getExtInfo(); - if (newExt == oldExt) + if (newExt.isEqualTo(oldExt, useClangTypes(this))) return CanSILFunctionType(this); auto calleeConvention = @@ -2106,11 +2111,13 @@ static CanSILFunctionType getSILFunctionType( // NOTE: SILFunctionType::ExtInfo doesn't track everything that // AnyFunctionType::ExtInfo tracks. For example: 'throws' or 'auto-closure' - auto silExtInfo = SILFunctionType::ExtInfo() - .withRepresentation(extInfo.getSILRepresentation()) - .withIsPseudogeneric(pseudogeneric) - .withNoEscape(extInfo.isNoEscape()) - .withDifferentiabilityKind(extInfo.getDifferentiabilityKind()); + auto silExtInfo = + SILFunctionType::ExtInfoBuilder() + .withRepresentation(extInfo.getSILRepresentation()) + .withIsPseudogeneric(pseudogeneric) + .withNoEscape(extInfo.isNoEscape()) + .withDifferentiabilityKind(extInfo.getDifferentiabilityKind()) + .build(); // Build the substituted generic signature we extracted. SubstitutionMap substitutions; @@ -3716,7 +3723,7 @@ class SILTypeSubstituter : // pseudogeneric. auto extInfo = origType->getExtInfo(); if (!shouldSubstituteOpaqueArchetypes) - extInfo = extInfo.withIsPseudogeneric(false); + extInfo = extInfo.intoBuilder().withIsPseudogeneric(false).build(); auto genericSig = shouldSubstituteOpaqueArchetypes ? origType->getInvocationGenericSignature() @@ -3962,7 +3969,7 @@ TypeConverter::getBridgedFunctionType(AbstractionPattern pattern, case SILFunctionTypeRepresentation::Closure: case SILFunctionTypeRepresentation::WitnessMethod: { // No bridging needed for native functions. - if (t->getExtInfo() == extInfo) + if (t->getExtInfo().isEqualTo(extInfo, useClangTypes(t))) return t; return CanAnyFunctionType::get(genericSig, t.getParams(), t.getResult(), extInfo); diff --git a/lib/SIL/IR/TypeLowering.cpp b/lib/SIL/IR/TypeLowering.cpp index d07445700f9e2..ae437faaeed6e 100644 --- a/lib/SIL/IR/TypeLowering.cpp +++ b/lib/SIL/IR/TypeLowering.cpp @@ -2150,15 +2150,16 @@ static CanAnyFunctionType getDestructorInterfaceType(DestructorDecl *dd, assert((!isForeign || isDeallocating) && "There are no foreign destroying destructors"); - auto extInfo = - AnyFunctionType::ExtInfo(FunctionType::Representation::Thin, - /*throws*/ false); + auto extInfoBuilder = + AnyFunctionType::ExtInfoBuilder(FunctionType::Representation::Thin, + /*throws*/ false); if (isForeign) - extInfo = extInfo - .withSILRepresentation(SILFunctionTypeRepresentation::ObjCMethod); + extInfoBuilder = extInfoBuilder.withSILRepresentation( + SILFunctionTypeRepresentation::ObjCMethod); else - extInfo = extInfo - .withSILRepresentation(SILFunctionTypeRepresentation::Method); + extInfoBuilder = extInfoBuilder.withSILRepresentation( + SILFunctionTypeRepresentation::Method); + auto extInfo = extInfoBuilder.build(); auto &C = dd->getASTContext(); CanType resultTy = (isDeallocating @@ -2184,11 +2185,14 @@ static CanAnyFunctionType getIVarInitDestroyerInterfaceType(ClassDecl *cd, auto resultType = (isDestroyer ? TupleType::getEmpty(cd->getASTContext()) : classType); - auto extInfo = AnyFunctionType::ExtInfo(FunctionType::Representation::Thin, - /*throws*/ false); - extInfo = extInfo - .withSILRepresentation(isObjC? SILFunctionTypeRepresentation::ObjCMethod - : SILFunctionTypeRepresentation::Method); + auto extInfoBuilder = + AnyFunctionType::ExtInfoBuilder(FunctionType::Representation::Thin, + /*throws*/ false); + auto extInfo = extInfoBuilder + .withSILRepresentation( + isObjC ? SILFunctionTypeRepresentation::ObjCMethod + : SILFunctionTypeRepresentation::Method) + .build(); resultType = CanFunctionType::get({}, resultType, extInfo); auto sig = cd->getGenericSignature(); @@ -2210,8 +2214,10 @@ getFunctionInterfaceTypeWithCaptures(TypeConverter &TC, auto closure = *constant.getAnyFunctionRef(); auto genericSig = getEffectiveGenericSignature(closure, captureInfo); - auto innerExtInfo = AnyFunctionType::ExtInfo(FunctionType::Representation::Thin, - funcType->throws()); + auto innerExtInfo = + AnyFunctionType::ExtInfoBuilder(FunctionType::Representation::Thin, + funcType->throws()) + .build(); return CanAnyFunctionType::get( getCanonicalSignatureOrNull(genericSig), diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 8bf94cf5d4913..70d2a8d7ad752 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -3714,10 +3714,14 @@ class SILVerifier : public SILVerifierBase { auto adjustedOperandExtInfo = opFTy->getExtInfo() + .intoBuilder() .withRepresentation(SILFunctionType::Representation::Thick) - .withNoEscape(resFTy->isNoEscape()); - require(adjustedOperandExtInfo == resFTy->getExtInfo(), - "operand and result of thin_to_think_function must agree in particulars"); + .withNoEscape(resFTy->isNoEscape()) + .build(); + require(adjustedOperandExtInfo.isEqualTo(resFTy->getExtInfo(), + useClangTypes(opFTy)), + "operand and result of thin_to_think_function must agree in " + "particulars"); } void checkThickToObjCMetatypeInst(ThickToObjCMetatypeInst *TTOCI) { diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index 2e8b3b80947ee..cd36b343f0e58 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -411,12 +411,13 @@ SILGenModule::getKeyPathProjectionCoroutine(bool isReadAccess, : ParameterConvention::Indirect_In_Guaranteed }, }; - auto extInfo = SILFunctionType::ExtInfo( - SILFunctionTypeRepresentation::Thin, - /*pseudogeneric*/ false, - /*non-escaping*/ false, - DifferentiabilityKind::NonDifferentiable, - /*clangFunctionType*/ nullptr); + auto extInfo = + SILFunctionType::ExtInfoBuilder(SILFunctionTypeRepresentation::Thin, + /*pseudogeneric*/ false, + /*non-escaping*/ false, + DifferentiabilityKind::NonDifferentiable, + /*clangFunctionType*/ nullptr) + .build(); auto functionTy = SILFunctionType::get(sig, extInfo, SILCoroutineKind::YieldOnce, diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index a0ff0494b71f5..7b1adef612fa1 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -131,8 +131,11 @@ getDynamicMethodLoweredType(SILModule &M, SILDeclRef constant, CanAnyFunctionType substMemberTy) { assert(constant.isForeign); - auto objcFormalTy = substMemberTy.withExtInfo(substMemberTy->getExtInfo() - .withSILRepresentation(SILFunctionTypeRepresentation::ObjCMethod)); + auto objcFormalTy = substMemberTy.withExtInfo( + substMemberTy->getExtInfo() + .intoBuilder() + .withSILRepresentation(SILFunctionTypeRepresentation::ObjCMethod) + .build()); return SILType::getPrimitiveObjectType( M.Types.getUncachedSILFunctionTypeForConstant( TypeExpansionContext::minimal(), constant, objcFormalTy)); diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index fbff1a5b02d71..7eedc3b1975fa 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -574,7 +574,7 @@ ManagedValue SILGenFunction::emitFuncToBlock(SILLocation loc, // context. Currently we don't capture anything directly into a block but a // Swift closure, but that's totally dumb. if (genericSig) - extInfo = extInfo.withIsPseudogeneric(); + extInfo = extInfo.intoBuilder().withIsPseudogeneric().build(); } auto invokeTy = SILFunctionType::get( diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index e185ce31bf751..d9acdc516f6ac 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -690,20 +690,18 @@ void SILGenFunction::emitArtificialTopLevel(Decl *mainDecl) { SILParameterInfo(argv->getType().getASTType(), ParameterConvention::Direct_Unowned), }; - auto NSApplicationMainType = SILFunctionType::get(nullptr, - SILFunctionType::ExtInfo() - // Should be C calling convention, but NSApplicationMain - // has an overlay to fix the type of argv. - .withRepresentation(SILFunctionType::Representation::Thin), - SILCoroutineKind::None, - ParameterConvention::Direct_Unowned, - argTypes, - /*yields*/ {}, - SILResultInfo(argc->getType().getASTType(), - ResultConvention::Unowned), - /*error result*/ None, - SubstitutionMap(), SubstitutionMap(), - getASTContext()); + auto NSApplicationMainType = SILFunctionType::get( + nullptr, + SILFunctionType::ExtInfoBuilder() + // Should be C calling convention, but NSApplicationMain + // has an overlay to fix the type of argv. + .withRepresentation(SILFunctionType::Representation::Thin) + .build(), + SILCoroutineKind::None, ParameterConvention::Direct_Unowned, argTypes, + /*yields*/ {}, + SILResultInfo(argc->getType().getASTType(), ResultConvention::Unowned), + /*error result*/ None, SubstitutionMap(), SubstitutionMap(), + getASTContext()); SILGenFunctionBuilder builder(SGM); auto NSApplicationMainFn = builder.getOrCreateFunction( diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp index d78dacc61df28..0ee11d74f6439 100644 --- a/lib/SILGen/SILGenPoly.cpp +++ b/lib/SILGen/SILGenPoly.cpp @@ -3099,11 +3099,12 @@ CanSILFunctionType SILGenFunction::buildThunkType( // This may inherit @noescape from the expectedType. The @noescape attribute // is only stripped when using this type to materialize a new decl. - auto extInfo = expectedType->getExtInfo() - .withRepresentation(SILFunctionType::Representation::Thin); + auto extInfoBuilder = + expectedType->getExtInfo().intoBuilder().withRepresentation( + SILFunctionType::Representation::Thin); if (withoutActuallyEscaping) - extInfo = extInfo.withNoEscape(false); + extInfoBuilder = extInfoBuilder.withNoEscape(false); // Does the thunk type involve archetypes other than opened existentials? bool hasArchetypes = false; @@ -3185,7 +3186,7 @@ CanSILFunctionType SILGenFunction::buildThunkType( // pseudogeneric, since we have no way to pass generic parameters. if (genericSig) if (F.getLoweredFunctionType()->isPseudogeneric()) - extInfo = extInfo.withIsPseudogeneric(); + extInfoBuilder = extInfoBuilder.withIsPseudogeneric(); // Add the function type as the parameter. auto contextConvention = @@ -3243,14 +3244,12 @@ CanSILFunctionType SILGenFunction::buildThunkType( } // The type of the thunk function. - return SILFunctionType::get(genericSig, extInfo, - expectedType->getCoroutineKind(), - ParameterConvention::Direct_Unowned, - interfaceParams, interfaceYields, - interfaceResults, interfaceErrorResult, - expectedType->getPatternSubstitutions(), - SubstitutionMap(), - getASTContext()); + return SILFunctionType::get( + genericSig, extInfoBuilder.build(), expectedType->getCoroutineKind(), + ParameterConvention::Direct_Unowned, interfaceParams, interfaceYields, + interfaceResults, interfaceErrorResult, + expectedType->getPatternSubstitutions(), SubstitutionMap(), + getASTContext()); } static ManagedValue createPartialApplyOfThunk(SILGenFunction &SGF, @@ -3477,8 +3476,9 @@ static CanSILFunctionType buildWithoutActuallyEscapingThunkType( CanSILFunctionType &escapingType, GenericEnvironment *&genericEnv, SubstitutionMap &interfaceSubs, CanType &dynamicSelfType) { - assert(escapingType->getExtInfo() == - noEscapingType->getExtInfo().withNoEscape(false)); + assert(escapingType->getExtInfo().isEqualTo( + noEscapingType->getExtInfo().withNoEscape(false), + useClangTypes(escapingType))); CanType inputSubstType, outputSubstType; auto type = SGF.buildThunkType(noEscapingType, escapingType, @@ -3540,8 +3540,9 @@ SILGenFunction::createWithoutActuallyEscapingClosure( auto noEscapingFnSubstTy = noEscapingFunctionValue.getType() .castTo(); // TODO: maybe this should use a more explicit instruction. - assert(escapingFnSubstTy->getExtInfo() == noEscapingFnSubstTy->getExtInfo() - .withNoEscape(false)); + assert(escapingFnSubstTy->getExtInfo().isEqualTo( + noEscapingFnSubstTy->getExtInfo().withNoEscape(false), + useClangTypes(escapingFnSubstTy))); // Apply function type substitutions, since the code sequence for a thunk // doesn't vary with function representation. @@ -4131,12 +4132,13 @@ ManagedValue Transform::transformFunction(ManagedValue fn, } // We do not, conversion is trivial. - auto expectedEI = expectedFnType->getExtInfo(); + auto expectedEI = expectedFnType->getExtInfo().intoBuilder(); auto newEI = expectedEI.withRepresentation(fnType->getRepresentation()) .withNoEscape(fnType->getRepresentation() == SILFunctionType::Representation::Thick ? fnType->isNoEscape() - : expectedFnType->isNoEscape()); + : expectedFnType->isNoEscape()) + .build(); auto newFnType = adjustFunctionType(expectedFnType, newEI, fnType->getCalleeConvention(), fnType->getWitnessMethodConformanceOrInvalid()); diff --git a/lib/SILOptimizer/Differentiation/Thunk.cpp b/lib/SILOptimizer/Differentiation/Thunk.cpp index ce7f3955d1792..820805fff06d9 100644 --- a/lib/SILOptimizer/Differentiation/Thunk.cpp +++ b/lib/SILOptimizer/Differentiation/Thunk.cpp @@ -129,13 +129,14 @@ CanSILFunctionType buildThunkType(SILFunction *fn, // - Building a reabstraction thunk type. // - Building an index subset thunk type, where the expected type has context // (i.e. is `@convention(thick)`). - auto extInfo = expectedType->getExtInfo(); + auto extInfoBuilder = expectedType->getExtInfo().intoBuilder(); if (thunkKind == DifferentiationThunkKind::Reabstraction || - extInfo.hasContext()) { - extInfo = extInfo.withRepresentation(SILFunctionType::Representation::Thin); + extInfoBuilder.hasContext()) { + extInfoBuilder = extInfoBuilder.withRepresentation( + SILFunctionType::Representation::Thin); } if (withoutActuallyEscaping) - extInfo = extInfo.withNoEscape(false); + extInfoBuilder = extInfoBuilder.withNoEscape(false); // Does the thunk type involve archetypes other than opened existentials? bool hasArchetypes = false; @@ -191,7 +192,7 @@ CanSILFunctionType buildThunkType(SILFunction *fn, // pseudogeneric, since we have no way to pass generic parameters. if (genericSig) if (fn->getLoweredFunctionType()->isPseudogeneric()) - extInfo = extInfo.withIsPseudogeneric(); + extInfoBuilder = extInfoBuilder.withIsPseudogeneric(); // Add the function type as the parameter. auto contextConvention = @@ -241,7 +242,7 @@ CanSILFunctionType buildThunkType(SILFunction *fn, // The type of the thunk function. return SILFunctionType::get( - genericSig, extInfo, expectedType->getCoroutineKind(), + genericSig, extInfoBuilder.build(), expectedType->getCoroutineKind(), ParameterConvention::Direct_Unowned, interfaceParams, interfaceYields, interfaceResults, interfaceErrorResult, expectedType->getPatternSubstitutions(), SubstitutionMap(), diff --git a/lib/SILOptimizer/Mandatory/Differentiation.cpp b/lib/SILOptimizer/Mandatory/Differentiation.cpp index 458ce21214e19..5156ffac9e792 100644 --- a/lib/SILOptimizer/Mandatory/Differentiation.cpp +++ b/lib/SILOptimizer/Mandatory/Differentiation.cpp @@ -872,9 +872,7 @@ static void emitFatalError(ADContext &context, SILFunction *f, ResultConvention::Unowned); // Fatal error function must have type `@convention(thin) () -> Never`. auto fatalErrorFnType = SILFunctionType::get( - /*genericSig*/ nullptr, - SILFunctionType::ExtInfo().withRepresentation( - SILFunctionTypeRepresentation::Thin), + /*genericSig*/ nullptr, SILFunctionType::ExtInfo::getThin(), SILCoroutineKind::None, ParameterConvention::Direct_Unowned, {}, /*interfaceYields*/ {}, neverResultInfo, /*interfaceErrorResults*/ None, {}, {}, context.getASTContext()); @@ -1020,8 +1018,10 @@ static SILValue promoteCurryThunkApplicationToDifferentiableFunction( // Construct new curry thunk type with `@differentiable` function // result. auto diffResultFnTy = resultFnTy->getWithExtInfo( - resultFnTy->getExtInfo().withDifferentiabilityKind( - DifferentiabilityKind::Normal)); + resultFnTy->getExtInfo() + .intoBuilder() + .withDifferentiabilityKind(DifferentiabilityKind::Normal) + .build()); auto newThunkResult = thunkResult.getWithInterfaceType(diffResultFnTy); auto thunkType = SILFunctionType::get( thunkTy->getSubstGenericSignature(), thunkTy->getExtInfo(), diff --git a/lib/SILOptimizer/Transforms/Outliner.cpp b/lib/SILOptimizer/Transforms/Outliner.cpp index fbf76e306f85d..e052a6b000f3c 100644 --- a/lib/SILOptimizer/Transforms/Outliner.cpp +++ b/lib/SILOptimizer/Transforms/Outliner.cpp @@ -295,11 +295,12 @@ CanSILFunctionType BridgedProperty::getOutlinedFunctionType(SILModule &M) { Results.push_back(SILResultInfo( switchInfo.Br->getArg(0)->getType().getASTType(), ResultConvention::Owned)); - auto ExtInfo = - SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin, - /*pseudogeneric*/ false, /*noescape*/ false, - DifferentiabilityKind::NonDifferentiable, - /*clangFunctionType*/ nullptr); + auto ExtInfo = SILFunctionType::ExtInfoBuilder( + SILFunctionType::Representation::Thin, + /*pseudogeneric*/ false, /*noescape*/ false, + DifferentiabilityKind::NonDifferentiable, + /*clangFunctionType*/ nullptr) + .build(); auto FunctionType = SILFunctionType::get( nullptr, ExtInfo, SILCoroutineKind::None, ParameterConvention::Direct_Unowned, Parameters, /*yields*/ {}, @@ -1176,12 +1177,13 @@ CanSILFunctionType ObjCMethodCall::getOutlinedFunctionType(SILModule &M) { ++OrigSigIdx; } - auto ExtInfo = SILFunctionType::ExtInfo( - SILFunctionType::Representation::Thin, - /*pseudogeneric*/ false, - /*noescape*/ false, - DifferentiabilityKind::NonDifferentiable, - /*clangFunctionType*/ nullptr); + auto ExtInfo = + SILFunctionType::ExtInfoBuilder(SILFunctionType::Representation::Thin, + /*pseudogeneric*/ false, + /*noescape*/ false, + DifferentiabilityKind::NonDifferentiable, + /*clangFunctionType*/ nullptr) + .build(); SmallVector Results; // If we don't have a bridged return we changed from @autoreleased to @owned diff --git a/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp b/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp index aa187b7d15815..a8f823e584d5a 100644 --- a/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp +++ b/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp @@ -84,10 +84,11 @@ class BugReducerTester : public SILFunctionTransform { SILResultInfo(EmptyTupleCanType, ResultConvention::Unowned)); auto FuncType = SILFunctionType::get( nullptr, - SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin, - false /*isPseudoGeneric*/, false /*noescape*/, - DifferentiabilityKind::NonDifferentiable, - nullptr /*clangFunctionType*/), + SILFunctionType::ExtInfoBuilder( + SILFunctionType::Representation::Thin, false /*isPseudoGeneric*/, + false /*noescape*/, DifferentiabilityKind::NonDifferentiable, + nullptr /*clangFunctionType*/) + .build(), SILCoroutineKind::None, ParameterConvention::Direct_Unowned, ArrayRef(), ArrayRef(), ResultInfoArray, None, SubstitutionMap(), SubstitutionMap(), diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index e75039217c3bb..6c13997547aaa 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -6732,7 +6732,9 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType, maybeDiagnoseUnsupportedDifferentiableConversion(cs, expr, toFunc); if (!isFromDifferentiable && isToDifferentiable) { auto newEI = - fromEI.withDifferentiabilityKind(toEI.getDifferentiabilityKind()); + fromEI.intoBuilder() + .withDifferentiabilityKind(toEI.getDifferentiabilityKind()) + .build(); fromFunc = FunctionType::get(toFunc->getParams(), fromFunc->getResult()) ->withExtInfo(newEI) ->castTo(); diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 134c7165aeaf0..69defe079fac7 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1906,23 +1906,27 @@ static std::pair getTypeOfReferenceWithSpecialTypeCheckingSemantics( CS.getConstraintLocator(locator, ConstraintLocator::FunctionResult), TVO_CanBindToNoEscape); FunctionType::Param arg(escapeClosure); - auto bodyClosure = FunctionType::get(arg, result, - FunctionType::ExtInfo(FunctionType::Representation::Swift, - /*noescape*/ true, - /*throws*/ true, - DifferentiabilityKind::NonDifferentiable, - /*clangFunctionType*/ nullptr)); + auto bodyClosure = FunctionType::get( + arg, result, + FunctionType::ExtInfoBuilder(FunctionType::Representation::Swift, + /*noescape*/ true, + /*throws*/ true, + DifferentiabilityKind::NonDifferentiable, + /*clangFunctionType*/ nullptr) + .build()); FunctionType::Param args[] = { FunctionType::Param(noescapeClosure), FunctionType::Param(bodyClosure, CS.getASTContext().getIdentifier("do")), }; - auto refType = FunctionType::get(args, result, - FunctionType::ExtInfo(FunctionType::Representation::Swift, - /*noescape*/ false, - /*throws*/ true, - DifferentiabilityKind::NonDifferentiable, - /*clangFunctionType*/ nullptr)); + auto refType = FunctionType::get( + args, result, + FunctionType::ExtInfoBuilder(FunctionType::Representation::Swift, + /*noescape*/ false, + /*throws*/ true, + DifferentiabilityKind::NonDifferentiable, + /*clangFunctionType*/ nullptr) + .build()); return {refType, refType}; } case DeclTypeCheckingSemantics::OpenExistential: { @@ -1941,22 +1945,26 @@ static std::pair getTypeOfReferenceWithSpecialTypeCheckingSemantics( CS.getConstraintLocator(locator, ConstraintLocator::FunctionResult), TVO_CanBindToNoEscape); FunctionType::Param bodyArgs[] = {FunctionType::Param(openedTy)}; - auto bodyClosure = FunctionType::get(bodyArgs, result, - FunctionType::ExtInfo(FunctionType::Representation::Swift, - /*noescape*/ true, - /*throws*/ true, - DifferentiabilityKind::NonDifferentiable, - /*clangFunctionType*/ nullptr)); + auto bodyClosure = FunctionType::get( + bodyArgs, result, + FunctionType::ExtInfoBuilder(FunctionType::Representation::Swift, + /*noescape*/ true, + /*throws*/ true, + DifferentiabilityKind::NonDifferentiable, + /*clangFunctionType*/ nullptr) + .build()); FunctionType::Param args[] = { FunctionType::Param(existentialTy), FunctionType::Param(bodyClosure, CS.getASTContext().getIdentifier("do")), }; - auto refType = FunctionType::get(args, result, - FunctionType::ExtInfo(FunctionType::Representation::Swift, - /*noescape*/ false, - /*throws*/ true, - DifferentiabilityKind::NonDifferentiable, - /*clangFunctionType*/ nullptr)); + auto refType = FunctionType::get( + args, result, + FunctionType::ExtInfoBuilder(FunctionType::Representation::Swift, + /*noescape*/ false, + /*throws*/ true, + DifferentiabilityKind::NonDifferentiable, + /*clangFunctionType*/ nullptr) + .build()); return {refType, refType}; } } diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index 574358ebff137..09aab47d101ed 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -1585,7 +1585,7 @@ class ExportabilityChecker : public DeclVisitor { // types first. Action walkToTypePost(Type T) override { if (auto fnType = T->getAs()) { - if (auto clangType = fnType->getClangFunctionType()) { + if (auto clangType = fnType->getClangTypeInfo().getType()) { auto loader = T->getASTContext().getClangModuleLoader(); // Serialization will serialize the sugared type if it can, // but we need the canonical type to be serializable or else diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 9fd55a32cd845..d8fb606a5c388 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -2277,7 +2277,7 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const { auto sig = AFD->getGenericSignature(); bool hasSelf = AFD->hasImplicitSelfDecl(); - AnyFunctionType::ExtInfo info; + AnyFunctionType::ExtInfoBuilder infoBuilder; // Result Type resultTy; @@ -2297,12 +2297,13 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const { SmallVector argTy; AFD->getParameters()->getParams(argTy); - info = info.withAsync(AFD->hasAsync()); + infoBuilder = infoBuilder.withAsync(AFD->hasAsync()); // 'throws' only applies to the innermost function. - info = info.withThrows(AFD->hasThrows()); + infoBuilder = infoBuilder.withThrows(AFD->hasThrows()); // Defer bodies must not escape. if (auto fd = dyn_cast(D)) - info = info.withNoEscape(fd->isDeferBody()); + infoBuilder = infoBuilder.withNoEscape(fd->isDeferBody()); + auto info = infoBuilder.build(); if (sig && !hasSelf) { funcTy = GenericFunctionType::get(sig, argTy, resultTy, info); diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index b8538587ab864..9be81b3cdb722 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -35,7 +35,7 @@ static void adjustFunctionTypeForOverride(Type &type) { auto fnType = type->castTo(); auto extInfo = fnType->getExtInfo(); extInfo = extInfo.withThrows(false); - if (fnType->getExtInfo() != extInfo) + if (!fnType->getExtInfo().isEqualTo(extInfo, useClangTypes(fnType))) type = fnType->withExtInfo(extInfo); } diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index d614afacfc02e..758456e6e676a 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -2214,9 +2214,10 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs, // Resolve the function type directly with these attributes. // [TODO: Store-SIL-Clang-type] - SILFunctionType::ExtInfo extInfo(rep, attrs.has(TAK_pseudogeneric), - attrs.has(TAK_noescape), diffKind, - nullptr); + auto extInfo = SILFunctionType::ExtInfoBuilder( + rep, attrs.has(TAK_pseudogeneric), + attrs.has(TAK_noescape), diffKind, nullptr) + .build(); ty = resolveSILFunctionType(fnRepr, options, coroutineKind, extInfo, calleeConvention, witnessMethodProtocol); @@ -2672,20 +2673,20 @@ Type TypeResolver::resolveASTFunctionType( } } - FunctionType::ExtInfo incompleteExtInfo(FunctionTypeRepresentation::Swift, - noescape, repr->throws(), diffKind, - /*clangFunctionType*/nullptr); + FunctionType::ExtInfoBuilder extInfoBuilder( + FunctionTypeRepresentation::Swift, noescape, repr->throws(), diffKind, + /*clangFunctionType*/ nullptr); const clang::Type *clangFnType = parsedClangFunctionType; if (representation == AnyFunctionType::Representation::CFunctionPointer && !clangFnType) clangFnType = Context.getClangFunctionType( - params, outputTy, incompleteExtInfo, - AnyFunctionType::Representation::CFunctionPointer); + params, outputTy, AnyFunctionType::Representation::CFunctionPointer); - auto extInfo = incompleteExtInfo.withRepresentation(representation) - .withAsync(repr->async()) - .withClangFunctionType(clangFnType); + auto extInfo = extInfoBuilder.withRepresentation(representation) + .withAsync(repr->async()) + .withClangFunctionType(clangFnType) + .build(); // Diagnose a couple of things that we can parse in SIL mode but we don't // allow in formal types. diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 8197ba44e96e4..2d4226bf83bb6 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -5026,9 +5026,10 @@ class TypeDeserializer { clangFunctionType = loadedClangType.get(); } - auto info = FunctionType::ExtInfo(*representation, noescape, throws, - *diffKind, clangFunctionType) - .withAsync(async); + auto info = FunctionType::ExtInfoBuilder(*representation, noescape, throws, + *diffKind, clangFunctionType) + .withAsync(async) + .build(); auto resultTy = MF.getTypeChecked(resultID); if (!resultTy) @@ -5413,8 +5414,10 @@ class TypeDeserializer { MF.fatal(); } - SILFunctionType::ExtInfo extInfo(*representation, pseudogeneric, noescape, - *diffKind, clangFunctionType); + auto extInfo = + SILFunctionType::ExtInfoBuilder(*representation, pseudogeneric, + noescape, *diffKind, clangFunctionType) + .build(); // Process the coroutine kind. auto coroutineKind = getActualSILCoroutineKind(rawCoroutineKind); diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 3b64d9322e085..cdbd34d191d59 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -4128,7 +4128,7 @@ class Serializer::TypeSerializer : public TypeVisitor { using namespace decls_block; auto resultType = S.addTypeRef(fnTy->getResult()); - auto clangType = S.addClangTypeRef(fnTy->getClangFunctionType()); + auto clangType = S.addClangTypeRef(fnTy->getClangTypeInfo().getType()); unsigned abbrCode = S.DeclTypeAbbrCodes[FunctionTypeLayout::Code]; FunctionTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, @@ -4216,7 +4216,7 @@ class Serializer::TypeSerializer : public TypeVisitor { S.addSubstitutionMapRef(fnTy->getInvocationSubstitutions()); auto patternSubstMapID = S.addSubstitutionMapRef(fnTy->getPatternSubstitutions()); - auto clangTypeID = S.addClangTypeRef(fnTy->getClangFunctionType()); + auto clangTypeID = S.addClangTypeRef(fnTy->getClangTypeInfo().getType()); auto stableCoroutineKind = getRawStableSILCoroutineKind(fnTy->getCoroutineKind());