diff --git a/cmake/modules/SwiftSource.cmake b/cmake/modules/SwiftSource.cmake index e30e01d3fdb..09f525c19a8 100644 --- a/cmake/modules/SwiftSource.cmake +++ b/cmake/modules/SwiftSource.cmake @@ -229,6 +229,7 @@ function(_compile_swift_files # The standard library and overlays are always built resiliently. if(SWIFTFILE_IS_STDLIB) list(APPEND swift_flags "-enable-library-evolution") + list(APPEND swift_flags "-Xfrontend" "-enable-ownership-stripping-after-serialization") endif() if(SWIFT_STDLIB_USE_NONATOMIC_RC) diff --git a/include/swift/AST/ASTTypeIDZone.def b/include/swift/AST/ASTTypeIDZone.def index d410ed16b64..1c893425054 100644 --- a/include/swift/AST/ASTTypeIDZone.def +++ b/include/swift/AST/ASTTypeIDZone.def @@ -27,6 +27,7 @@ SWIFT_TYPEID(CtorInitializerKind) SWIFT_TYPEID(ResilienceExpansion) SWIFT_TYPEID_NAMED(Optional, PropertyWrapperMutability) SWIFT_TYPEID_NAMED(CustomAttr *, CustomAttr) +SWIFT_TYPEID_NAMED(OperatorDecl *, OperatorDecl) SWIFT_TYPEID_NAMED(TypeAliasDecl *, TypeAliasDecl) SWIFT_TYPEID(AncestryFlags) SWIFT_TYPEID_NAMED(GenericSignature *, GenericSignature) diff --git a/include/swift/AST/ASTTypeIDs.h b/include/swift/AST/ASTTypeIDs.h index 5c1df4540ed..ae0668b98db 100644 --- a/include/swift/AST/ASTTypeIDs.h +++ b/include/swift/AST/ASTTypeIDs.h @@ -36,10 +36,8 @@ class Type; struct TypePair; enum class AncestryFlags : uint8_t; -#define SWIFT_AST_TYPEID_ZONE 1 - // Define the AST type zone (zone 1) -#define SWIFT_TYPEID_ZONE SWIFT_AST_TYPEID_ZONE +#define SWIFT_TYPEID_ZONE AST #define SWIFT_TYPEID_HEADER "swift/AST/ASTTypeIDZone.def" #include "swift/Basic/DefineTypeIDZone.h" diff --git a/include/swift/AST/AccessRequests.h b/include/swift/AST/AccessRequests.h index 1a34a0baadc..6f66639cd9a 100644 --- a/include/swift/AST/AccessRequests.h +++ b/include/swift/AST/AccessRequests.h @@ -97,24 +97,21 @@ public: void cacheResult(DefaultAndMax value) const; }; -/// The zone number for access-control requests. -#define SWIFT_ACCESS_REQUESTS_TYPEID_ZONE 11 - -#define SWIFT_TYPEID_ZONE SWIFT_ACCESS_REQUESTS_TYPEID_ZONE +#define SWIFT_TYPEID_ZONE AccessControl #define SWIFT_TYPEID_HEADER "swift/AST/AccessTypeIDZone.def" #include "swift/Basic/DefineTypeIDZone.h" #undef SWIFT_TYPEID_ZONE #undef SWIFT_TYPEID_HEADER // Set up reporting of evaluated requests. -#define SWIFT_TYPEID(RequestType) \ +#define SWIFT_REQUEST(Zone, RequestType) \ template<> \ inline void reportEvaluatedRequest(UnifiedStatsReporter &stats, \ const RequestType &request) { \ ++stats.getFrontendCounters().RequestType; \ } #include "swift/AST/AccessTypeIDZone.def" -#undef SWIFT_TYPEID +#undef SWIFT_REQUEST } // end namespace swift diff --git a/include/swift/AST/AccessTypeIDZone.def b/include/swift/AST/AccessTypeIDZone.def index e75df4eff11..ee3079a4e47 100644 --- a/include/swift/AST/AccessTypeIDZone.def +++ b/include/swift/AST/AccessTypeIDZone.def @@ -14,6 +14,7 @@ // TypeID zone, for use with the TypeID template. // //===----------------------------------------------------------------------===// -SWIFT_TYPEID(AccessLevelRequest) -SWIFT_TYPEID(SetterAccessLevelRequest) -SWIFT_TYPEID(DefaultAndMaxAccessLevelRequest) + +SWIFT_REQUEST(AccessControl, AccessLevelRequest) +SWIFT_REQUEST(AccessControl, DefaultAndMaxAccessLevelRequest) +SWIFT_REQUEST(AccessControl, SetterAccessLevelRequest) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 6893c5e1427..0a84d3ec6a0 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -5926,7 +5926,6 @@ class FuncDecl : public AbstractFunctionDecl { TypeLoc FnRetType; - OperatorDecl *Operator = nullptr; OpaqueTypeDecl *OpaqueReturn = nullptr; protected: @@ -6073,13 +6072,7 @@ public: return cast_or_null(AbstractFunctionDecl::getOverriddenDecl()); } - OperatorDecl *getOperatorDecl() const { - return Operator; - } - void setOperatorDecl(OperatorDecl *o) { - assert(isOperator() && "can't set an OperatorDecl for a non-operator"); - Operator = o; - } + OperatorDecl *getOperatorDecl() const; OpaqueTypeDecl *getOpaqueResultTypeDecl() const { return OpaqueReturn; diff --git a/include/swift/AST/Evaluator.h b/include/swift/AST/Evaluator.h index bbf3c7e6ed4..9afe352603a 100644 --- a/include/swift/AST/Evaluator.h +++ b/include/swift/AST/Evaluator.h @@ -249,7 +249,7 @@ public: /// /// These functions will be called to evaluate any requests within that /// zone. - void registerRequestFunctions(uint8_t zoneID, + void registerRequestFunctions(Zone zone, ArrayRef functions); /// Evaluate the given request and produce its result, diff --git a/include/swift/AST/NameLookupRequests.h b/include/swift/AST/NameLookupRequests.h index 5226101e480..0025bd437c5 100644 --- a/include/swift/AST/NameLookupRequests.h +++ b/include/swift/AST/NameLookupRequests.h @@ -254,10 +254,7 @@ public: void cacheResult(DestructorDecl *value) const; }; -/// The zone number for name-lookup requests. -#define SWIFT_NAME_LOOKUP_REQUESTS_TYPEID_ZONE 9 - -#define SWIFT_TYPEID_ZONE SWIFT_NAME_LOOKUP_REQUESTS_TYPEID_ZONE +#define SWIFT_TYPEID_ZONE NameLookup #define SWIFT_TYPEID_HEADER "swift/AST/NameLookupTypeIDZone.def" #include "swift/Basic/DefineTypeIDZone.h" #undef SWIFT_TYPEID_ZONE @@ -268,14 +265,14 @@ template void reportEvaluatedRequest(UnifiedStatsReporter &stats, const Request &request); -#define SWIFT_TYPEID(RequestType) \ +#define SWIFT_REQUEST(Zone, RequestType) \ template<> \ inline void reportEvaluatedRequest(UnifiedStatsReporter &stats, \ const RequestType &request) { \ ++stats.getFrontendCounters().RequestType; \ } #include "swift/AST/NameLookupTypeIDZone.def" -#undef SWIFT_TYPEID +#undef SWIFT_REQUEST } // end namespace swift diff --git a/include/swift/AST/NameLookupTypeIDZone.def b/include/swift/AST/NameLookupTypeIDZone.def index c05125f2a89..f6398b78908 100644 --- a/include/swift/AST/NameLookupTypeIDZone.def +++ b/include/swift/AST/NameLookupTypeIDZone.def @@ -14,11 +14,13 @@ // TypeID zone, for use with the TypeID template. // //===----------------------------------------------------------------------===// -SWIFT_TYPEID(InheritedDeclsReferencedRequest) -SWIFT_TYPEID(UnderlyingTypeDeclsReferencedRequest) -SWIFT_TYPEID(SuperclassDeclRequest) -SWIFT_TYPEID(ExtendedNominalRequest) -SWIFT_TYPEID(SelfBoundsFromWhereClauseRequest) -SWIFT_TYPEID(TypeDeclsFromWhereClauseRequest) -SWIFT_TYPEID(CustomAttrNominalRequest) -SWIFT_TYPEID(GetDestructorRequest) + +SWIFT_REQUEST(NameLookup, CustomAttrNominalRequest) +SWIFT_REQUEST(NameLookup, ExtendedNominalRequest) +SWIFT_REQUEST(NameLookup, GetDestructorRequest) +SWIFT_REQUEST(NameLookup, InheritedDeclsReferencedRequest) +SWIFT_REQUEST(NameLookup, SelfBoundsFromWhereClauseRequest) +SWIFT_REQUEST(NameLookup, SuperclassDeclRequest) +SWIFT_REQUEST(NameLookup, TypeDeclsFromWhereClauseRequest) +SWIFT_REQUEST(NameLookup, UnderlyingTypeDeclsReferencedRequest) + diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index cbda2d4427d..621935eb60a 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -1067,7 +1067,6 @@ private: // Evaluation. llvm::Expected evaluate(Evaluator &evaluator, ClassDecl *value) const; - public: // Caching. bool isCached() const { return true; } @@ -1116,7 +1115,25 @@ private: // Evaluation. llvm::Expected evaluate(Evaluator &eval, ExtensionDecl *) const; +public: + // Caching. + bool isCached() const { return true; } +}; +class FunctionOperatorRequest : + public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + // Evaluation. + llvm::Expected + evaluate(Evaluator &evaluator, FuncDecl *value) const; + public: // Caching. bool isCached() const { return true; } @@ -1133,24 +1150,21 @@ inline bool AnyValue::Holder::equals(const HolderBase &other) const { void simple_display(llvm::raw_ostream &out, Type value); -/// The zone number for the type checker. -#define SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE 10 - -#define SWIFT_TYPEID_ZONE SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE +#define SWIFT_TYPEID_ZONE TypeChecker #define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def" #include "swift/Basic/DefineTypeIDZone.h" #undef SWIFT_TYPEID_ZONE #undef SWIFT_TYPEID_HEADER // Set up reporting of evaluated requests. -#define SWIFT_TYPEID(RequestType) \ +#define SWIFT_REQUEST(Zone, RequestType) \ template<> \ inline void reportEvaluatedRequest(UnifiedStatsReporter &stats, \ const RequestType &request) { \ ++stats.getFrontendCounters().RequestType; \ } #include "swift/AST/TypeCheckerTypeIDZone.def" -#undef SWIFT_TYPEID +#undef SWIFT_REQUEST } // end namespace swift diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 7ff2113b8be..b25b8bc29a2 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -14,48 +14,50 @@ // TypeID zone, for use with the TypeID template. // //===----------------------------------------------------------------------===// -SWIFT_TYPEID(InheritedTypeRequest) -SWIFT_TYPEID(SuperclassTypeRequest) -SWIFT_TYPEID(EnumRawTypeRequest) -SWIFT_TYPEID(OverriddenDeclsRequest) -SWIFT_TYPEID(IsObjCRequest) -SWIFT_TYPEID(InitKindRequest) -SWIFT_TYPEID(ProtocolRequiresClassRequest) -SWIFT_TYPEID(ExistentialConformsToSelfRequest) -SWIFT_TYPEID(ExistentialTypeSupportedRequest) -SWIFT_TYPEID(IsFinalRequest) -SWIFT_TYPEID(IsDynamicRequest) -SWIFT_TYPEID(RequirementRequest) -SWIFT_TYPEID(RequirementSignatureRequest) -SWIFT_TYPEID(DefaultDefinitionTypeRequest) -SWIFT_TYPEID(USRGenerationRequest) -SWIFT_TYPEID(StructuralTypeRequest) -SWIFT_TYPEID(ResilienceExpansionRequest) -SWIFT_TYPEID(DefaultTypeRequest) -SWIFT_TYPEID(MangleLocalTypeDeclRequest) -SWIFT_TYPEID(PropertyWrapperTypeInfoRequest) -SWIFT_TYPEID(PropertyWrapperMutabilityRequest) -SWIFT_TYPEID(AttachedPropertyWrappersRequest) -SWIFT_TYPEID(AttachedPropertyWrapperTypeRequest) -SWIFT_TYPEID(PropertyWrapperBackingPropertyTypeRequest) -SWIFT_TYPEID(PropertyWrapperBackingPropertyInfoRequest) -SWIFT_TYPEID(AttachedFunctionBuilderRequest) -SWIFT_TYPEID(FunctionBuilderTypeRequest) -SWIFT_TYPEID(SelfAccessKindRequest) -SWIFT_TYPEID(IsGetterMutatingRequest) -SWIFT_TYPEID(IsSetterMutatingRequest) -SWIFT_TYPEID(OpaqueReadOwnershipRequest) -SWIFT_TYPEID(LazyStoragePropertyRequest) -SWIFT_TYPEID(TypeCheckFunctionBodyUntilRequest) -SWIFT_TYPEID(StoredPropertiesRequest) -SWIFT_TYPEID(StoredPropertiesAndMissingMembersRequest) -SWIFT_TYPEID(StorageImplInfoRequest) -SWIFT_TYPEID(RequiresOpaqueAccessorsRequest) -SWIFT_TYPEID(RequiresOpaqueModifyCoroutineRequest) -SWIFT_TYPEID(IsAccessorTransparentRequest) -SWIFT_TYPEID(SynthesizeAccessorRequest) -SWIFT_TYPEID(EmittedMembersRequest) -SWIFT_TYPEID(IsImplicitlyUnwrappedOptionalRequest) -SWIFT_TYPEID(ClassAncestryFlagsRequest) -SWIFT_TYPEID(AbstractGenericSignatureRequest) -SWIFT_TYPEID(ExtendedTypeRequest) + +SWIFT_REQUEST(TypeChecker, AbstractGenericSignatureRequest) +SWIFT_REQUEST(TypeChecker, AttachedFunctionBuilderRequest) +SWIFT_REQUEST(TypeChecker, AttachedPropertyWrapperTypeRequest) +SWIFT_REQUEST(TypeChecker, AttachedPropertyWrappersRequest) +SWIFT_REQUEST(TypeChecker, ClassAncestryFlagsRequest) +SWIFT_REQUEST(TypeChecker, DefaultDefinitionTypeRequest) +SWIFT_REQUEST(TypeChecker, DefaultTypeRequest) +SWIFT_REQUEST(TypeChecker, EmittedMembersRequest) +SWIFT_REQUEST(TypeChecker, EnumRawTypeRequest) +SWIFT_REQUEST(TypeChecker, ExistentialConformsToSelfRequest) +SWIFT_REQUEST(TypeChecker, ExistentialTypeSupportedRequest) +SWIFT_REQUEST(TypeChecker, ExtendedTypeRequest) +SWIFT_REQUEST(TypeChecker, FunctionBuilderTypeRequest) +SWIFT_REQUEST(TypeChecker, FunctionOperatorRequest) +SWIFT_REQUEST(TypeChecker, InheritedTypeRequest) +SWIFT_REQUEST(TypeChecker, InitKindRequest) +SWIFT_REQUEST(TypeChecker, IsAccessorTransparentRequest) +SWIFT_REQUEST(TypeChecker, IsDynamicRequest) +SWIFT_REQUEST(TypeChecker, IsFinalRequest) +SWIFT_REQUEST(TypeChecker, IsGetterMutatingRequest) +SWIFT_REQUEST(TypeChecker, IsImplicitlyUnwrappedOptionalRequest) +SWIFT_REQUEST(TypeChecker, IsObjCRequest) +SWIFT_REQUEST(TypeChecker, IsSetterMutatingRequest) +SWIFT_REQUEST(TypeChecker, LazyStoragePropertyRequest) +SWIFT_REQUEST(TypeChecker, MangleLocalTypeDeclRequest) +SWIFT_REQUEST(TypeChecker, OpaqueReadOwnershipRequest) +SWIFT_REQUEST(TypeChecker, OverriddenDeclsRequest) +SWIFT_REQUEST(TypeChecker, PropertyWrapperBackingPropertyInfoRequest) +SWIFT_REQUEST(TypeChecker, PropertyWrapperBackingPropertyTypeRequest) +SWIFT_REQUEST(TypeChecker, PropertyWrapperMutabilityRequest) +SWIFT_REQUEST(TypeChecker, PropertyWrapperTypeInfoRequest) +SWIFT_REQUEST(TypeChecker, ProtocolRequiresClassRequest) +SWIFT_REQUEST(TypeChecker, RequirementRequest) +SWIFT_REQUEST(TypeChecker, RequirementSignatureRequest) +SWIFT_REQUEST(TypeChecker, RequiresOpaqueAccessorsRequest) +SWIFT_REQUEST(TypeChecker, RequiresOpaqueModifyCoroutineRequest) +SWIFT_REQUEST(TypeChecker, ResilienceExpansionRequest) +SWIFT_REQUEST(TypeChecker, SelfAccessKindRequest) +SWIFT_REQUEST(TypeChecker, StorageImplInfoRequest) +SWIFT_REQUEST(TypeChecker, StoredPropertiesAndMissingMembersRequest) +SWIFT_REQUEST(TypeChecker, StoredPropertiesRequest) +SWIFT_REQUEST(TypeChecker, StructuralTypeRequest) +SWIFT_REQUEST(TypeChecker, SuperclassTypeRequest) +SWIFT_REQUEST(TypeChecker, SynthesizeAccessorRequest) +SWIFT_REQUEST(TypeChecker, TypeCheckFunctionBodyUntilRequest) +SWIFT_REQUEST(TypeChecker, USRGenerationRequest) diff --git a/include/swift/Basic/DefineTypeIDZone.h b/include/swift/Basic/DefineTypeIDZone.h index 734505b5e02..1c9177c5979 100644 --- a/include/swift/Basic/DefineTypeIDZone.h +++ b/include/swift/Basic/DefineTypeIDZone.h @@ -33,9 +33,10 @@ // Define a TypeID where the type name and internal name are the same. #define SWIFT_TYPEID(Type) SWIFT_TYPEID_NAMED(Type, Type) +#define SWIFT_REQUEST(Zone, Type) SWIFT_TYPEID_NAMED(Type, Type) // First pass: put all of the names into an enum so we get values for them. -template<> struct TypeIDZoneTypes { +template<> struct TypeIDZoneTypes { enum Types : uint8_t { #define SWIFT_TYPEID_NAMED(Type, Name) Name, #define SWIFT_TYPEID_TEMPLATE1_NAMED(Template, Name, Param1, Arg1) Name, @@ -48,9 +49,10 @@ template<> struct TypeIDZoneTypes { // Second pass: create specializations of TypeID for these types. #define SWIFT_TYPEID_NAMED(Type, Name) \ template<> struct TypeID { \ - static const uint8_t zoneID = SWIFT_TYPEID_ZONE; \ + static const uint8_t zoneID = \ + static_cast(Zone::SWIFT_TYPEID_ZONE); \ static const uint8_t localID = \ - TypeIDZoneTypes::Name; \ + TypeIDZoneTypes::Name; \ \ static const uint64_t value = formTypeID(zoneID, localID); \ \ @@ -61,8 +63,8 @@ template<> struct TypeID { \ template struct TypeID> { \ private: \ static const uint64_t templateID = \ - formTypeID(SWIFT_TYPEID_ZONE, \ - TypeIDZoneTypes::Name); \ + formTypeID(static_cast(Zone::SWIFT_TYPEID_ZONE), \ + TypeIDZoneTypes::Name); \ \ public: \ static const uint64_t value = \ @@ -76,6 +78,9 @@ public: \ template const uint64_t TypeID>::value; #include SWIFT_TYPEID_HEADER + +#undef SWIFT_REQUEST + #undef SWIFT_TYPEID_NAMED #undef SWIFT_TYPEID_TEMPLATE1_NAMED diff --git a/include/swift/Basic/ImplementTypeIDZone.h b/include/swift/Basic/ImplementTypeIDZone.h index c943ad3f87b..ccd3a28ed0f 100644 --- a/include/swift/Basic/ImplementTypeIDZone.h +++ b/include/swift/Basic/ImplementTypeIDZone.h @@ -33,6 +33,7 @@ #endif // Define a TypeID where the type name and internal name are the same. +#define SWIFT_REQUEST(Zone, Type) SWIFT_TYPEID_NAMED(Type, Type) #define SWIFT_TYPEID(Type) SWIFT_TYPEID_NAMED(Type, Type) // Out-of-line definitions. @@ -43,6 +44,8 @@ #include SWIFT_TYPEID_HEADER +#undef SWIFT_REQUEST + #undef SWIFT_TYPEID_NAMED #undef SWIFT_TYPEID_TEMPLATE1_NAMED diff --git a/include/swift/Basic/Statistics.def b/include/swift/Basic/Statistics.def index 6107c5f7fb1..d062c1b8b50 100644 --- a/include/swift/Basic/Statistics.def +++ b/include/swift/Basic/Statistics.def @@ -268,13 +268,13 @@ FRONTEND_STATISTIC(Sema, NumUnloadedLazyIterableDeclContexts) /// Number of lookups into a module and its imports. /// All type check requests go into the Sema area. -#define SWIFT_TYPEID(NAME) FRONTEND_STATISTIC(Sema, NAME) +#define SWIFT_REQUEST(ZONE, NAME) FRONTEND_STATISTIC(Sema, NAME) #include "swift/AST/AccessTypeIDZone.def" #include "swift/AST/NameLookupTypeIDZone.def" #include "swift/AST/TypeCheckerTypeIDZone.def" #include "swift/Sema/IDETypeCheckingRequestIDZone.def" #include "swift/IDE/IDERequestIDZone.def" -#undef SWIFT_TYPEID +#undef SWIFT_REQUEST /// The next 10 statistics count 5 kinds of SIL entities present /// after the SILGen and SILOpt phases. The entities are functions, diff --git a/include/swift/Basic/TypeID.h b/include/swift/Basic/TypeID.h index a051a609033..0ea62a673e4 100644 --- a/include/swift/Basic/TypeID.h +++ b/include/swift/Basic/TypeID.h @@ -27,6 +27,22 @@ namespace swift { +enum class Zone : uint8_t { + C = 0, + AST = 1, + AccessControl = 11, + IDETypes = 136, + IDE = 137, + IDETypeChecking = 97, + NameLookup = 9, + TypeChecker = 10, + // N.B. This is not a formal zone and exists solely to support the unit tests. + ArithmeticEvaluator = 255, +}; + +static_assert(std::is_same::type, uint8_t>::value, + "underlying type is no longer uint8_t!"); + /// Form a unique 64-bit integer value describing the type `T`. /// /// This template needs to be specialized for every type that can @@ -37,7 +53,7 @@ struct TypeID; /// Template whose specializations provide the set of type IDs within a /// given zone. -template struct TypeIDZoneTypes; +template struct TypeIDZoneTypes; /// Form a type ID given a zone and type value. constexpr uint64_t formTypeID(uint8_t zone, uint8_t type) { @@ -45,7 +61,7 @@ constexpr uint64_t formTypeID(uint8_t zone, uint8_t type) { } // Define the C type zone (zone 0). -#define SWIFT_TYPEID_ZONE 0 +#define SWIFT_TYPEID_ZONE C #define SWIFT_TYPEID_HEADER "swift/Basic/CTypeIDZone.def" #include "swift/Basic/DefineTypeIDZone.h" diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index 5862ccdfcc1..d7c89b2be6b 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -76,6 +76,9 @@ public: /// binary module has already been built for use by the compiler. std::string PrebuiltModuleCachePath; + /// For these modules, we should prefer using Swift interface when importing them. + std::vector PreferInterfaceForModules; + /// Emit index data for imported serialized swift system modules. bool IndexSystemModules = false; diff --git a/include/swift/Frontend/ParseableInterfaceModuleLoader.h b/include/swift/Frontend/ParseableInterfaceModuleLoader.h index cbd83e08624..7988634e07b 100644 --- a/include/swift/Frontend/ParseableInterfaceModuleLoader.h +++ b/include/swift/Frontend/ParseableInterfaceModuleLoader.h @@ -132,8 +132,9 @@ class ParseableInterfaceModuleLoader : public SerializedModuleLoaderBase { explicit ParseableInterfaceModuleLoader( ASTContext &ctx, StringRef cacheDir, StringRef prebuiltCacheDir, DependencyTracker *tracker, ModuleLoadingMode loadMode, + ArrayRef PreferInterfaceForModules, bool RemarkOnRebuildFromInterface) - : SerializedModuleLoaderBase(ctx, tracker, loadMode), + : SerializedModuleLoaderBase(ctx, tracker, loadMode, PreferInterfaceForModules), CacheDir(cacheDir), PrebuiltCacheDir(prebuiltCacheDir), RemarkOnRebuildFromInterface(RemarkOnRebuildFromInterface) {} @@ -154,10 +155,12 @@ public: static std::unique_ptr create(ASTContext &ctx, StringRef cacheDir, StringRef prebuiltCacheDir, DependencyTracker *tracker, ModuleLoadingMode loadMode, + ArrayRef PreferInterfaceForModules = {}, bool RemarkOnRebuildFromInterface = false) { return std::unique_ptr( new ParseableInterfaceModuleLoader(ctx, cacheDir, prebuiltCacheDir, tracker, loadMode, + PreferInterfaceForModules, RemarkOnRebuildFromInterface)); } diff --git a/include/swift/IDE/IDERequestIDZone.def b/include/swift/IDE/IDERequestIDZone.def index ba64fa73134..d6203384792 100644 --- a/include/swift/IDE/IDERequestIDZone.def +++ b/include/swift/IDE/IDERequestIDZone.def @@ -14,8 +14,9 @@ // TypeID zone, for use with the TypeID template. // //===----------------------------------------------------------------------===// -SWIFT_TYPEID(CursorInfoRequest) -SWIFT_TYPEID(RangeInfoRequest) -SWIFT_TYPEID(ProvideDefaultImplForRequest) -SWIFT_TYPEID(CollectOverriddenDeclsRequest) -SWIFT_TYPEID(ResolveProtocolNameRequest) + +SWIFT_REQUEST(IDE, CollectOverriddenDeclsRequest) +SWIFT_REQUEST(IDE, CursorInfoRequest) +SWIFT_REQUEST(IDE, ProvideDefaultImplForRequest) +SWIFT_REQUEST(IDE, RangeInfoRequest) +SWIFT_REQUEST(IDE, ResolveProtocolNameRequest) diff --git a/include/swift/IDE/IDERequests.h b/include/swift/IDE/IDERequests.h index 096f62138ee..e9936360f1d 100644 --- a/include/swift/IDE/IDERequests.h +++ b/include/swift/IDE/IDERequests.h @@ -282,22 +282,21 @@ public: }; /// The zone number for the IDE. -#define SWIFT_IDE_REQUESTS_TYPEID_ZONE 137 -#define SWIFT_TYPEID_ZONE SWIFT_IDE_REQUESTS_TYPEID_ZONE +#define SWIFT_TYPEID_ZONE IDE #define SWIFT_TYPEID_HEADER "swift/IDE/IDERequestIDZone.def" #include "swift/Basic/DefineTypeIDZone.h" #undef SWIFT_TYPEID_ZONE #undef SWIFT_TYPEID_HEADER // Set up reporting of evaluated requests. -#define SWIFT_TYPEID(RequestType) \ +#define SWIFT_REQUEST(Zone, RequestType) \ template<> \ inline void reportEvaluatedRequest(UnifiedStatsReporter &stats, \ const RequestType &request) { \ ++stats.getFrontendCounters().RequestType; \ } #include "swift/IDE/IDERequestIDZone.def" -#undef SWIFT_TYPEID +#undef SWIFT_REQUEST } // end namespace swift diff --git a/include/swift/IDE/IDETypeIDs.h b/include/swift/IDE/IDETypeIDs.h index 82d2ffac7a0..8f71f94f1e2 100644 --- a/include/swift/IDE/IDETypeIDs.h +++ b/include/swift/IDE/IDETypeIDs.h @@ -20,8 +20,7 @@ #include "swift/Basic/TypeID.h" namespace swift { -#define SWIFT_IDE_TYPEID_ZONE 136 -#define SWIFT_TYPEID_ZONE SWIFT_IDE_TYPEID_ZONE +#define SWIFT_TYPEID_ZONE IDETypes #define SWIFT_TYPEID_HEADER "swift/IDE/IDETypeIDZone.def" #include "swift/Basic/DefineTypeIDZone.h" diff --git a/include/swift/Sema/IDETypeCheckingRequestIDZone.def b/include/swift/Sema/IDETypeCheckingRequestIDZone.def index 6358ba0b01e..4339ee5fc27 100644 --- a/include/swift/Sema/IDETypeCheckingRequestIDZone.def +++ b/include/swift/Sema/IDETypeCheckingRequestIDZone.def @@ -14,8 +14,9 @@ // TypeID zone, for use with the TypeID template. // //===----------------------------------------------------------------------===// -SWIFT_TYPEID(IsDeclApplicableRequest) -SWIFT_TYPEID(TypeRelationCheckRequest) -SWIFT_TYPEID(RootAndResultTypeOfKeypathDynamicMemberRequest) -SWIFT_TYPEID(RootTypeOfKeypathDynamicMemberRequest) -SWIFT_TYPEID(HasDynamicMemberLookupAttributeRequest) + +SWIFT_REQUEST(IDETypeChecking, HasDynamicMemberLookupAttributeRequest) +SWIFT_REQUEST(IDETypeChecking, IsDeclApplicableRequest) +SWIFT_REQUEST(IDETypeChecking, RootAndResultTypeOfKeypathDynamicMemberRequest) +SWIFT_REQUEST(IDETypeChecking, RootTypeOfKeypathDynamicMemberRequest) +SWIFT_REQUEST(IDETypeChecking, TypeRelationCheckRequest) diff --git a/include/swift/Sema/IDETypeCheckingRequests.h b/include/swift/Sema/IDETypeCheckingRequests.h index 1b971a30340..d2e2316abcf 100644 --- a/include/swift/Sema/IDETypeCheckingRequests.h +++ b/include/swift/Sema/IDETypeCheckingRequests.h @@ -258,22 +258,21 @@ public: }; /// The zone number for the IDE. -#define SWIFT_IDE_TYPE_CHECK_REQUESTS_TYPEID_ZONE 97 -#define SWIFT_TYPEID_ZONE SWIFT_IDE_TYPE_CHECK_REQUESTS_TYPEID_ZONE +#define SWIFT_TYPEID_ZONE IDETypeChecking #define SWIFT_TYPEID_HEADER "swift/Sema/IDETypeCheckingRequestIDZone.def" #include "swift/Basic/DefineTypeIDZone.h" #undef SWIFT_TYPEID_ZONE #undef SWIFT_TYPEID_HEADER // Set up reporting of evaluated requests. -#define SWIFT_TYPEID(RequestType) \ +#define SWIFT_REQUEST(Zone, RequestType) \ template<> \ inline void reportEvaluatedRequest(UnifiedStatsReporter &stats, \ const RequestType &request) { \ ++stats.getFrontendCounters().RequestType; \ } #include "swift/Sema/IDETypeCheckingRequestIDZone.def" -#undef SWIFT_TYPEID +#undef SWIFT_REQUEST } // end namespace swift diff --git a/include/swift/Serialization/DeclTypeRecordNodes.def b/include/swift/Serialization/DeclTypeRecordNodes.def index 46d4b167a06..462106db5bf 100644 --- a/include/swift/Serialization/DeclTypeRecordNodes.def +++ b/include/swift/Serialization/DeclTypeRecordNodes.def @@ -149,7 +149,7 @@ PATTERN(VAR) OTHER(PARAMETERLIST, 210) // 211 is unused OTHER(FOREIGN_ERROR_CONVENTION, 212) -OTHER(DECL_CONTEXT, 213) +// 213 is unused OTHER(XREF_TYPE_PATH_PIECE, 214) OTHER(XREF_VALUE_PATH_PIECE, 215) OTHER(XREF_EXTENSION_PATH_PIECE, 216) diff --git a/include/swift/Serialization/ModuleFile.h b/include/swift/Serialization/ModuleFile.h index 3222d68ce5a..f4e61c1bf7f 100644 --- a/include/swift/Serialization/ModuleFile.h +++ b/include/swift/Serialization/ModuleFile.h @@ -305,9 +305,6 @@ private: /// Decls referenced by this module. MutableArrayRef> Decls; - /// DeclContexts referenced by this module. - MutableArrayRef> DeclContexts; - /// Local DeclContexts referenced by this module. MutableArrayRef> LocalDeclContexts; @@ -871,7 +868,7 @@ public: DeclContext *getDeclContext(serialization::DeclContextID DID); /// Returns the local decl context with the given ID, deserializing it if needed. - DeclContext *getLocalDeclContext(serialization::DeclContextID DID); + DeclContext *getLocalDeclContext(serialization::LocalDeclContextID DID); /// Returns the appropriate module for the given ID. ModuleDecl *getModule(serialization::ModuleID MID); diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h index 5f29833ad54..94f43bb5fe8 100644 --- a/include/swift/Serialization/ModuleFormat.h +++ b/include/swift/Serialization/ModuleFormat.h @@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 514; // specialize attr +const uint16_t SWIFTMODULE_VERSION_MINOR = 515; // remove DeclContext indirection using DeclIDField = BCFixed<31>; @@ -66,9 +66,58 @@ using TypeIDWithBitField = BCFixed<32>; using IdentifierID = DeclID; using IdentifierIDField = DeclIDField; -// DeclContextID must be the same as DeclID because it is stored in the same way. -using DeclContextID = DeclID; -using DeclContextIDField = DeclIDField; +// LocalDeclContextID must be the same as DeclID because it is stored in the +// same way. +using LocalDeclContextID = DeclID; +using LocalDeclContextIDField = DeclIDField; + +/// Stores either a DeclID or a LocalDeclContextID, using 32 bits. +class DeclContextID { + int32_t rawValue; + explicit DeclContextID(int32_t rawValue) : rawValue(rawValue) {} +public: + DeclContextID() : DeclContextID(0) {} + + static DeclContextID forDecl(DeclID value) { + assert(value && "should encode null using DeclContextID()"); + assert(llvm::isUInt<31>(value) && "too many DeclIDs"); + return DeclContextID(static_cast(value)); + } + static DeclContextID forLocalDeclContext(LocalDeclContextID value) { + assert(value && "should encode null using DeclContextID()"); + assert(llvm::isUInt<31>(value) && "too many LocalDeclContextIDs"); + return DeclContextID(-static_cast(value)); + } + + explicit operator bool() const { + return rawValue != 0; + } + + Optional getAsDeclID() const { + if (rawValue > 0) + return DeclID(rawValue); + return None; + } + + Optional getAsLocalDeclContextID() const { + if (rawValue < 0) + return LocalDeclContextID(-rawValue); + return None; + } + + static DeclContextID getFromOpaqueValue(uint32_t opaqueValue) { + return DeclContextID(opaqueValue); + } + uint32_t getOpaqueValue() const { return rawValue; } +}; + +class DeclContextIDField : public BCFixed<32> { +public: + static DeclContextID convert(uint64_t rawValue) { + assert(llvm::isUInt<32>(rawValue)); + return DeclContextID::getFromOpaqueValue(rawValue); + } +}; // NormalConformanceID must be the same as DeclID because it is stored // in the same way. @@ -852,9 +901,9 @@ namespace decls_block { BCFixed<1>, // pseudogeneric? BCFixed<1>, // noescape? BCFixed<1>, // error result? - BCFixed<30>, // number of parameters - BCFixed<30>, // number of yields - BCFixed<30>, // number of results + BCVBR<6>, // number of parameters + BCVBR<5>, // number of yields + BCVBR<5>, // number of results GenericSignatureIDField, // generic signature BCArray // parameter types/conventions, alternating // followed by result types/conventions, alternating @@ -870,7 +919,7 @@ namespace decls_block { using SILLayoutLayout = BCRecordLayout< SIL_LAYOUT, GenericSignatureIDField, // generic signature - BCFixed<31>, // number of fields + BCVBR<8>, // number of fields BCArray // field types with mutability >; @@ -1057,7 +1106,7 @@ namespace decls_block { AccessLevelField, // setter access, if applicable DeclIDField, // opaque return type decl BCFixed<2>, // # of property wrapper backing properties - BCVBR<4>, // total number of vtable entries introduced by all accessors + BCVBR<4>, // total number of vtable entries introduced by all accessors BCArray // accessors, backing properties, and dependencies >; @@ -1154,7 +1203,7 @@ namespace decls_block { StaticSpellingKindField, // spelling of 'static' or 'class' BCVBR<3>, // numpatterns BCArray // init contexts - // The patterns and decl-contexts trail the record. + // The patterns trail the record. >; template @@ -1223,7 +1272,7 @@ namespace decls_block { StaticSpellingKindField, // is subscript static? BCVBR<5>, // number of parameter name components DeclIDField, // opaque return type decl - BCFixed<8>, // total number of vtable entries introduced by all accessors + BCVBR<4>, // total number of vtable entries introduced by all accessors BCArray // name components, // followed by DeclID accessors, // followed by TypeID dependencies @@ -1347,8 +1396,8 @@ namespace decls_block { LAYOUT_REQUIREMENT, LayoutRequirementKindField, // requirement kind TypeIDField, // type being constrained - BCFixed<24>, // size - BCFixed<32> // alignment + BCVBR<16>, // size + BCVBR<8> // alignment >; /// Specifies the private discriminator string for a private declaration. This @@ -1500,7 +1549,7 @@ namespace decls_block { using AlignmentDeclAttrLayout = BCRecordLayout< Alignment_DECL_ATTR, BCFixed<1>, // implicit flag - BCFixed<31> // alignment + BCVBR<8> // alignment >; using SwiftNativeObjCRuntimeBaseDeclAttrLayout = BCRecordLayout< @@ -1520,16 +1569,6 @@ namespace decls_block { BCFixed<2> // modref value >; - using DeclContextLayout = BCRecordLayout< - DECL_CONTEXT, - // If this DeclContext is a local context, this is an - // index into the local decl context table. - // If this DeclContext is a Decl (and not a DeclContext - // *at all*, this is an index into the decl table. - DeclContextIDField, - BCFixed<1> // is a decl - >; - using ForeignErrorConventionLayout = BCRecordLayout< FOREIGN_ERROR_CONVENTION, ForeignErrorConventionKindField, // kind @@ -1739,7 +1778,6 @@ namespace index_block { ENTRY_POINT, LOCAL_DECL_CONTEXT_OFFSETS, - DECL_CONTEXT_OFFSETS, LOCAL_TYPE_DECLS, OPAQUE_RETURN_TYPE_DECLS, GENERIC_ENVIRONMENT_OFFSETS, diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h index b419cda8db6..93f5f0f936b 100644 --- a/include/swift/Serialization/SerializedModuleLoader.h +++ b/include/swift/Serialization/SerializedModuleLoader.h @@ -42,8 +42,10 @@ class SerializedModuleLoaderBase : public ModuleLoader { protected: ASTContext &Ctx; ModuleLoadingMode LoadMode; + ArrayRef PreferInterfaceForModules; SerializedModuleLoaderBase(ASTContext &ctx, DependencyTracker *tracker, - ModuleLoadingMode LoadMode); + ModuleLoadingMode LoadMode, + ArrayRef PreferInterfaceForModules = {}); void collectVisibleTopLevelModuleNamesImpl(SmallVectorImpl &names, StringRef extension) const; diff --git a/lib/AST/AccessRequests.cpp b/lib/AST/AccessRequests.cpp index befc0fb2d88..20b1605560b 100644 --- a/lib/AST/AccessRequests.cpp +++ b/lib/AST/AccessRequests.cpp @@ -25,7 +25,7 @@ using namespace swift; namespace swift { // Implement the access-control type zone. -#define SWIFT_TYPEID_ZONE SWIFT_ACCESSS_REQUESTS_TYPEID_ZONE +#define SWIFT_TYPEID_ZONE AccessControl #define SWIFT_TYPEID_HEADER "swift/AST/AccessTypeIDZone.def" #include "swift/Basic/ImplementTypeIDZone.h" #undef SWIFT_TYPEID_ZONE @@ -321,13 +321,13 @@ DefaultAndMaxAccessLevelRequest::cacheResult( // Define request evaluation functions for each of the access requests. static AbstractRequestFunction *accessRequestFunctions[] = { -#define SWIFT_TYPEID(Name) \ +#define SWIFT_REQUEST(Zone, Name) \ reinterpret_cast(&Name::evaluateRequest), #include "swift/AST/AccessTypeIDZone.def" -#undef SWIFT_TYPEID +#undef SWIFT_REQUEST }; void swift::registerAccessRequestFunctions(Evaluator &evaluator) { - evaluator.registerRequestFunctions(SWIFT_ACCESS_REQUESTS_TYPEID_ZONE, + evaluator.registerRequestFunctions(Zone::AccessControl, accessRequestFunctions); } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 2c1f0949d23..a32be436c6a 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -6887,6 +6887,18 @@ FuncDecl *FuncDecl::create(ASTContext &Context, SourceLoc StaticLoc, FD->getBodyResultTypeLoc() = FnRetType; return FD; } + +OperatorDecl *FuncDecl::getOperatorDecl() const { + // Fast-path: Most functions are not operators. + if (!isOperator()) { + return nullptr; + } + return evaluateOrDefault(getASTContext().evaluator, + FunctionOperatorRequest{ + const_cast(this) + }, + nullptr); + } AccessorDecl *AccessorDecl::createImpl(ASTContext &ctx, SourceLoc declLoc, diff --git a/lib/AST/Evaluator.cpp b/lib/AST/Evaluator.cpp index d96fa76dc5f..959a46c1f2c 100644 --- a/lib/AST/Evaluator.cpp +++ b/lib/AST/Evaluator.cpp @@ -50,8 +50,9 @@ Evaluator::getAbstractRequestFunction(uint8_t zoneID, uint8_t requestID) const { } void Evaluator::registerRequestFunctions( - uint8_t zoneID, + Zone zone, ArrayRef functions) { + uint8_t zoneID = static_cast(zone); #ifndef NDEBUG for (const auto &zone : requestFunctionsByZone) { assert(zone.first != zoneID); diff --git a/lib/AST/NameLookupRequests.cpp b/lib/AST/NameLookupRequests.cpp index 9eeee9c190e..1161b58ed99 100644 --- a/lib/AST/NameLookupRequests.cpp +++ b/lib/AST/NameLookupRequests.cpp @@ -21,7 +21,7 @@ using namespace swift; namespace swift { // Implement the name lookup type zone. -#define SWIFT_TYPEID_ZONE SWIFT_NAME_LOOKUP_REQUESTS_TYPEID_ZONE +#define SWIFT_TYPEID_ZONE NameLookup #define SWIFT_TYPEID_HEADER "swift/AST/NameLookupTypeIDZone.def" #include "swift/Basic/ImplementTypeIDZone.h" #undef SWIFT_TYPEID_ZONE @@ -113,13 +113,13 @@ void GetDestructorRequest::cacheResult(DestructorDecl *value) const { // Define request evaluation functions for each of the name lookup requests. static AbstractRequestFunction *nameLookupRequestFunctions[] = { -#define SWIFT_TYPEID(Name) \ +#define SWIFT_REQUEST(Zone, Name) \ reinterpret_cast(&Name::evaluateRequest), #include "swift/AST/NameLookupTypeIDZone.def" -#undef SWIFT_TYPEID +#undef SWIFT_REQUEST }; void swift::registerNameLookupRequestFunctions(Evaluator &evaluator) { - evaluator.registerRequestFunctions(SWIFT_NAME_LOOKUP_REQUESTS_TYPEID_ZONE, + evaluator.registerRequestFunctions(Zone::NameLookup, nameLookupRequestFunctions); } diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 9fb91c28036..81b94d0fd61 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -23,7 +23,7 @@ using namespace swift; namespace swift { // Implement the type checker type zone (zone 10). -#define SWIFT_TYPEID_ZONE SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE +#define SWIFT_TYPEID_ZONE TypeChecker #define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def" #include "swift/Basic/ImplementTypeIDZone.h" #undef SWIFT_TYPEID_ZONE diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 53b65681e42..ae501b3346c 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -370,7 +370,8 @@ bool CompilerInstance::setUpModuleLoaders() { StringRef PrebuiltModuleCachePath = FEOpts.PrebuiltModuleCachePath; auto PIML = ParseableInterfaceModuleLoader::create( *Context, ModuleCachePath, PrebuiltModuleCachePath, - getDependencyTracker(), MLM, FEOpts.RemarkOnRebuildFromModuleInterface); + getDependencyTracker(), MLM, FEOpts.PreferInterfaceForModules, + FEOpts.RemarkOnRebuildFromModuleInterface); Context->addModuleLoader(std::move(PIML)); } Context->addModuleLoader(std::move(SML)); diff --git a/lib/Frontend/ParseableInterfaceModuleLoader.cpp b/lib/Frontend/ParseableInterfaceModuleLoader.cpp index 699f1a20579..b9eed1cfa84 100644 --- a/lib/Frontend/ParseableInterfaceModuleLoader.cpp +++ b/lib/Frontend/ParseableInterfaceModuleLoader.cpp @@ -1435,11 +1435,14 @@ std::error_code ParseableInterfaceModuleLoader::findModuleFilesInDirectory( } // Create an instance of the Impl to do the heavy lifting. + auto ModuleName = ModuleID.first.str(); ParseableInterfaceModuleLoaderImpl Impl( - Ctx, ModPath, InPath, ModuleID.first.str(), + Ctx, ModPath, InPath, ModuleName, CacheDir, PrebuiltCacheDir, ModuleID.second, RemarkOnRebuildFromInterface, dependencyTracker, - LoadMode); + llvm::is_contained(PreferInterfaceForModules, + ModuleName)? + ModuleLoadingMode::PreferParseable : LoadMode); // Ask the impl to find us a module that we can load or give us an error // telling us that we couldn't load it. diff --git a/lib/IDE/IDERequests.cpp b/lib/IDE/IDERequests.cpp index e8b5318a643..a52adaceaaf 100644 --- a/lib/IDE/IDERequests.cpp +++ b/lib/IDE/IDERequests.cpp @@ -29,7 +29,7 @@ using namespace swift::ide; namespace swift { // Implement the IDE type zone. -#define SWIFT_TYPEID_ZONE SWIFT_IDE_REQUESTS_TYPEID_ZONE +#define SWIFT_TYPEID_ZONE IDE #define SWIFT_TYPEID_HEADER "swift/IDE/IDERequestIDZone.def" #include "swift/Basic/ImplementTypeIDZone.h" #undef SWIFT_TYPEID_ZONE @@ -38,14 +38,14 @@ namespace swift { // Define request evaluation functions for each of the IDE requests. static AbstractRequestFunction *ideRequestFunctions[] = { -#define SWIFT_TYPEID(Name) \ +#define SWIFT_REQUEST(Zone, Name) \ reinterpret_cast(&Name::evaluateRequest), #include "swift/IDE/IDERequestIDZone.def" -#undef SWIFT_TYPEID +#undef SWIFT_REQUEST }; void swift::registerIDERequestFunctions(Evaluator &evaluator) { - evaluator.registerRequestFunctions(SWIFT_IDE_REQUESTS_TYPEID_ZONE, + evaluator.registerRequestFunctions(Zone::IDE, ideRequestFunctions); registerIDETypeCheckRequestFunctions(evaluator); } diff --git a/lib/SILOptimizer/Mandatory/SemanticARCOpts.cpp b/lib/SILOptimizer/Mandatory/SemanticARCOpts.cpp index c6c04a4bc2e..06580a176a4 100644 --- a/lib/SILOptimizer/Mandatory/SemanticARCOpts.cpp +++ b/lib/SILOptimizer/Mandatory/SemanticARCOpts.cpp @@ -16,6 +16,7 @@ #include "swift/SIL/BranchPropagatedUser.h" #include "swift/SIL/MemAccessUtils.h" #include "swift/SIL/OwnershipUtils.h" +#include "swift/SILOptimizer/Utils/Local.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILInstruction.h" @@ -121,8 +122,23 @@ static bool isConsumed( namespace { +/// A two stage visitor that optimizes ownership instructions and eliminates any +/// trivially dead code that results after optimization. The two stages are used +/// to avoid iterator invalidation. Specifically: +/// +/// 1. We first process the CFG instruction by instruction, only eliminating +/// instructions that are guaranteed to be dominated by the visited +/// instrution. While we do that, we add the operands of any instruction that we +/// successfully optimize to the worklist. NOTE: We do not process arguments +/// here to get SSA guarantees around dominance. +/// +/// 2. Once we have processed the CFG and done some initial optimization, we +/// enter phase 2 where we process the worklist. Here we are allowed to process +/// arbitrary values and instructions, removing things that we are erasing from +/// the worklist before we delete them. struct SemanticARCOptVisitor : SILInstructionVisitor { + SmallSetVector worklist; SILFunction &F; Optional TheDeadEndBlocks; @@ -133,17 +149,100 @@ struct SemanticARCOptVisitor TheDeadEndBlocks.emplace(&F); return *TheDeadEndBlocks; } - + + /// Given a single value instruction, RAUW it with newValue, add newValue to + /// the worklist, and then call eraseInstruction on i. + void eraseAndRAUWSingleValueInstruction(SingleValueInstruction *i, SILValue newValue) { + worklist.insert(newValue); + i->replaceAllUsesWith(newValue); + eraseInstruction(i); + } + + /// Add all operands of i to the worklist and then call eraseInstruction on + /// i. Assumes that the instruction doesnt have users. + void eraseInstructionAndAddOptsToWorklist(SILInstruction *i) { + // Then copy all operands into the worklist for future processing. + for (SILValue v : i->getOperandValues()) { + worklist.insert(v); + } + eraseInstruction(i); + } + + /// Remove all results of the given instruction from the worklist and then + /// erase the instruction. Assumes that the instruction does not have any + /// users left. + void eraseInstruction(SILInstruction *i) { + // Remove all SILValues of the instruction from the worklist and then erase + // the instruction. + for (SILValue result : i->getResults()) { + worklist.remove(result); + } + i->eraseFromParent(); + } + + /// The default visitor. bool visitSILInstruction(SILInstruction *i) { return false; } bool visitCopyValueInst(CopyValueInst *cvi); bool visitBeginBorrowInst(BeginBorrowInst *bbi); bool visitLoadInst(LoadInst *li); bool isWrittenTo(LoadInst *li); + + bool processWorklist(); + + bool performGuaranteedCopyValueOptimization(CopyValueInst *cvi); + bool eliminateDeadLiveRangeCopyValue(CopyValueInst *cvi); }; } // end anonymous namespace +bool SemanticARCOptVisitor::processWorklist() { + // NOTE: The madeChange here is not strictly necessary since we only have + // items added to the worklist today if we have already made /some/ sort of + // change. That being said, I think there is a low cost to including this here + // and makes the algorithm more correct, visually and in the face of potential + // refactoring. + bool madeChange = false; + + while (!worklist.empty()) { + SILValue next = worklist.pop_back_val(); + + // First check if this is an instruction that is trivially dead. This can + // occur if we eliminate rr traffic resulting in dead projections and the + // like. + // + // If we delete, we first add all of our deleted instructions operands to + // the worklist and then remove all results (since we are going to delete + // the instruction). + if (auto *defInst = next->getDefiningInstruction()) { + if (isInstructionTriviallyDead(defInst)) { + madeChange = true; + recursivelyDeleteTriviallyDeadInstructions( + defInst, true/*force*/, + [&](SILInstruction *i) { + for (SILValue operand : i->getOperandValues()) { + worklist.insert(operand); + } + for (SILValue result : i->getResults()) { + worklist.remove(result); + } + ++NumEliminatedInsts; + }); + continue; + } + } + + // Otherwise, if we have a single value instruction (to be expanded later + // perhaps), try to visit that value recursively. + if (auto *svi = dyn_cast(next)) { + madeChange |= visit(svi); + continue; + } + } + + return madeChange; +} + bool SemanticARCOptVisitor::visitBeginBorrowInst(BeginBorrowInst *bbi) { auto kind = bbi->getOperand().getOwnershipKind(); SmallVector endBorrows; @@ -167,11 +266,11 @@ bool SemanticARCOptVisitor::visitBeginBorrowInst(BeginBorrowInst *bbi) { // begin borrow and end borrows. while (!endBorrows.empty()) { auto *ebi = endBorrows.pop_back_val(); - ebi->eraseFromParent(); + eraseInstruction(ebi); ++NumEliminatedInsts; } - bbi->replaceAllUsesWith(bbi->getOperand()); - bbi->eraseFromParent(); + + eraseAndRAUWSingleValueInstruction(bbi, bbi->getOperand()); ++NumEliminatedInsts; return true; } @@ -181,7 +280,11 @@ static bool canHandleOperand(SILValue operand, SmallVectorImpl &out) { return false; /// TODO: Add support for begin_borrow, load_borrow. - return all_of(out, [](SILValue v) { return isa(v); }); + auto canHandleValue = [](SILValue v) -> bool { + return isa(v) || isa(v) || + isa(v); + }; + return all_of(out, canHandleValue); } // Eliminate a copy of a borrowed value, if: @@ -216,7 +319,7 @@ static bool canHandleOperand(SILValue operand, SmallVectorImpl &out) { // are within the borrow scope. // // TODO: This needs a better name. -static bool performGuaranteedCopyValueOptimization(CopyValueInst *cvi) { +bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst *cvi) { SmallVector borrowIntroducers; // Whitelist the operands that we know how to support and make sure @@ -229,6 +332,9 @@ static bool performGuaranteedCopyValueOptimization(CopyValueInst *cvi) { // make sure all of them are destroy_value. For our non-destroying // instructions, make sure that they accept a guaranteed value. After that, // make sure that our destroys are within the lifetime of our borrowed values. + // + // TODO: Change isConsumed to return branch propagated users for destroys, so + // we do not need to construct another array. SmallVector destroys; SmallVector guaranteedForwardingInsts; if (isConsumed(cvi, destroys, &guaranteedForwardingInsts)) @@ -240,21 +346,48 @@ static bool performGuaranteedCopyValueOptimization(CopyValueInst *cvi) { // post-dominated by the end_borrow set. If they do not, then the // copy_value is lifetime extending the guaranteed value, we can not // eliminate it. - // - // TODO: When we support begin_borrow/load_borrow a linear linfetime - // check will be needed here. - assert(all_of(borrowIntroducers, - [](SILValue v) { return isa(v); })); + { + SmallVector destroysForLinearLifetimeCheck( + destroys.begin(), destroys.end()); + SmallVector endBorrowInsts; + SmallPtrSet visitedBlocks; + for (SILValue v : borrowIntroducers) { + if (isa(v)) { + continue; + } + + SWIFT_DEFER { + endBorrowInsts.clear(); + visitedBlocks.clear(); + }; + + if (auto *lbi = dyn_cast(v)) { + llvm::copy(lbi->getEndBorrows(), std::back_inserter(endBorrowInsts)); + } else if (auto *bbi = dyn_cast(v)) { + llvm::copy(bbi->getEndBorrows(), std::back_inserter(endBorrowInsts)); + } else { + llvm_unreachable("Unhandled borrow introducer?!"); + } + + // Make sure that our destroys are properly nested within our end + // borrows. Otherwise, we can not optimize. + auto result = valueHasLinearLifetime( + v, endBorrowInsts, destroysForLinearLifetimeCheck, visitedBlocks, + getDeadEndBlocks(), ownership::ErrorBehaviorKind::ReturnFalse); + if (result.getFoundError()) + return false; + } + } // Otherwise, we know that our copy_value/destroy_values are all completely // within the guaranteed value scope. First delete the destroys/copies. while (!destroys.empty()) { auto *dvi = destroys.pop_back_val(); - dvi->eraseFromParent(); + eraseInstruction(dvi); ++NumEliminatedInsts; } - cvi->replaceAllUsesWith(cvi->getOperand()); - cvi->eraseFromParent(); + + eraseAndRAUWSingleValueInstruction(cvi, cvi->getOperand()); // Then change all of our guaranteed forwarding insts to have guaranteed // ownership kind instead of what ever they previously had (ignoring trivial @@ -302,12 +435,12 @@ static bool performGuaranteedCopyValueOptimization(CopyValueInst *cvi) { /// If cvi only has destroy value users, then cvi is a dead live range. Lets /// eliminate all such dead live ranges. -static bool eliminateDeadLiveRangeCopyValue(CopyValueInst *cvi) { +bool SemanticARCOptVisitor::eliminateDeadLiveRangeCopyValue(CopyValueInst *cvi) { // See if we are lucky and have a simple case. if (auto *op = cvi->getSingleUse()) { if (auto *dvi = dyn_cast(op->getUser())) { - dvi->eraseFromParent(); - cvi->eraseFromParent(); + eraseInstruction(dvi); + eraseInstructionAndAddOptsToWorklist(cvi); NumEliminatedInsts += 2; return true; } @@ -331,10 +464,10 @@ static bool eliminateDeadLiveRangeCopyValue(CopyValueInst *cvi) { // Now that we have a truly dead live range copy value, eliminate it! while (!destroys.empty()) { - destroys.pop_back_val()->eraseFromParent(); + eraseInstruction(destroys.pop_back_val()); ++NumEliminatedInsts; } - cvi->eraseFromParent(); + eraseInstructionAndAddOptsToWorklist(cvi); ++NumEliminatedInsts; return true; } @@ -513,12 +646,11 @@ bool SemanticARCOptVisitor::visitLoadInst(LoadInst *li) { while (!destroyValues.empty()) { auto *dvi = destroyValues.pop_back_val(); SILBuilderWithScope(dvi).createEndBorrow(dvi->getLoc(), lbi); - dvi->eraseFromParent(); + eraseInstruction(dvi); ++NumEliminatedInsts; } - li->replaceAllUsesWith(lbi); - li->eraseFromParent(); + eraseAndRAUWSingleValueInstruction(li, lbi); ++NumEliminatedInsts; ++NumLoadCopyConvertedToLoadBorrow; return true; @@ -542,10 +674,11 @@ struct SemanticARCOpts : SILFunctionTransform { "Can not perform semantic arc optimization unless ownership " "verification is enabled"); - // Iterate over all of the arguments, performing small peephole - // ARC optimizations. - // - // FIXME: Should we iterate or use a RPOT order here? + // Iterate over all of the arguments, performing small peephole ARC + // optimizations. We assume that the visitor will add any instructions we + // need to recursively to the visitor's worklist. Also, note that we assume + // that we do not look through /any/ sil block arguments here since our + // iteration here is only valid up to SSA. bool madeChange = false; SemanticARCOptVisitor visitor(f); @@ -584,6 +717,15 @@ struct SemanticARCOpts : SILFunctionTransform { madeChange |= visitor.visit(&*ii); } + // Finally drain the worklist on the visitor and process until we reach the + // fixpoint and thus do not have any further work to do. + // + // NOTE: At this point madeChange has already been set to true if we have + // anything in the worklist, so technically we do not need to do this. But I + // would rather represent this state to future proof the pass to be + // "visually" correct. + madeChange |= visitor.processWorklist(); + if (madeChange) { invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions); } diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index 423e27eea66..1bfe0772bcf 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -978,8 +978,33 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const { cs.addConstraint(ConstraintKind::Bind, TypeVar, type, locator); // If this was from a defaultable binding note that. - if (Binding.isDefaultableBinding()) - cs.DefaultedConstraints.push_back(Binding.DefaultableBinding); + if (Binding.isDefaultableBinding()) { + auto *locator = Binding.DefaultableBinding; + // If this default binding comes from a "hole" + // in the constraint system, we have to propagate + // this information and mark this type variable + // as well as mark everything adjacent to it as + // a potential "hole". + // + // Consider this example: + // + // func foo(_: T) {} + // foo(.bar) <- Since `.bar` can't be inferred due to + // luck of information about its base type, + // it's member type is going to get defaulted + // to `Any` which has to be propaged to type + // variable associated with `T` and vice versa. + if (cs.shouldAttemptFixes() && cs.isHoleAt(locator)) { + auto &CG = cs.getConstraintGraph(); + for (auto *constraint : CG.gatherConstraints( + TypeVar, ConstraintGraph::GatheringKind::EquivalenceClass)) { + for (auto *typeVar : constraint->getTypeVariables()) + cs.recordHole(typeVar); + } + } + + cs.DefaultedConstraints.push_back(locator); + } return !cs.failedConstraint && !cs.simplify(); } diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index db4bc9683f9..ca81d5a207b 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -2863,18 +2863,6 @@ bool MissingMemberFailure::diagnoseAsError() { if (!anchor || !baseExpr) return false; - if (auto *typeVar = getBaseType()->getAs()) { - auto &CS = getConstraintSystem(); - auto *memberLoc = typeVar->getImpl().getLocator(); - // Don't try to diagnose anything besides first missing - // member in the chain. e.g. `x.foo().bar()` let's make - // sure to diagnose only `foo()` as missing because we - // don't really know much about what `bar()` is supposed - // to be. - if (CS.MissingMembers.count(memberLoc)) - return false; - } - auto baseType = resolveType(getBaseType())->getWithoutSpecifierType(); DeclNameLoc nameLoc(anchor->getStartLoc()); @@ -2940,6 +2928,27 @@ bool MissingMemberFailure::diagnoseAsError() { diagnostic.highlight(baseExpr->getSourceRange()) .highlight(nameLoc.getSourceRange()); correction->addFixits(diagnostic); + } else if (instanceTy->getAnyNominal() && + getName().getBaseName() == DeclBaseName::createConstructor()) { + auto &cs = getConstraintSystem(); + + auto memberName = getName().getBaseName(); + auto result = cs.performMemberLookup( + ConstraintKind::ValueMember, memberName, metatypeTy, + FunctionRefKind::DoubleApply, getLocator(), + /*includeInaccessibleMembers=*/true); + + // If there are no `init` members at all produce a tailored + // diagnostic for that, otherwise fallback to generic + // "no such member" one. + if (result.ViableCandidates.empty() && + result.UnviableCandidates.empty()) { + emitDiagnostic(anchor->getLoc(), diag::no_accessible_initializers, + instanceTy) + .highlight(baseExpr->getSourceRange()); + } else { + emitBasicError(baseType); + } } else { emitBasicError(baseType); } diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 2f098fab5fc..f6fd7d41ab8 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -2757,10 +2757,25 @@ namespace { } return TupleType::get(destTupleTypes, CS.getASTContext()); } else { - Type destTy = CS.createTypeVariable(CS.getConstraintLocator(expr), - TVO_CanBindToNoEscape); - CS.addConstraint(ConstraintKind::Bind, LValueType::get(destTy), CS.getType(expr), - CS.getConstraintLocator(expr)); + auto *locator = CS.getConstraintLocator(expr); + + auto isOrCanBeLValueType = [](Type type) { + if (auto *typeVar = type->getAs()) { + return typeVar->getImpl().canBindToLValue(); + } + return type->is(); + }; + + auto exprType = CS.getType(expr); + if (!isOrCanBeLValueType(exprType)) { + // Pretend that destination is an l-value type. + exprType = LValueType::get(exprType); + (void)CS.recordFix(TreatRValueAsLValue::create(CS, locator)); + } + + auto *destTy = CS.createTypeVariable(locator, TVO_CanBindToNoEscape); + CS.addConstraint(ConstraintKind::Bind, LValueType::get(destTy), + exprType, locator); return destTy; } } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 3cb9639b284..9be0ec2b97d 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -2205,6 +2205,9 @@ static ConstraintFix *fixPropertyWrapperFailure( if (!decl->hasValidSignature() || !type) return nullptr; + if (baseTy->isEqual(type)) + return nullptr; + if (!attemptFix(resolvedOverload, decl, type)) return nullptr; @@ -2298,7 +2301,8 @@ repairViaBridgingCast(ConstraintSystem &cs, Type fromType, Type toType, /// \return true if at least some of the failures has been repaired /// successfully, which allows type matcher to continue. bool ConstraintSystem::repairFailures( - Type lhs, Type rhs, SmallVectorImpl &conversionsOrFixes, + Type lhs, Type rhs, ConstraintKind matchKind, + SmallVectorImpl &conversionsOrFixes, ConstraintLocatorBuilder locator) { SmallVector path; auto *anchor = locator.getLocatorParts(path); @@ -2382,10 +2386,43 @@ bool ConstraintSystem::repairFailures( return true; }; + auto repairByTreatingRValueAsLValue = [&](Type lhs, Type rhs) -> bool { + if (!lhs->is() && + (rhs->is() || rhs->is())) { + // Conversion from l-value to inout in an operator argument + // position (which doesn't require explicit `&`) decays into + // a `Bind` of involved object types, same goes for explicit + // `&` conversion from l-value to inout type. + auto kind = (isa(anchor) || + (rhs->is() && + matchKind == ConstraintKind::OperatorArgumentConversion)) + ? ConstraintKind::Bind + : matchKind; + + auto result = matchTypes(lhs, rhs->getWithoutSpecifierType(), kind, + TMF_ApplyingFix, locator); + + if (result.isSuccess()) { + conversionsOrFixes.push_back( + TreatRValueAsLValue::create(*this, getConstraintLocator(locator))); + return true; + } + } + + return false; + }; + if (path.empty()) { if (!anchor) return false; + // This could be: + // - `InOutExpr` used with r-value e.g. `foo(&x)` where `x` is a `let`. + // - `ForceValueExpr` e.g. `foo.bar! = 42` where `bar` or `foo` are + // immutable or a subscript e.g. `foo["bar"]! = 42`. + if (repairByTreatingRValueAsLValue(lhs, rhs)) + return true; + // If method reference forms a value type of the key path, // there is going to be a constraint to match result of the // member lookup to the generic parameter `V` of *KeyPath @@ -2460,6 +2497,18 @@ bool ConstraintSystem::repairFailures( if (repairViaBridgingCast(*this, lhs, rhs, conversionsOrFixes, locator)) break; + // Argument is a r-value but parameter expects an l-value e.g. + // + // func foo(_ x: inout Int) {} + // let x: Int = 42 + // foo(x) // `x` can't be converted to `inout Int`. + // + // This has to happen before checking for optionality mismatch + // because otherwise `Int? arg conv inout Int` is going to get + // fixed as 2 fixes - "force unwrap" + r-value -> l-value mismatch. + if (repairByTreatingRValueAsLValue(lhs, rhs)) + break; + if (lhs->getOptionalObjectType() && !rhs->getOptionalObjectType()) { conversionsOrFixes.push_back( ForceOptional::create(*this, lhs, lhs->getOptionalObjectType(), loc)); @@ -2484,6 +2533,7 @@ bool ConstraintSystem::repairFailures( }, rhs)) { conversionsOrFixes.push_back(fix); + break; } // If argument in l-value type and parameter is `inout` or a pointer, @@ -2495,25 +2545,28 @@ bool ConstraintSystem::repairFailures( ConstraintKind::ArgumentConversion, TypeMatchFlags::TMF_ApplyingFix, locator); - if (result.isSuccess()) + if (result.isSuccess()) { conversionsOrFixes.push_back(AddAddressOf::create( *this, lhs, rhs, getConstraintLocator(locator))); + break; + } } // If the argument is inout and the parameter is not inout or a pointer, // suggest removing the &. if (lhs->is() && !rhs->is()) { auto objectType = rhs->lookThroughAllOptionalTypes(); - if (objectType->getAnyPointerElementType()) - break; + if (!objectType->getAnyPointerElementType()) { + auto result = matchTypes(lhs->getInOutObjectType(), rhs, + ConstraintKind::ArgumentConversion, + TypeMatchFlags::TMF_ApplyingFix, locator); - auto result = matchTypes(lhs->getInOutObjectType(), rhs, - ConstraintKind::ArgumentConversion, - TypeMatchFlags::TMF_ApplyingFix, locator); - - if (result.isSuccess()) - conversionsOrFixes.push_back(RemoveAddressOf::create(*this, lhs, - rhs, getConstraintLocator(locator))); + if (result.isSuccess()) { + conversionsOrFixes.push_back(RemoveAddressOf::create( + *this, lhs, rhs, getConstraintLocator(locator))); + break; + } + } } break; @@ -2679,7 +2732,15 @@ bool ConstraintSystem::repairFailures( break; } - case ConstraintLocator::FunctionResult: { + case ConstraintLocator::Member: + case ConstraintLocator::FunctionResult: + case ConstraintLocator::DynamicLookupResult: { + // Most likely this is an attempt to use get-only subscript as mutating, + // or assign a value of a result of function/member ref e.g. `foo() = 42` + // or `foo.bar = 42`, or `foo.bar()! = 42`. + if (repairByTreatingRValueAsLValue(rhs, lhs)) + break; + // `apply argument` -> `arg/param compare` -> // `@autoclosure result` -> `function result` if (path.size() > 3) { @@ -2734,6 +2795,13 @@ bool ConstraintSystem::repairFailures( break; } + case ConstraintLocator::SubscriptMember: { + if (repairByTreatingRValueAsLValue(lhs, rhs)) + break; + + break; + } + default: break; } @@ -3524,25 +3592,11 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, getConstraintLocator(locator))); } } - - if (!type1->is() && type2->is()) { - // If we have a concrete type that's an rvalue, "fix" it. - conversionsOrFixes.push_back( - TreatRValueAsLValue::create(*this, getConstraintLocator(locator))); - } - } - - if (attemptFixes && type2->is()) { - conversionsOrFixes.push_back( - TreatRValueAsLValue::create(*this, getConstraintLocator(locator))); - } else if (attemptFixes && kind == ConstraintKind::Bind && type1->is()) { - conversionsOrFixes.push_back( - TreatRValueAsLValue::create(*this, getConstraintLocator(locator))); } // Attempt to repair any failures identifiable at this point. if (attemptFixes) { - if (repairFailures(type1, type2, conversionsOrFixes, locator)) { + if (repairFailures(type1, type2, kind, conversionsOrFixes, locator)) { if (conversionsOrFixes.empty()) return getTypeMatchSuccess(); } @@ -3765,6 +3819,23 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint( ConstraintKind kind, ConstraintLocatorBuilder locator, TypeMatchOptions flags) { + if (shouldAttemptFixes()) { + auto *typeVar = type->getAs(); + // If type variable, associated with this conformance check, + // has been determined to be a "hole" in constraint system, + // let's consider this check a success without recording + // a fix, because it's just a consequence of other failure + // e.g. + // + // func foo(_: T) {} + // foo(Foo.bar) <- if `Foo` doesn't have `bar` there is + // no reason to complain about missing conformance. + if (typeVar && isHole(typeVar)) { + increaseScore(SK_Fix); + return SolutionKind::Solved; + } + } + // Dig out the fixed type to which this type refers. type = getFixedTypeRecursive(type, flags, /*wantRValue=*/true); @@ -5062,6 +5133,7 @@ fixMemberRef(ConstraintSystem &cs, Type baseTy, // overload here, that would help if such subscript has // not been provided. case MemberLookupResult::UR_WritableKeyPathOnReadOnlyMember: + return TreatRValueAsLValue::create(cs, cs.getConstraintLocator(locator)); case MemberLookupResult::UR_ReferenceWritableKeyPathOnMutatingMember: break; case MemberLookupResult::UR_KeyPathWithAnyObjectRootType: @@ -5176,12 +5248,33 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint( // If the lookup found no hits at all (either viable or unviable), diagnose it // as such and try to recover in various ways. if (shouldAttemptFixes()) { - // Let's record missing member in constraint system, this helps to prevent - // stacking up fixes for the same member, because e.g. if its base was of - // optional type, we'd re-introduce member constraint with optional stripped - // off to see if the problem is related to base not being explicitly unwrapped. - if (!MissingMembers.insert(locator)) - return SolutionKind::Error; + auto fixMissingMember = [&](Type baseTy, Type memberTy, + ConstraintLocator *locator) -> SolutionKind { + // Let's check whether there are any generic parameters + // associated with base type, we'd have to default them + // to `Any` and record as potential holes if so. + baseTy.transform([&](Type type) -> Type { + if (auto *typeVar = type->getAs()) { + if (typeVar->getImpl().hasRepresentativeOrFixed()) + return type; + recordHole(typeVar); + } + return type; + }); + + auto *fix = + DefineMemberBasedOnUse::create(*this, baseTy, member, locator); + if (recordFix(fix)) + return SolutionKind::Error; + + // Allow member type to default to `Any` to make it possible to form + // solutions when contextual type of the result cannot be deduced e.g. + // `let _ = x.foo`. + if (auto *memberTypeVar = memberTy->getAs()) + recordHole(memberTypeVar); + + return SolutionKind::Solved; + }; if (baseObjTy->getOptionalObjectType()) { // If the base type was an optional, look through it. @@ -5203,6 +5296,18 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint( } } + // Let's check whether the problem is related to optionality of base + // type, or there is no member with a given name. + result = + performMemberLookup(kind, member, baseObjTy->getOptionalObjectType(), + functionRefKind, locator, + /*includeInaccessibleMembers*/ true); + + // If uwrapped type still couldn't find anything for a given name, + // let's fallback to a "not such member" fix. + if (result.ViableCandidates.empty() && result.UnviableCandidates.empty()) + return fixMissingMember(origBaseTy, memberTy, locator); + // The result of the member access can either be the expected member type // (for '!' or optional members with '?'), or the original member type // with one extra level of optionality ('?' with non-optional members). @@ -5230,17 +5335,19 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint( return SolutionKind::Solved; } - auto solveWithNewBaseOrName = [&](Type baseType, DeclName memberName, - bool allowFixes = true) -> SolutionKind { - // Let's re-enable fixes for this member, because - // the base or member name has been changed. - if (allowFixes) - MissingMembers.remove(locator); + auto solveWithNewBaseOrName = [&](Type baseType, + DeclName memberName) -> SolutionKind { return simplifyMemberConstraint(kind, baseType, memberName, memberTy, useDC, functionRefKind, outerAlternatives, - flags, locatorB); + flags | TMF_ApplyingFix, locatorB); }; + // If this member reference is a result of a previous fix, let's not allow + // any more fixes expect when base is optional, because it could also be + // an IUO which requires a separate fix. + if (flags.contains(TMF_ApplyingFix)) + return SolutionKind::Error; + // Check if any property wrappers on the base of the member lookup have // matching members that we can fall back to, or if the type wraps any // properties that have matching members. @@ -5248,8 +5355,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint( *this, baseTy, locator, [&](ResolvedOverloadSetListItem *overload, VarDecl *decl, Type newBase) { - return solveWithNewBaseOrName(newBase, member, - /*allowFixes=*/false) == + return solveWithNewBaseOrName(newBase, member) == SolutionKind::Solved; })) { return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved; @@ -5316,29 +5422,20 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint( // fake its presence based on use, that makes it possible to diagnose // problems related to member lookup more precisely. - origBaseTy.transform([&](Type type) -> Type { - if (auto *typeVar = type->getAs()) { - if (typeVar->getImpl().hasRepresentativeOrFixed()) - return type; - // Default all of the generic parameters found in base to `Any`. - addConstraint(ConstraintKind::Defaultable, typeVar, - getASTContext().TheAnyType, - typeVar->getImpl().getLocator()); + // If base type is a "hole" there is no reason to record any + // more "member not found" fixes for chained member references. + if (auto *baseType = origBaseTy->getMetatypeInstanceType() + ->getRValueType() + ->getAs()) { + if (isHole(baseType)) { + increaseScore(SK_Fix); + if (auto *memberTypeVar = memberTy->getAs()) + recordHole(memberTypeVar); + return SolutionKind::Solved; } - return type; - }); + } - auto *fix = - DefineMemberBasedOnUse::create(*this, origBaseTy, member, locator); - if (recordFix(fix)) - return SolutionKind::Error; - - // Allow member type to default to `Any` to make it possible to form - // solutions when contextual type of the result cannot be deduced e.g. - // `let _ = x.foo`. - addConstraint(ConstraintKind::Defaultable, memberTy, - getASTContext().TheAnyType, locator); - return SolutionKind::Solved; + return fixMissingMember(origBaseTy, memberTy, locator); } return SolutionKind::Error; } @@ -6285,9 +6382,9 @@ ConstraintSystem::simplifyApplicableFnConstraint( // Let's check if this member couldn't be found and is fixed // to exist based on its usage. if (auto *memberTy = type2->getAs()) { - auto *locator = memberTy->getImpl().getLocator(); - if (MissingMembers.count(locator)) { + if (isHole(memberTy)) { auto *funcTy = type1->castTo(); + auto *locator = memberTy->getImpl().getLocator(); // Bind type variable associated with member to a type of argument // application, which makes it seem like member exists with the // types of the parameters matching argument types exactly. @@ -6295,8 +6392,9 @@ ConstraintSystem::simplifyApplicableFnConstraint( // There might be no contextual type for result of the application, // in cases like `let _ = x.foo()`, so let's default result to `Any` // to make expressions like that type-check. - addConstraint(ConstraintKind::Defaultable, funcTy->getResult(), - getASTContext().TheAnyType, locator); + auto resultTy = funcTy->getResult(); + if (auto *typeVar = resultTy->getAs()) + recordHole(typeVar); return SolutionKind::Solved; } } @@ -7241,6 +7339,15 @@ bool ConstraintSystem::recordFix(ConstraintFix *fix) { return false; } +void ConstraintSystem::recordHole(TypeVariableType *typeVar) { + assert(typeVar); + auto *locator = typeVar->getImpl().getLocator(); + if (Holes.insert(locator)) { + addConstraint(ConstraintKind::Defaultable, typeVar, + getASTContext().TheAnyType, locator); + } +} + ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( ConstraintFix *fix, Type type1, Type type2, ConstraintKind matchKind, TypeMatchOptions flags, ConstraintLocatorBuilder locator) { @@ -7288,20 +7395,6 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( return result; } - case FixKind::TreatRValueAsLValue: { - if (type2->is() || type2->is()) - type1 = LValueType::get(type1); - else - type2 = LValueType::get(type2); - auto result = matchTypes(type1, type2, - matchKind, subflags, locator); - if (result == SolutionKind::Solved) - if (recordFix(fix)) - return SolutionKind::Error; - - return result; - } - case FixKind::AutoClosureForwarding: { if (recordFix(fix)) return SolutionKind::Error; @@ -7351,6 +7444,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( case FixKind::RemoveReturn: case FixKind::AddConformance: case FixKind::RemoveAddressOf: + case FixKind::TreatRValueAsLValue: case FixKind::SkipSameTypeRequirement: case FixKind::SkipSuperclassRequirement: case FixKind::AddMissingArguments: diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index dad56f65646..329ad7aee30 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -125,12 +125,6 @@ Solution ConstraintSystem::finalize() { } solution.Fixes.append(Fixes.begin() + firstFixIndex, Fixes.end()); - // Remember all of the missing member references encountered, - // that helps diagnostics to avoid emitting error for each - // member in the chain. - for (auto *member : MissingMembers) - solution.MissingMembers.push_back(member); - // Remember all the disjunction choices we made. for (auto &choice : DisjunctionChoices) { // We shouldn't ever register disjunction choices multiple times, @@ -267,10 +261,6 @@ void ConstraintSystem::applySolution(const Solution &solution) { // Register any fixes produced along this path. Fixes.append(solution.Fixes.begin(), solution.Fixes.end()); - - // Register any missing members encountered along this path. - MissingMembers.insert(solution.MissingMembers.begin(), - solution.MissingMembers.end()); } /// Restore the type variable bindings to what they were before @@ -452,6 +442,7 @@ ConstraintSystem::SolverScope::SolverScope(ConstraintSystem &cs) numSavedBindings = cs.solverState->savedBindings.size(); numConstraintRestrictions = cs.ConstraintRestrictions.size(); numFixes = cs.Fixes.size(); + numHoles = cs.Holes.size(); numFixedRequirements = cs.FixedRequirements.size(); numDisjunctionChoices = cs.DisjunctionChoices.size(); numOpenedTypes = cs.OpenedTypes.size(); @@ -459,7 +450,6 @@ ConstraintSystem::SolverScope::SolverScope(ConstraintSystem &cs) numDefaultedConstraints = cs.DefaultedConstraints.size(); numAddedNodeTypes = cs.addedNodeTypes.size(); numCheckedConformances = cs.CheckedConformances.size(); - numMissingMembers = cs.MissingMembers.size(); numDisabledConstraints = cs.solverState->getNumDisabledConstraints(); numFavoredConstraints = cs.solverState->getNumFavoredConstraints(); numBuilderTransformedClosures = cs.builderTransformedClosures.size(); @@ -500,6 +490,9 @@ ConstraintSystem::SolverScope::~SolverScope() { // Remove any fixes. truncate(cs.Fixes, numFixes); + // Remove any holes encountered along the current path. + truncate(cs.Holes, numHoles); + // Remove any disjunction choices. truncate(cs.DisjunctionChoices, numDisjunctionChoices); @@ -525,9 +518,6 @@ ConstraintSystem::SolverScope::~SolverScope() { // Remove any conformances checked along the current path. truncate(cs.CheckedConformances, numCheckedConformances); - // Remove any missing members found along the current path. - truncate(cs.MissingMembers, numMissingMembers); - /// Remove any builder transformed closures. truncate(cs.builderTransformedClosures, numBuilderTransformedClosures); diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 1412b215e25..37ef39a94dd 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -634,9 +634,6 @@ public: /// The list of fixes that need to be applied to the initial expression /// to make the solution work. llvm::SmallVector Fixes; - /// The list of member references which couldn't be resolved, - /// and had to be assumed based on their use. - llvm::SmallVector MissingMembers; /// The set of disjunction choices used to arrive at this solution, /// which informs constraint application. @@ -1095,8 +1092,13 @@ private: /// The set of fixes applied to make the solution work. llvm::SmallVector Fixes; - /// The set of type variables representing types of missing members. - llvm::SmallSetVector MissingMembers; + + /// The set of "holes" in the constraint system encountered + /// along the current path identified by locator. A "hole" is + /// a type variable which type couldn't be determined due to + /// an inference failure e.g. missing member, ambiguous generic + /// parameter which hasn't been explicitly specified. + llvm::SmallSetVector Holes; /// The set of remembered disjunction choices used to reach /// the current constraint system. @@ -1631,6 +1633,9 @@ public: /// The length of \c Fixes. unsigned numFixes; + /// The length of \c Holes. + unsigned numHoles; + /// The length of \c FixedRequirements. unsigned numFixedRequirements; @@ -1650,8 +1655,6 @@ public: unsigned numCheckedConformances; - unsigned numMissingMembers; - unsigned numDisabledConstraints; unsigned numFavoredConstraints; @@ -2034,6 +2037,16 @@ public: /// subsequent solution would be worse than the best known solution. bool recordFix(ConstraintFix *fix); + void recordHole(TypeVariableType *typeVar); + + bool isHole(TypeVariableType *typeVar) const { + return isHoleAt(typeVar->getImpl().getLocator()); + } + + bool isHoleAt(ConstraintLocator *locator) const { + return bool(Holes.count(locator)); + } + /// Determine whether constraint system already has a fix recorded /// for a particular location. bool hasFixFor(ConstraintLocator *locator) const { @@ -2765,7 +2778,7 @@ public: /// Attempt to repair typing failures and record fixes if needed. /// \return true if at least some of the failures has been repaired /// successfully, which allows type matcher to continue. - bool repairFailures(Type lhs, Type rhs, + bool repairFailures(Type lhs, Type rhs, ConstraintKind matchKind, SmallVectorImpl &conversionsOrFixes, ConstraintLocatorBuilder locator); diff --git a/lib/Sema/IDETypeCheckingRequests.cpp b/lib/Sema/IDETypeCheckingRequests.cpp index f53d3fa0e17..579c1160df9 100644 --- a/lib/Sema/IDETypeCheckingRequests.cpp +++ b/lib/Sema/IDETypeCheckingRequests.cpp @@ -25,7 +25,7 @@ using namespace swift; namespace swift { // Implement the IDE type zone. -#define SWIFT_TYPEID_ZONE SWIFT_IDE_TYPE_CHECK_REQUESTS_TYPEID_ZONE +#define SWIFT_TYPEID_ZONE IDETypeChecking #define SWIFT_TYPEID_HEADER "swift/Sema/IDETypeCheckingRequestIDZone.def" #include "swift/Basic/ImplementTypeIDZone.h" #undef SWIFT_TYPEID_ZONE @@ -34,14 +34,14 @@ namespace swift { // Define request evaluation functions for each of the IDE type check requests. static AbstractRequestFunction *ideTypeCheckRequestFunctions[] = { -#define SWIFT_TYPEID(Name) \ +#define SWIFT_REQUEST(Zone, Name) \ reinterpret_cast(&Name::evaluateRequest), #include "swift/Sema/IDETypeCheckingRequestIDZone.def" -#undef SWIFT_TYPEID +#undef SWIFT_REQUEST }; void swift::registerIDETypeCheckRequestFunctions(Evaluator &evaluator) { - evaluator.registerRequestFunctions(SWIFT_IDE_TYPE_CHECK_REQUESTS_TYPEID_ZONE, + evaluator.registerRequestFunctions(Zone::IDETypeChecking, ideTypeCheckRequestFunctions); } diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index f3595e3e83a..da6e82b614d 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -3430,19 +3430,19 @@ static void validateTypealiasType(TypeChecker &tc, TypeAliasDecl *typeAlias) { } -/// Bind the given function declaration, which declares an operator, to -/// the corresponding operator declaration. -void bindFuncDeclToOperator(TypeChecker &TC, FuncDecl *FD) { - OperatorDecl *op = nullptr; +/// Bind the given function declaration, which declares an operator, to the corresponding operator declaration. +llvm::Expected +FunctionOperatorRequest::evaluate(Evaluator &evaluator, FuncDecl *FD) const { + auto &C = FD->getASTContext(); + auto &diags = C.Diags; auto operatorName = FD->getFullName().getBaseIdentifier(); // Check for static/final/class when we're in a type. auto dc = FD->getDeclContext(); if (dc->isTypeContext()) { if (!FD->isStatic()) { - TC.diagnose(FD->getLoc(), diag::nonstatic_operator_in_type, - operatorName, - dc->getDeclaredInterfaceType()) + FD->diagnose(diag::nonstatic_operator_in_type, + operatorName, dc->getDeclaredInterfaceType()) .fixItInsert(FD->getAttributeInsertionLoc(/*forModifier=*/true), "static "); @@ -3451,17 +3451,18 @@ void bindFuncDeclToOperator(TypeChecker &TC, FuncDecl *FD) { // For a class, we also need the function or class to be 'final'. if (!classDecl->isFinal() && !FD->isFinal() && FD->getStaticSpelling() != StaticSpellingKind::KeywordStatic) { - TC.diagnose(FD->getLoc(), diag::nonfinal_operator_in_class, - operatorName, dc->getDeclaredInterfaceType()) + FD->diagnose(diag::nonfinal_operator_in_class, + operatorName, dc->getDeclaredInterfaceType()) .fixItInsert(FD->getAttributeInsertionLoc(/*forModifier=*/true), "final "); - FD->getAttrs().add(new (TC.Context) FinalAttr(/*IsImplicit=*/true)); + FD->getAttrs().add(new (C) FinalAttr(/*IsImplicit=*/true)); } } } else if (!dc->isModuleScopeContext()) { - TC.diagnose(FD, diag::operator_in_local_scope); + FD->diagnose(diag::operator_in_local_scope); } + OperatorDecl *op = nullptr; SourceFile &SF = *FD->getDeclContext()->getParentSourceFile(); if (FD->isUnaryOperator()) { if (FD->getAttrs().hasAttribute()) { @@ -3485,13 +3486,13 @@ void bindFuncDeclToOperator(TypeChecker &TC, FuncDecl *FD) { // If we found both prefix and postfix, or neither prefix nor postfix, // complain. We can't fix this situation. if (static_cast(prefixOp) == static_cast(postfixOp)) { - TC.diagnose(FD, diag::declared_unary_op_without_attribute); + diags.diagnose(FD, diag::declared_unary_op_without_attribute); // If we found both, point at them. if (prefixOp) { - TC.diagnose(prefixOp, diag::unary_operator_declaration_here, false) + diags.diagnose(prefixOp, diag::unary_operator_declaration_here, false) .fixItInsert(FD->getLoc(), "prefix "); - TC.diagnose(postfixOp, diag::unary_operator_declaration_here, true) + diags.diagnose(postfixOp, diag::unary_operator_declaration_here, true) .fixItInsert(FD->getLoc(), "postfix "); } else { // FIXME: Introduce a Fix-It that adds the operator declaration? @@ -3499,7 +3500,7 @@ void bindFuncDeclToOperator(TypeChecker &TC, FuncDecl *FD) { // FIXME: Errors could cascade here, because name lookup for this // operator won't find this declaration. - return; + return nullptr; } // We found only one operator declaration, so we know whether this @@ -3519,10 +3520,10 @@ void bindFuncDeclToOperator(TypeChecker &TC, FuncDecl *FD) { } // Emit diagnostic with the Fix-It. - TC.diagnose(FD->getFuncLoc(), diag::unary_op_missing_prepos_attribute, + diags.diagnose(FD->getFuncLoc(), diag::unary_op_missing_prepos_attribute, static_cast(postfixOp)) .fixItInsert(FD->getFuncLoc(), insertionText); - TC.diagnose(op, diag::unary_operator_declaration_here, + diags.diagnose(op, diag::unary_operator_declaration_here, static_cast(postfixOp)); } } else if (FD->isBinaryOperator()) { @@ -3530,18 +3531,22 @@ void bindFuncDeclToOperator(TypeChecker &TC, FuncDecl *FD) { FD->isCascadingContextForLookup(false), FD->getLoc()); } else { - TC.diagnose(FD, diag::invalid_arg_count_for_operator); - return; + diags.diagnose(FD, diag::invalid_arg_count_for_operator); + return nullptr; } if (!op) { SourceLoc insertionLoc; if (isa(FD->getParent())) { - // Parent context is SourceFile, insertion location is start of func declaration - // or unary operator - insertionLoc = FD->isUnaryOperator() ? FD->getAttrs().getStartLoc() : FD->getStartLoc(); + // Parent context is SourceFile, insertion location is start of func + // declaration or unary operator + if (FD->isUnaryOperator()) { + insertionLoc = FD->getAttrs().getStartLoc(); + } else { + insertionLoc = FD->getStartLoc(); + } } else { - // Finding top-level decl context before SourceFile and inserting before it + // Find the topmost non-file decl context and insert there. for (DeclContext *CurContext = FD->getLocalContext(); !isa(CurContext); CurContext = CurContext->getParent()) { @@ -3552,25 +3557,28 @@ void bindFuncDeclToOperator(TypeChecker &TC, FuncDecl *FD) { } SmallString<128> insertion; - auto numOfParams = FD->getParameters()->size(); - if (numOfParams == 1) { - if (FD->getAttrs().hasAttribute()) - insertion += "prefix operator "; - else - insertion += "postfix operator "; - } else if (numOfParams == 2) { - insertion += "infix operator "; - } + { + llvm::raw_svector_ostream str(insertion); + assert(FD->isUnaryOperator() || FD->isBinaryOperator()); + if (FD->isUnaryOperator()) { + if (FD->getAttrs().hasAttribute()) + str << "prefix operator "; + else + str << "postfix operator "; + } else { + str << "infix operator "; + } - insertion += operatorName.str(); - insertion += " : <# Precedence Group #>\n"; - InFlightDiagnostic opDiagnostic = TC.diagnose(FD, diag::declared_operator_without_operator_decl); + str << operatorName.str() << " : <# Precedence Group #>\n"; + } + InFlightDiagnostic opDiagnostic = + diags.diagnose(FD, diag::declared_operator_without_operator_decl); if (insertionLoc.isValid()) opDiagnostic.fixItInsert(insertionLoc, insertion); - return; + return nullptr; } - FD->setOperatorDecl(op); + return op; } bool swift::isMemberOperator(FuncDecl *decl, Type type) { @@ -3868,10 +3876,9 @@ void TypeChecker::validateDecl(ValueDecl *D) { DeclValidationRAII IBV(FD); - // Bind operator functions to the corresponding operator declaration. - if (FD->isOperator()) - bindFuncDeclToOperator(*this, FD); - + // Force computing the operator decl in case it emits diagnostics. + (void) FD->getOperatorDecl(); + // Validate 'static'/'class' on functions in extensions. auto StaticSpelling = FD->getStaticSpelling(); if (StaticSpelling != StaticSpellingKind::None && diff --git a/lib/Sema/TypeCheckRequestFunctions.cpp b/lib/Sema/TypeCheckRequestFunctions.cpp index 1c5d6de7e26..5bf382b3986 100644 --- a/lib/Sema/TypeCheckRequestFunctions.cpp +++ b/lib/Sema/TypeCheckRequestFunctions.cpp @@ -234,13 +234,13 @@ FunctionBuilderTypeRequest::evaluate(Evaluator &evaluator, // Define request evaluation functions for each of the type checker requests. static AbstractRequestFunction *typeCheckerRequestFunctions[] = { -#define SWIFT_TYPEID(Name) \ +#define SWIFT_REQUEST(Zone, Name) \ reinterpret_cast(&Name::evaluateRequest), #include "swift/AST/TypeCheckerTypeIDZone.def" -#undef SWIFT_TYPEID +#undef SWIFT_REQUEST }; void swift::registerTypeCheckerRequestFunctions(Evaluator &evaluator) { - evaluator.registerRequestFunctions(SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE, + evaluator.registerRequestFunctions(Zone::TypeChecker, typeCheckerRequestFunctions); } diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index b92b3fed7a1..8c98a9d9acd 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -1835,7 +1835,7 @@ StringRef ModuleFile::getIdentifierText(IdentifierID IID) { return rawStrPtr.slice(0, terminatorOffset); } -DeclContext *ModuleFile::getLocalDeclContext(DeclContextID DCID) { +DeclContext *ModuleFile::getLocalDeclContext(LocalDeclContextID DCID) { assert(DCID != 0 && "invalid local DeclContext ID 0"); auto &declContextOrOffset = LocalDeclContexts[DCID-1]; @@ -1923,57 +1923,24 @@ DeclContext *ModuleFile::getLocalDeclContext(DeclContextID DCID) { } DeclContext *ModuleFile::getDeclContext(DeclContextID DCID) { - if (DCID == 0) + if (!DCID) return FileContext; - assert(DCID <= DeclContexts.size() && "invalid DeclContext ID"); - auto &declContextOrOffset = DeclContexts[DCID-1]; + if (Optional contextID = DCID.getAsLocalDeclContextID()) + return getLocalDeclContext(contextID.getValue()); - if (declContextOrOffset.isComplete()) - return declContextOrOffset; + auto D = getDecl(DCID.getAsDeclID().getValue()); - BCOffsetRAII restoreOffset(DeclTypeCursor); - fatalIfNotSuccess(DeclTypeCursor.JumpToBit(declContextOrOffset)); - llvm::BitstreamEntry entry = fatalIfUnexpected(DeclTypeCursor.advance()); + if (auto GTD = dyn_cast(D)) + return GTD; + if (auto ED = dyn_cast(D)) + return ED; + if (auto AFD = dyn_cast(D)) + return AFD; + if (auto SD = dyn_cast(D)) + return SD; - if (entry.Kind != llvm::BitstreamEntry::Record) - fatal(); - - SmallVector scratch; - StringRef blobData; - - unsigned recordID = fatalIfUnexpected( - DeclTypeCursor.readRecord(entry.ID, scratch, &blobData)); - - if (recordID != decls_block::DECL_CONTEXT) - llvm_unreachable("Expected a DECL_CONTEXT record"); - - DeclContextID declOrDeclContextId; - bool isDecl; - - decls_block::DeclContextLayout::readRecord(scratch, declOrDeclContextId, - isDecl); - - if (!isDecl) - return getLocalDeclContext(declOrDeclContextId); - - auto D = getDecl(declOrDeclContextId); - - if (auto ND = dyn_cast(D)) { - declContextOrOffset = ND; - } else if (auto ED = dyn_cast(D)) { - declContextOrOffset = ED; - } else if (auto AFD = dyn_cast(D)) { - declContextOrOffset = AFD; - } else if (auto SD = dyn_cast(D)) { - declContextOrOffset = SD; - } else if (auto TAD = dyn_cast(D)) { - declContextOrOffset = TAD; - } else { - llvm_unreachable("Unknown Decl : DeclContext kind"); - } - - return declContextOrOffset; + llvm_unreachable("Unknown Decl : DeclContext kind"); } ModuleDecl *ModuleFile::getModule(ModuleID MID) { @@ -3089,7 +3056,8 @@ public: if (!isAccessor) { if (Decl *associated = MF.getDecl(associatedDeclID)) { if (auto op = dyn_cast(associated)) { - fn->setOperatorDecl(op); + ctx.evaluator.cacheOutput(FunctionOperatorRequest{fn}, + std::move(op)); if (isa(op)) fn->getAttrs().add(new (ctx) PrefixAttr(/*implicit*/false)); @@ -3226,8 +3194,10 @@ public: } patterns.emplace_back(pattern.get(), DeclContextID()); - if (!initContextIDs.empty()) - patterns.back().second = initContextIDs[i]; + if (!initContextIDs.empty()) { + patterns.back().second = + DeclContextID::getFromOpaqueValue(initContextIDs[i]); + } } auto binding = diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index 149496e5ebe..b008cc4dfc1 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -987,10 +987,6 @@ bool ModuleFile::readIndexBlock(llvm::BitstreamCursor &cursor) { assert(blobData.empty()); allocateBuffer(Decls, scratch); break; - case index_block::DECL_CONTEXT_OFFSETS: - assert(blobData.empty()); - allocateBuffer(DeclContexts, scratch); - break; case index_block::TYPE_OFFSETS: assert(blobData.empty()); allocateBuffer(Types, scratch); diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index d1042809c0d..dd69f99c71a 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -526,7 +526,7 @@ static Accessors getAccessors(const AbstractStorageDecl *storage) { return accessors; } -DeclID Serializer::addLocalDeclContextRef(const DeclContext *DC) { +LocalDeclContextID Serializer::addLocalDeclContextRef(const DeclContext *DC) { assert(DC->isLocalContext() && "Expected a local DeclContext"); return LocalDeclContextsToSerialize.addRef(DC); } @@ -547,10 +547,12 @@ Serializer::addSubstitutionMapRef(SubstitutionMap substitutions) { } DeclContextID Serializer::addDeclContextRef(const DeclContext *DC) { + assert(DC && "cannot reference a null DeclContext"); + switch (DC->getContextKind()) { case DeclContextKind::Module: case DeclContextKind::FileUnit: // Skip up to the module - return 0; + return DeclContextID(); default: break; } @@ -558,11 +560,8 @@ DeclContextID Serializer::addDeclContextRef(const DeclContext *DC) { // If this decl context is a plain old serializable decl, queue it up for // normal serialization. if (shouldSerializeAsLocalContext(DC)) - addLocalDeclContextRef(DC); - else - addDeclRef(DC->getAsDecl()); - - return DeclContextsToSerialize.addRef(DC); + return DeclContextID::forLocalDeclContext(addLocalDeclContextRef(DC)); + return DeclContextID::forDecl(addDeclRef(DC->getAsDecl())); } DeclID Serializer::addDeclRef(const Decl *D, bool allowTypeAliasXRef) { @@ -751,7 +750,6 @@ void Serializer::writeBlockInfoBlock() { BLOCK_RECORD(index_block, GENERIC_SIGNATURE_OFFSETS); BLOCK_RECORD(index_block, GENERIC_ENVIRONMENT_OFFSETS); BLOCK_RECORD(index_block, SUBSTITUTION_MAP_OFFSETS); - BLOCK_RECORD(index_block, DECL_CONTEXT_OFFSETS); BLOCK_RECORD(index_block, LOCAL_TYPE_DECLS); BLOCK_RECORD(index_block, NORMAL_CONFORMANCE_OFFSETS); BLOCK_RECORD(index_block, SIL_LAYOUT_OFFSETS); @@ -1179,7 +1177,7 @@ void Serializer::writeGenericRequirements(ArrayRef requirements, } } -void Serializer::writeGenericSignature(const GenericSignature *sig) { +void Serializer::writeASTBlockEntity(const GenericSignature *sig) { using namespace decls_block; assert(sig != nullptr); @@ -1259,7 +1257,7 @@ void Serializer::writeGenericEnvironment(const GenericEnvironment *env) { DeclTypeAbbrCodes); } -void Serializer::writeSubstitutionMap(const SubstitutionMap substitutions) { +void Serializer::writeASTBlockEntity(const SubstitutionMap substitutions) { using namespace decls_block; assert(substitutions); assert(SubstitutionMapsToSerialize.hasRef(substitutions)); @@ -1279,7 +1277,7 @@ void Serializer::writeSubstitutionMap(const SubstitutionMap substitutions) { writeConformances(substitutions.getConformances(), DeclTypeAbbrCodes); } -void Serializer::writeSILLayout(const SILLayout *layout) { +void Serializer::writeASTBlockEntity(const SILLayout *layout) { using namespace decls_block; assert(SILLayoutsToSerialize.hasRef(layout)); @@ -1303,7 +1301,7 @@ void Serializer::writeSILLayout(const SILLayout *layout) { data); } -void Serializer::writeNormalConformance( +void Serializer::writeASTBlockEntity( const NormalProtocolConformance *conformance) { using namespace decls_block; @@ -1360,7 +1358,8 @@ void Serializer::writeNormalConformance( = DeclTypeAbbrCodes[NormalProtocolConformanceLayout::Code]; auto ownerID = addDeclContextRef(conformance->getDeclContext()); NormalProtocolConformanceLayout::emitRecord(Out, ScratchRecord, abbrCode, - addDeclRef(protocol), ownerID, + addDeclRef(protocol), + ownerID.getOpaqueValue(), numTypeWitnesses, numValueWitnesses, numSignatureConformances, @@ -1884,40 +1883,6 @@ bool Serializer::isDeclXRef(const Decl *D) const { return true; } -void Serializer::writeDeclContext(const DeclContext *DC) { - using namespace decls_block; - assert(DeclContextsToSerialize.hasRef(DC) && "not referenced properly"); - - auto abbrCode = DeclTypeAbbrCodes[DeclContextLayout::Code]; - DeclContextID declOrDeclContextID = 0; - auto isDecl = false; - - switch (DC->getContextKind()) { - case DeclContextKind::AbstractFunctionDecl: - case DeclContextKind::SubscriptDecl: - case DeclContextKind::GenericTypeDecl: - case DeclContextKind::ExtensionDecl: - case DeclContextKind::EnumElementDecl: - declOrDeclContextID = addDeclRef(DC->getAsDecl()); - isDecl = true; - break; - - case DeclContextKind::TopLevelCodeDecl: - case DeclContextKind::AbstractClosureExpr: - case DeclContextKind::Initializer: - case DeclContextKind::SerializedLocal: - declOrDeclContextID = addLocalDeclContextRef(DC); - break; - case DeclContextKind::Module: - llvm_unreachable("References to the module are serialized implicitly"); - case DeclContextKind::FileUnit: - llvm_unreachable("Can't serialize a FileUnit"); - } - - DeclContextLayout::emitRecord(Out, ScratchRecord, abbrCode, - declOrDeclContextID, isDecl); -} - void Serializer::writePatternBindingInitializer(PatternBindingDecl *binding, unsigned bindingIndex) { using namespace decls_block; @@ -1942,8 +1907,9 @@ Serializer::writeDefaultArgumentInitializer(const DeclContext *parentContext, unsigned index) { using namespace decls_block; auto abbrCode = DeclTypeAbbrCodes[DefaultArgumentInitializerLayout::Code]; + auto parentID = addDeclContextRef(parentContext); DefaultArgumentInitializerLayout::emitRecord(Out, ScratchRecord, abbrCode, - addDeclContextRef(parentContext), + parentID.getOpaqueValue(), index); } @@ -1952,17 +1918,18 @@ void Serializer::writeAbstractClosureExpr(const DeclContext *parentContext, unsigned discriminator) { using namespace decls_block; auto abbrCode = DeclTypeAbbrCodes[AbstractClosureExprLayout::Code]; + auto parentID = addDeclContextRef(parentContext); AbstractClosureExprLayout::emitRecord(Out, ScratchRecord, abbrCode, addTypeRef(Ty), isImplicit, discriminator, - addDeclContextRef(parentContext)); + parentID.getOpaqueValue()); } -void Serializer::writeLocalDeclContext(const DeclContext *DC) { +void Serializer::writeASTBlockEntity(const DeclContext *DC) { using namespace decls_block; assert(shouldSerializeAsLocalContext(DC) && - "Can't serialize as local context"); + "should be serialized as a Decl instead"); assert(LocalDeclContextsToSerialize.hasRef(DC)); switch (DC->getContextKind()) { @@ -1985,7 +1952,7 @@ void Serializer::writeLocalDeclContext(const DeclContext *DC) { case DeclContextKind::TopLevelCodeDecl: { auto abbrCode = DeclTypeAbbrCodes[TopLevelCodeDeclContextLayout::Code]; TopLevelCodeDeclContextLayout::emitRecord(Out, ScratchRecord, abbrCode, - addDeclContextRef(DC->getParent())); + addDeclContextRef(DC->getParent()).getOpaqueValue()); break; } @@ -2013,7 +1980,7 @@ void Serializer::writeLocalDeclContext(const DeclContext *DC) { case LocalDeclContextKind::TopLevelCodeDecl: { auto abbrCode = DeclTypeAbbrCodes[TopLevelCodeDeclContextLayout::Code]; TopLevelCodeDeclContextLayout::emitRecord(Out, ScratchRecord, - abbrCode, addDeclContextRef(DC->getParent())); + abbrCode, addDeclContextRef(DC->getParent()).getOpaqueValue()); return; } } @@ -2749,7 +2716,7 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[ExtensionLayout::Code]; ExtensionLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, S.addTypeRef(baseTy), - contextID, + contextID.getOpaqueValue(), extension->isImplicit(), S.addGenericEnvironmentRef( extension->getGenericEnvironment()), @@ -2791,17 +2758,17 @@ public: auto initContextID = S.addDeclContextRef(binding->getPatternList()[i].getInitContext()); if (!initContextIDs.empty()) { - initContextIDs.push_back(initContextID); + initContextIDs.push_back(initContextID.getOpaqueValue()); } else if (initContextID) { initContextIDs.append(i, 0); - initContextIDs.push_back(initContextID); + initContextIDs.push_back(initContextID.getOpaqueValue()); } } unsigned abbrCode = S.DeclTypeAbbrCodes[PatternBindingLayout::Code]; PatternBindingLayout::emitRecord( - S.Out, S.ScratchRecord, abbrCode, contextID, binding->isImplicit(), - binding->isStatic(), + S.Out, S.ScratchRecord, abbrCode, contextID.getOpaqueValue(), + binding->isImplicit(), binding->isStatic(), uint8_t(getStableStaticSpelling(binding->getStaticSpelling())), binding->getNumPatternEntries(), initContextIDs); @@ -2832,8 +2799,8 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[PrecedenceGroupLayout::Code]; PrecedenceGroupLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, - nameID, contextID, associativity, - group->isAssignment(), + nameID, contextID.getOpaqueValue(), + associativity, group->isAssignment(), group->getHigherThan().size(), relations); } @@ -2851,7 +2818,7 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[InfixOperatorLayout::Code]; InfixOperatorLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, nameID, - contextID, groupID, + contextID.getOpaqueValue(), groupID, designatedNominalTypeDeclIDs); } @@ -2866,7 +2833,8 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[Layout::Code]; Layout::emitRecord(S.Out, S.ScratchRecord, abbrCode, S.addDeclBaseNameRef(op->getName()), - contextID, designatedNominalTypeDeclIDs); + contextID.getOpaqueValue(), + designatedNominalTypeDeclIDs); } void visitPrefixOperatorDecl(const PrefixOperatorDecl *op) { @@ -2908,7 +2876,7 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[TypeAliasLayout::Code]; TypeAliasLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, S.addDeclBaseNameRef(typeAlias->getName()), - contextID, + contextID.getOpaqueValue(), S.addTypeRef(underlying), /*no longer used*/TypeID(), typeAlias->isImplicit(), @@ -2945,7 +2913,7 @@ public: AssociatedTypeDeclLayout::emitRecord( S.Out, S.ScratchRecord, abbrCode, S.addDeclBaseNameRef(assocType->getName()), - contextID, + contextID.getOpaqueValue(), S.addTypeRef(assocType->getDefaultDefinitionType()), assocType->isImplicit(), overriddenAssocTypeIDs); @@ -2980,7 +2948,7 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[StructLayout::Code]; StructLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, S.addDeclBaseNameRef(theStruct->getName()), - contextID, + contextID.getOpaqueValue(), theStruct->isImplicit(), theStruct->isObjC(), S.addGenericEnvironmentRef( @@ -3037,7 +3005,7 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[EnumLayout::Code]; EnumLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, S.addDeclBaseNameRef(theEnum->getName()), - contextID, + contextID.getOpaqueValue(), theEnum->isImplicit(), theEnum->isObjC(), S.addGenericEnvironmentRef( @@ -3096,7 +3064,7 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[ClassLayout::Code]; ClassLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, S.addDeclBaseNameRef(theClass->getName()), - contextID, + contextID.getOpaqueValue(), theClass->isImplicit(), theClass->isObjC(), inheritsSuperclassInitializers, @@ -3146,7 +3114,7 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[ProtocolLayout::Code]; ProtocolLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, S.addDeclBaseNameRef(proto->getName()), - contextID, + contextID.getOpaqueValue(), proto->isImplicit(), const_cast(proto) ->requiresClass(), @@ -3206,7 +3174,7 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[VarLayout::Code]; VarLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, S.addDeclBaseNameRef(var->getName()), - contextID, + contextID.getOpaqueValue(), var->isImplicit(), var->isObjC(), var->isStatic(), @@ -3252,7 +3220,7 @@ public: ParamLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, S.addDeclBaseNameRef(param->getArgumentName()), S.addDeclBaseNameRef(param->getName()), - contextID, + contextID.getOpaqueValue(), getRawStableParamDeclSpecifier(param->getSpecifier()), S.addTypeRef(interfaceType), param->isImplicitlyUnwrappedOptional(), @@ -3288,7 +3256,7 @@ public: nameComponentsAndDependencies.push_back(S.addTypeRef(dependency)); FuncLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, - contextID, + contextID.getOpaqueValue(), fn->isImplicit(), fn->isStatic(), uint8_t( @@ -3341,8 +3309,8 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[OpaqueTypeLayout::Code]; OpaqueTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, - contextID, namingDeclID, interfaceSigID, - interfaceTypeID, genericEnvID, + contextID.getOpaqueValue(), namingDeclID, + interfaceSigID, interfaceTypeID, genericEnvID, underlyingTypeID); writeGenericParams(opaqueDecl->getGenericParams()); } @@ -3376,7 +3344,7 @@ public: dependencies.push_back(S.addTypeRef(dependency)); AccessorLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, - contextID, + contextID.getOpaqueValue(), fn->isImplicit(), fn->isStatic(), uint8_t(getStableStaticSpelling( @@ -3441,7 +3409,7 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[EnumElementLayout::Code]; EnumElementLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, - contextID, + contextID.getOpaqueValue(), elem->isImplicit(), elem->hasAssociatedValues(), (unsigned)rawValueKind, @@ -3486,7 +3454,7 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[SubscriptLayout::Code]; SubscriptLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, - contextID, + contextID.getOpaqueValue(), subscript->isImplicit(), subscript->isObjC(), subscript->isGetterMutating(), @@ -3537,7 +3505,7 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[ConstructorLayout::Code]; ConstructorLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, - contextID, + contextID.getOpaqueValue(), ctor->isFailable(), ctor->isImplicitlyUnwrappedOptional(), ctor->isImplicit(), @@ -3572,7 +3540,7 @@ public: unsigned abbrCode = S.DeclTypeAbbrCodes[DestructorLayout::Code]; DestructorLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, - contextID, + contextID.getOpaqueValue(), dtor->isImplicit(), dtor->isObjC(), S.addGenericEnvironmentRef( @@ -3609,7 +3577,7 @@ public: } }; -void Serializer::writeDecl(const Decl *D) { +void Serializer::writeASTBlockEntity(const Decl *D) { using namespace decls_block; PrettyStackTraceDecl trace("serializing", D); @@ -4135,7 +4103,7 @@ public: } }; -void Serializer::writeType(Type ty) { +void Serializer::writeASTBlockEntity(Type ty) { using namespace decls_block; PrettyStackTraceType traceRAII(ty->getASTContext(), "serializing", ty); assert(TypesToSerialize.hasRef(ty)); @@ -4152,6 +4120,16 @@ void Serializer::writeType(Type ty) { TypeSerializer(*this).visit(ty); } +template +bool Serializer::writeASTBlockEntitiesIfNeeded( + SpecificASTBlockRecordKeeper &entities) { + if (!entities.hasMoreToSerialize()) + return false; + while (auto next = entities.popNext(Out.GetCurrentBitNo())) + writeASTBlockEntity(next.getValue()); + return true; +} + void Serializer::writeAllDeclsAndTypes() { BCBlockRAII restoreBlock(Out, DECLS_AND_TYPES_BLOCK_ID, 8); using namespace decls_block; @@ -4226,7 +4204,6 @@ void Serializer::writeAllDeclsAndTypes() { registerDeclTypeAbbr(); registerDeclTypeAbbr(); - registerDeclTypeAbbr(); registerDeclTypeAbbr(); registerDeclTypeAbbr(); registerDeclTypeAbbr(); @@ -4267,55 +4244,25 @@ void Serializer::writeAllDeclsAndTypes() { // until /all/ of the pending lists are empty. wroteSomething = false; - while (auto next = DeclsToSerialize.popNext(Out.GetCurrentBitNo())) { - writeDecl(next.getValue()); - wroteSomething = true; - } - - while (auto next = TypesToSerialize.popNext(Out.GetCurrentBitNo())) { - writeType(next.getValue()); - wroteSomething = true; - } - - while (auto next = - LocalDeclContextsToSerialize.popNext(Out.GetCurrentBitNo())) { - writeLocalDeclContext(next.getValue()); - wroteSomething = true; - } - - while (auto next = DeclContextsToSerialize.popNext(Out.GetCurrentBitNo())) { - writeDeclContext(next.getValue()); - wroteSomething = true; - } - - while (auto next = - GenericSignaturesToSerialize.popNext(Out.GetCurrentBitNo())) { - writeGenericSignature(next.getValue()); - wroteSomething = true; - } + wroteSomething |= writeASTBlockEntitiesIfNeeded(DeclsToSerialize); + wroteSomething |= writeASTBlockEntitiesIfNeeded(TypesToSerialize); + wroteSomething |= + writeASTBlockEntitiesIfNeeded(LocalDeclContextsToSerialize); + wroteSomething |= + writeASTBlockEntitiesIfNeeded(GenericSignaturesToSerialize); + wroteSomething |= + writeASTBlockEntitiesIfNeeded(SubstitutionMapsToSerialize); + wroteSomething |= + writeASTBlockEntitiesIfNeeded(NormalConformancesToSerialize); + wroteSomething |= writeASTBlockEntitiesIfNeeded(SILLayoutsToSerialize); + // Generic environments are recorded in a funny way; see + // writeNextGenericEnvironment() for why they can't just use the same logic + // as everything else. while (GenericEnvironmentsToSerialize.hasMoreToSerialize()) { writeNextGenericEnvironment(); wroteSomething = true; } - - while (auto next = - SubstitutionMapsToSerialize.popNext(Out.GetCurrentBitNo())) { - writeSubstitutionMap(next.getValue()); - wroteSomething = true; - } - - while (auto next = - NormalConformancesToSerialize.popNext(Out.GetCurrentBitNo())) { - writeNormalConformance(next.getValue()); - wroteSomething = true; - } - - while (auto next = SILLayoutsToSerialize.popNext(Out.GetCurrentBitNo())) { - writeSILLayout(next.getValue()); - wroteSomething = true; - } - } while (wroteSomething); } @@ -4758,7 +4705,6 @@ void Serializer::writeAST(ModuleOrSourceFile DC, index_block::OffsetsLayout Offsets(Out); writeOffsets(Offsets, DeclsToSerialize); writeOffsets(Offsets, TypesToSerialize); - writeOffsets(Offsets, DeclContextsToSerialize); writeOffsets(Offsets, LocalDeclContextsToSerialize); writeOffsets(Offsets, GenericSignaturesToSerialize); writeOffsets(Offsets, GenericEnvironmentsToSerialize); diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h index 108c7c938d2..02e983b332a 100644 --- a/lib/Serialization/Serialization.h +++ b/lib/Serialization/Serialization.h @@ -193,11 +193,7 @@ class Serializer : public SerializerBase { index_block::TYPE_OFFSETS> TypesToSerialize; - ASTBlockRecordKeeper - DeclContextsToSerialize; - - ASTBlockRecordKeeper LocalDeclContextsToSerialize; @@ -303,13 +299,10 @@ private: void writeCrossReference(const Decl *D); /// Writes the given decl. - void writeDecl(const Decl *D); - - /// Writes the given decl context. - void writeDeclContext(const DeclContext *DC); + void writeASTBlockEntity(const Decl *D); /// Write a DeclContext as a local DeclContext at the current offset. - void writeLocalDeclContext(const DeclContext *DC); + void writeASTBlockEntity(const DeclContext *DC); /// Write the components of a PatternBindingInitializer as a local context. void writePatternBindingInitializer(PatternBindingDecl *binding, @@ -322,10 +315,10 @@ private: void writeAbstractClosureExpr(const DeclContext *parentContext, Type Ty, bool isImplicit, unsigned discriminator); /// Writes the given type. - void writeType(Type ty); + void writeASTBlockEntity(Type ty); /// Writes a generic signature. - void writeGenericSignature(const GenericSignature *sig); + void writeASTBlockEntity(const GenericSignature *sig); /// Writes the next generic environment in #GenericEnvironmentsToSerialize. /// @@ -337,7 +330,7 @@ private: void writeGenericEnvironment(const GenericEnvironment *env); /// Writes a substitution map. - void writeSubstitutionMap(const SubstitutionMap substitutions); + void writeASTBlockEntity(const SubstitutionMap substitutions); /// Registers the abbreviation for the given decl or type layout. template @@ -348,6 +341,12 @@ private: DeclTypeAbbrCodes[Layout::Code] = Layout::emitAbbrev(Out); } + /// Writes all queued \p entities until there are no more. + /// + /// \returns true if any entities were written + template + bool writeASTBlockEntitiesIfNeeded(SpecificASTBlockRecordKeeper &entities); + /// Writes all decls and types in the DeclsToWrite queue. /// /// This will continue until the queue is empty, even if the items currently @@ -436,7 +435,7 @@ public: /// Records the use of the given local DeclContext. /// /// The DeclContext will be scheduled for serialization if necessary. - DeclContextID addLocalDeclContextRef(const DeclContext *DC); + LocalDeclContextID addLocalDeclContextRef(const DeclContext *DC); /// Records the use of the given generic signature. /// @@ -477,10 +476,10 @@ public: IdentifierID addContainingModuleRef(const DeclContext *DC); /// Write a normal protocol conformance. - void writeNormalConformance(const NormalProtocolConformance *conformance); + void writeASTBlockEntity(const NormalProtocolConformance *conformance); /// Write a SILLayout. - void writeSILLayout(const SILLayout *layout); + void writeASTBlockEntity(const SILLayout *layout); /// Writes a protocol conformance. /// diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index fbc5d8f4c26..f0d4402ffc1 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -104,8 +104,10 @@ Optional forEachModuleSearchPath( // Defined out-of-line so that we can see ~ModuleFile. SerializedModuleLoaderBase::SerializedModuleLoaderBase( - ASTContext &ctx, DependencyTracker *tracker, ModuleLoadingMode loadMode) - : ModuleLoader(tracker), Ctx(ctx), LoadMode(loadMode) {} + ASTContext &ctx, DependencyTracker *tracker, ModuleLoadingMode loadMode, + ArrayRef PreferInterfaceForModules) + : ModuleLoader(tracker), Ctx(ctx), LoadMode(loadMode), + PreferInterfaceForModules(PreferInterfaceForModules) {} SerializedModuleLoaderBase::~SerializedModuleLoaderBase() = default; SerializedModuleLoader::~SerializedModuleLoader() = default; diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt index b13de5f0fb5..c3f5bb29e4e 100644 --- a/stdlib/public/core/CMakeLists.txt +++ b/stdlib/public/core/CMakeLists.txt @@ -288,8 +288,6 @@ if(SWIFT_STDLIB_ENABLE_STDLIBCORE_EXCLUSIVITY_CHECKING) list(APPEND swift_stdlib_compile_flags "-enforce-exclusivity=checked") endif() -list(APPEND swift_stdlib_compile_flags "-Xfrontend" "-enable-ownership-stripping-after-serialization") - if(SWIFT_CHECK_ESSENTIAL_STDLIB) add_swift_target_library(swift_stdlib_essential ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB IS_STDLIB_CORE INSTALL_IN_COMPONENT never_install diff --git a/test/ParseableInterface/Inputs/enums-layout-helper.swift b/test/ParseableInterface/Inputs/enums-layout-helper.swift index 09026e45308..738434ffea4 100644 --- a/test/ParseableInterface/Inputs/enums-layout-helper.swift +++ b/test/ParseableInterface/Inputs/enums-layout-helper.swift @@ -76,6 +76,20 @@ public enum FutureproofIndirectCaseEnum { case c } +// CHECK-LABEL: public enum FutureproofIndirectMultiCaseEnum +public enum FutureproofIndirectMultiCaseEnum { + // CHECK-SINGLE-FRONTEND-NEXT: {{^}} case a1, a2{{$}} + // CHECK-MULTI-FILE-NEXT: {{^}} case a1{{$}} + // CHECK-MULTI-FILE-NEXT: {{^}} case a2{{$}} + case a1, a2 + // CHECK-SINGLE-FRONTEND-NEXT: indirect case b1(Swift.Int), b2(Swift.Int){{$}} + // CHECK-MULTI-FILE-NEXT: indirect case b1(Swift.Int){{$}} + // CHECK-MULTI-FILE-NEXT: indirect case b2(Swift.Int){{$}} + indirect case b1(Int), b2(Int) + // CHECK-NEXT: {{^}} case c{{$}} + case c +} + // CHECK-LABEL: public enum FrozenIndirectCaseEnum @_frozen public enum FrozenIndirectCaseEnum { // CHECK-NEXT: {{^}} case a{{$}} @@ -85,3 +99,17 @@ public enum FutureproofIndirectCaseEnum { // CHECK-NEXT: {{^}} case c{{$}} case c } + +// CHECK-LABEL: public enum FrozenIndirectMultiCaseEnum +@_frozen public enum FrozenIndirectMultiCaseEnum { + // CHECK-SINGLE-FRONTEND-NEXT: {{^}} case a1, a2{{$}} + // CHECK-MULTI-FILE-NEXT: {{^}} case a1{{$}} + // CHECK-MULTI-FILE-NEXT: {{^}} case a2{{$}} + case a1, a2 + // CHECK-SINGLE-FRONTEND-NEXT: indirect case b1(Swift.Int), b2(Swift.Int){{$}} + // CHECK-MULTI-FILE-NEXT: indirect case b1(Swift.Int){{$}} + // CHECK-MULTI-FILE-NEXT: indirect case b2(Swift.Int){{$}} + indirect case b1(Int), b2(Int) + // CHECK-NEXT: {{^}} case c{{$}} + case c +} diff --git a/test/ParseableInterface/enums-layout.swift b/test/ParseableInterface/enums-layout.swift index 72bcc7d0d33..6541a522b65 100644 --- a/test/ParseableInterface/enums-layout.swift +++ b/test/ParseableInterface/enums-layout.swift @@ -1,12 +1,12 @@ // RUN: %empty-directory(%t) // RUN: %target-build-swift -emit-module-interface-path %t/Lib.swiftinterface -emit-module -o %t/unused.swiftmodule -enable-library-evolution -Xfrontend -enable-objc-interop -Xfrontend -disable-objc-attr-requires-foundation-module -swift-version 5 %S/Inputs/enums-layout-helper.swift -module-name Lib -// RUN: %FileCheck %S/Inputs/enums-layout-helper.swift < %t/Lib.swiftinterface +// RUN: %FileCheck -check-prefix CHECK -check-prefix CHECK-MULTI-FILE %S/Inputs/enums-layout-helper.swift < %t/Lib.swiftinterface // RUN: %target-swift-frontend -enable-objc-interop -O -emit-ir -primary-file %s -I %t -Xllvm -swiftmergefunc-threshold=0 | %FileCheck %s // Try again using a single-frontend build. // RUN: %empty-directory(%t) // RUN: %target-build-swift -force-single-frontend-invocation -emit-module-interface-path %t/Lib.swiftinterface -emit-module -o %t/unused.swiftmodule -enable-library-evolution -Xfrontend -enable-objc-interop -Xfrontend -disable-objc-attr-requires-foundation-module -swift-version 5 %S/Inputs/enums-layout-helper.swift -module-name Lib -// RUN: %FileCheck %S/Inputs/enums-layout-helper.swift < %t/Lib.swiftinterface +// RUN: %FileCheck -check-prefix CHECK -check-prefix CHECK-SINGLE-FRONTEND %S/Inputs/enums-layout-helper.swift < %t/Lib.swiftinterface // RUN: %target-swift-frontend -enable-objc-interop -O -emit-ir -primary-file %s -I %t -Xllvm -swiftmergefunc-threshold=0 | %FileCheck %s diff --git a/test/SILOptimizer/semantic-arc-opts.sil b/test/SILOptimizer/semantic-arc-opts.sil index 2aefc947e88..13f20bcbc0a 100644 --- a/test/SILOptimizer/semantic-arc-opts.sil +++ b/test/SILOptimizer/semantic-arc-opts.sil @@ -10,12 +10,15 @@ import Builtin sil @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () sil @owned_user : $@convention(thin) (@owned Builtin.NativeObject) -> () +sil @get_owned_obj : $@convention(thin) () -> @owned Builtin.NativeObject struct NativeObjectPair { var obj1 : Builtin.NativeObject var obj2 : Builtin.NativeObject } +sil @get_nativeobject_pair : $@convention(thin) () -> @owned NativeObjectPair + class Klass {} struct MyInt { @@ -679,3 +682,97 @@ bb0(%x : @owned $ClassLet): return undef : $() } + +// Make sure that we properly eliminate all ref count ops except for the destroy +// for the @owned argument. The recursion happens since we can not eliminate the +// begin_borrow without eliminating the struct_extract (which we do after we +// eliminate the destroy_value). +// CHECK-LABEL: sil [ossa] @worklist_test : $@convention(thin) (@owned NativeObjectPair) -> () { +// CHECK-NOT: struct_extract +// CHECK: } // end sil function 'worklist_test' +sil [ossa] @worklist_test : $@convention(thin) (@owned NativeObjectPair) -> () { +bb0(%0 : @owned $NativeObjectPair): + %1 = begin_borrow %0 : $NativeObjectPair + %2 = struct_extract %1 : $NativeObjectPair, #NativeObjectPair.obj1 + %3 = copy_value %2 : $Builtin.NativeObject + br bb1 + +bb1: + destroy_value %3 : $Builtin.NativeObject + end_borrow %1 : $NativeObjectPair + destroy_value %0 : $NativeObjectPair + %9999 = tuple() + return %9999 : $() +} + +// CHECK-LABEL: sil [ossa] @begin_borrow_simple : $@convention(thin) () -> () { +// CHECK-NOT: copy_value +// CHECK: } // end sil function 'begin_borrow_simple' +sil [ossa] @begin_borrow_simple : $@convention(thin) () -> () { +bb0: + %0 = function_ref @get_nativeobject_pair : $@convention(thin) () -> @owned NativeObjectPair + %1 = apply %0() : $@convention(thin) () -> @owned NativeObjectPair + %2 = begin_borrow %1 : $NativeObjectPair + %3 = struct_extract %2 : $NativeObjectPair, #NativeObjectPair.obj1 + %4 = copy_value %3 : $Builtin.NativeObject + %5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () + apply %5(%4) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () + destroy_value %4 : $Builtin.NativeObject + end_borrow %2 : $NativeObjectPair + destroy_value %1 : $NativeObjectPair + %9999 = tuple() + return %9999 : $() +} + +// CHECK-LABEL: sil [ossa] @begin_borrow_fail : $@convention(thin) () -> () { +// CHECK: copy_value +// CHECK: } // end sil function 'begin_borrow_fail' +sil [ossa] @begin_borrow_fail : $@convention(thin) () -> () { +bb0: + %0 = function_ref @get_nativeobject_pair : $@convention(thin) () -> @owned NativeObjectPair + %1 = apply %0() : $@convention(thin) () -> @owned NativeObjectPair + %2 = begin_borrow %1 : $NativeObjectPair + %3 = struct_extract %2 : $NativeObjectPair, #NativeObjectPair.obj1 + %4 = copy_value %3 : $Builtin.NativeObject + %5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () + apply %5(%4) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () + end_borrow %2 : $NativeObjectPair + destroy_value %4 : $Builtin.NativeObject + destroy_value %1 : $NativeObjectPair + %9999 = tuple() + return %9999 : $() +} + +// CHECK-LABEL: sil [ossa] @load_borrow_simple : $@convention(thin) (@in NativeObjectPair) -> () { +// CHECK-NOT: copy_value +// CHECK: } // end sil function 'load_borrow_simple' +sil [ossa] @load_borrow_simple : $@convention(thin) (@in NativeObjectPair) -> () { +bb0(%0 : $*NativeObjectPair): + %2 = load_borrow %0 : $*NativeObjectPair + %3 = struct_extract %2 : $NativeObjectPair, #NativeObjectPair.obj1 + %4 = copy_value %3 : $Builtin.NativeObject + %5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () + apply %5(%4) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () + destroy_value %4 : $Builtin.NativeObject + end_borrow %2 : $NativeObjectPair + destroy_addr %0 : $*NativeObjectPair + %9999 = tuple() + return %9999 : $() +} + +// CHECK-LABEL: sil [ossa] @load_borrow_fail : $@convention(thin) (@in NativeObjectPair) -> () { +// CHECK: copy_value +// CHECK: } // end sil function 'load_borrow_fail' +sil [ossa] @load_borrow_fail : $@convention(thin) (@in NativeObjectPair) -> () { +bb0(%0 : $*NativeObjectPair): + %2 = load_borrow %0 : $*NativeObjectPair + %3 = struct_extract %2 : $NativeObjectPair, #NativeObjectPair.obj1 + %4 = copy_value %3 : $Builtin.NativeObject + %5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () + apply %5(%4) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () + end_borrow %2 : $NativeObjectPair + destroy_value %4 : $Builtin.NativeObject + destroy_addr %0 : $*NativeObjectPair + %9999 = tuple() + return %9999 : $() +} \ No newline at end of file diff --git a/test/Sema/diag_ambiguous_overloads.swift b/test/Sema/diag_ambiguous_overloads.swift index 9026ae43b0e..a80fdb1c588 100644 --- a/test/Sema/diag_ambiguous_overloads.swift +++ b/test/Sema/diag_ambiguous_overloads.swift @@ -94,8 +94,6 @@ class sr7440_Genre { return sr7440_Genre.fetch(genreID: iTunesGenre.genreID, name: iTunesGenre.name) // expected-error@-1 {{value of type 'sr7440_ITunesGenre' has no member 'genreID'; did you mean 'genre'?}} // expected-error@-2 {{cannot convert return expression of type '()' to return type 'sr7440_Genre'}} -// expected-error@-3 {{protocol type 'Any' cannot conform to 'BinaryInteger' because only concrete types can conform to protocols}} -// TODO(diagnostics): Last diagnostic should not be recorded but to be able to correctly handle it we need a notion of a "hole" in constraint system. } } diff --git a/test/api-digester/Outputs/Cake-interface-vs-binary.txt b/test/api-digester/Outputs/Cake-interface-vs-binary.txt new file mode 100644 index 00000000000..5a867d2fad1 --- /dev/null +++ b/test/api-digester/Outputs/Cake-interface-vs-binary.txt @@ -0,0 +1,12 @@ +cake: Func FrozenKind.__derived_enum_equals(_:_:) has been removed +cake: Accessor GlobalLetChangedToVar.Get() is a new API without @available attribute +cake: Accessor GlobalVarChangedToLet.Get() is a new API without @available attribute +cake: Accessor GlobalVarChangedToLet.Modify() is a new API without @available attribute +cake: Accessor GlobalVarChangedToLet.Set() is a new API without @available attribute +cake: Class C4 is now with @objc +cake: Enum FrozenKind is now with @frozen +cake: Enum IceKind is now with @frozen +cake: Func FrozenKind.==(_:_:) is a new API without @available attribute +cake: Var C1.CIIns1 is no longer a stored property +cake: Var C1.CIIns2 is no longer a stored property +cake: Var RemoveSetters.Value is no longer a stored property diff --git a/test/api-digester/compare-dump-interface-vs-binary.swift b/test/api-digester/compare-dump-interface-vs-binary.swift new file mode 100644 index 00000000000..b94c2529342 --- /dev/null +++ b/test/api-digester/compare-dump-interface-vs-binary.swift @@ -0,0 +1,23 @@ +// RUN: %empty-directory(%t.mod1) +// RUN: %empty-directory(%t.mod2) +// RUN: %empty-directory(%t.sdk) +// RUN: %empty-directory(%t.module-cache) + +// Generate .swiftinterface file for module cake +// RUN: %target-swift-frontend -typecheck -emit-parseable-module-interface-path %t.mod1/cake.swiftinterface %S/Inputs/cake_baseline/cake.swift -I %S/Inputs/APINotesLeft %clang-importer-sdk-nosource -parse-as-library -enable-library-evolution -disable-objc-attr-requires-foundation-module -module-cache-path %t.module-cache + +// Generate .swiftmodule file for module cake +// RUN: %target-swift-frontend -emit-module -o %t.mod1/cake.swiftmodule %S/Inputs/cake_baseline/cake.swift -I %S/Inputs/APINotesLeft %clang-importer-sdk-nosource -parse-as-library -disable-objc-attr-requires-foundation-module -module-cache-path %t.module-cache + +// Dump Json file for cake ABI via .swiftmodule file +// RUN: %api-digester -dump-sdk -module cake -o - -module-cache-path %t.module-cache %clang-importer-sdk-nosource -I %t.mod1 -I %S/Inputs/APINotesLeft -abi > %t.dump1.json + +// Dump Json file for cake ABI via .swiftinteface file +// RUN: %api-digester -dump-sdk -module cake -o - -module-cache-path %t.module-cache %clang-importer-sdk-nosource -I %t.mod1 -I %S/Inputs/APINotesLeft -abi -use-interface-for-module cake > %t.dump2.json + +// Compare two Json files and we should see some differences. +// RUN: %api-digester -diagnose-sdk -print-module --input-paths %t.dump1.json -input-paths %t.dump2.json -abi -o %t.result + +// RUN: %clang -E -P -x c %S/Outputs/Cake-interface-vs-binary.txt -o - | sed '/^\s*$/d' > %t.expected +// RUN: %clang -E -P -x c %t.result -o - | sed '/^\s*$/d' > %t.result.tmp +// RUN: diff -u %t.expected %t.result.tmp diff --git a/test/decl/class/circular_inheritance.swift b/test/decl/class/circular_inheritance.swift index 06ab90d8955..b5578bab467 100644 --- a/test/decl/class/circular_inheritance.swift +++ b/test/decl/class/circular_inheritance.swift @@ -59,6 +59,7 @@ class Outer3 // expected-error {{circular reference}} protocol Initable { init() // expected-note@-1 {{protocol requires initializer 'init()' with type '()'; do you want to add a stub?}} + // expected-note@-2 {{did you mean 'init'?}} } protocol Shape : Circle {} diff --git a/test/decl/protocol/special/coding/class_codable_default_initializer.swift b/test/decl/protocol/special/coding/class_codable_default_initializer.swift index bdaa773cfad..017aaf726f3 100644 --- a/test/decl/protocol/special/coding/class_codable_default_initializer.swift +++ b/test/decl/protocol/special/coding/class_codable_default_initializer.swift @@ -7,7 +7,7 @@ class NoInitializers { // expected-error {{class 'NoInitializers' has no initial func foo() { // The class should not receive a default constructor. - let _ = NoInitializers.init() // expected-error {{type 'NoInitializers' has no member 'init'}} + let _ = NoInitializers.init() // expected-error {{'NoInitializers' cannot be constructed because it has no accessible initializers}} } } diff --git a/test/stdlib/Inputs/SwiftNativeNSBase/SwiftNativeNSBase.m b/test/stdlib/Inputs/SwiftNativeNSBase/SwiftNativeNSBase.m index 5632b822bb6..85afa78ed9f 100644 --- a/test/stdlib/Inputs/SwiftNativeNSBase/SwiftNativeNSBase.m +++ b/test/stdlib/Inputs/SwiftNativeNSBase/SwiftNativeNSBase.m @@ -77,6 +77,11 @@ BOOL TestSwiftNativeNSBase_UnwantedCdtors() if (! ([name hasPrefix:@"__SwiftNativeNS"] && [name hasSuffix:@"Base"])) { continue; } + if ([name isEqual: @"__SwiftNativeNSDataBase"] || + [name isEqual: @"__SwiftNativeNSIndexSetBase"]) { + //These two were removed but are still present when back-deploying + continue; + } if (! [expectedClasses containsObject:name]) { fail("did not expect class %s\n", name.UTF8String); continue; diff --git a/test/stmt/statements.swift b/test/stmt/statements.swift index 70ea76712f9..fbb9237d2f2 100644 --- a/test/stmt/statements.swift +++ b/test/stmt/statements.swift @@ -39,12 +39,12 @@ func funcdecl5(_ a: Int, y: Int) { x = y (x) = y - 1 = x // expected-error {{cannot assign to a literal value}} - (1) = x // expected-error {{cannot assign to a literal value}} - "string" = "other" // expected-error {{cannot assign to a literal value}} + 1 = x // expected-error {{cannot assign to value: literals are not mutable}} + (1) = x // expected-error {{cannot assign to value: literals are not mutable}} + "string" = "other" // expected-error {{cannot assign to value: literals are not mutable}} [1, 1, 1, 1] = [1, 1] // expected-error {{cannot assign to immutable expression of type '[Int]}} 1.0 = x // expected-error {{cannot assign to a literal value}} - nil = 1 // expected-error {{cannot assign to a literal value}} + nil = 1 // expected-error {{cannot assign to value: literals are not mutable}} (x:1).x = 1 // expected-error {{cannot assign to immutable expression of type 'Int'}} var tup : (x:Int, y:Int) diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp index 4bbddefbd6f..9e588c802b6 100644 --- a/tools/swift-api-digester/swift-api-digester.cpp +++ b/tools/swift-api-digester/swift-api-digester.cpp @@ -229,6 +229,11 @@ static llvm::cl::opt Migrator("migrator", llvm::cl::desc("Dump Json suitable for generating migration script"), llvm::cl::cat(Category)); + +static llvm::cl::list +PreferInterfaceForModules("use-interface-for-module", llvm::cl::ZeroOrMore, + llvm::cl::desc("Prefer loading these modules via interface"), + llvm::cl::cat(Category)); } // namespace options namespace { @@ -2431,6 +2436,9 @@ static int prepareForDump(const char *Main, for (auto M : options::ModuleNames) { Modules.insert(M); } + for (auto M: options::PreferInterfaceForModules) { + InitInvok.getFrontendOptions().PreferInterfaceForModules.push_back(M); + } if (Modules.empty()) { llvm::errs() << "Need to specify -include-all or -module \n"; exit(1); diff --git a/unittests/AST/ArithmeticEvaluator.cpp b/unittests/AST/ArithmeticEvaluator.cpp index 1cdea7261ae..ec6a19b4db2 100644 --- a/unittests/AST/ArithmeticEvaluator.cpp +++ b/unittests/AST/ArithmeticEvaluator.cpp @@ -174,12 +174,11 @@ struct ExternallyCachedEvaluationRule // Define the arithmetic evaluator's zone. namespace swift { -#define SWIFT_ARITHMETIC_EVALUATOR_ZONE 255 -#define SWIFT_TYPEID_ZONE SWIFT_ARITHMETIC_EVALUATOR_ZONE +#define SWIFT_TYPEID_ZONE ArithmeticEvaluator #define SWIFT_TYPEID_HEADER "ArithmeticEvaluatorTypeIDZone.def" #include "swift/Basic/DefineTypeIDZone.h" -#define SWIFT_TYPEID_ZONE SWIFT_ARITHMETIC_EVALUATOR_ZONE +#define SWIFT_TYPEID_ZONE ArithmeticEvaluator #define SWIFT_TYPEID_HEADER "ArithmeticEvaluatorTypeIDZone.def" #include "swift/Basic/ImplementTypeIDZone.h" @@ -187,10 +186,10 @@ namespace swift { /// All of the arithmetic request functions. static AbstractRequestFunction *arithmeticRequestFunctions[] = { -#define SWIFT_TYPEID(Name) \ +#define SWIFT_REQUEST(Zone, Name) \ reinterpret_cast(&Name::evaluateRequest), #include "ArithmeticEvaluatorTypeIDZone.def" -#undef SWIFT_TYPEID +#undef SWIFT_REQUEST }; /// Helper to short-circuit errors to NaN. @@ -212,7 +211,7 @@ TEST(ArithmeticEvaluator, Simple) { SourceManager sourceMgr; DiagnosticEngine diags(sourceMgr); Evaluator evaluator(diags); - evaluator.registerRequestFunctions(SWIFT_ARITHMETIC_EVALUATOR_ZONE, + evaluator.registerRequestFunctions(Zone::ArithmeticEvaluator, arithmeticRequestFunctions); const double expectedResult = (3.14159 + 2.71828) * 42.0; @@ -335,7 +334,7 @@ TEST(ArithmeticEvaluator, Cycle) { SourceManager sourceMgr; DiagnosticEngine diags(sourceMgr); Evaluator evaluator(diags); - evaluator.registerRequestFunctions(SWIFT_ARITHMETIC_EVALUATOR_ZONE, + evaluator.registerRequestFunctions(Zone::ArithmeticEvaluator, arithmeticRequestFunctions); // Evaluate when there is a cycle. diff --git a/unittests/AST/ArithmeticEvaluatorTypeIDZone.def b/unittests/AST/ArithmeticEvaluatorTypeIDZone.def index a32fd4ea5bf..f441059b493 100644 --- a/unittests/AST/ArithmeticEvaluatorTypeIDZone.def +++ b/unittests/AST/ArithmeticEvaluatorTypeIDZone.def @@ -14,6 +14,6 @@ // TypeID zone, for use with the TypeID template. // //===----------------------------------------------------------------------===// -SWIFT_TYPEID(UncachedEvaluationRule) -SWIFT_TYPEID(InternallyCachedEvaluationRule) -SWIFT_TYPEID(ExternallyCachedEvaluationRule) +SWIFT_REQUEST(ArithmeticEvaluator, UncachedEvaluationRule) +SWIFT_REQUEST(ArithmeticEvaluator, InternallyCachedEvaluationRule) +SWIFT_REQUEST(ArithmeticEvaluator, ExternallyCachedEvaluationRule)