diff --git a/CHANGELOG.md b/CHANGELOG.md index d1fad97e01e8b..a593772e306cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,18 @@ > **Note**\ > This is in reverse chronological order, so newer entries are added to the top. +## Swift 5.9.2 + +* [SE-0407][]: + + Member macros can specify a list of protocols via the `conformances` argument to the macro role. The macro implementation will be provided with those protocols that are listed but have not already been implemented by the type to which the member macro is attached, in the same manner as extension macros. + + ```swift + @attached(member, conformances: Decodable, Encodable, names: named(init(from:), encode(to:))) +@attached(extension, conformances: Decodable, Encodable, names: named(init(from:), encode(to:))) +macro Codable() = #externalMacro(module: "MyMacros", type: "CodableMacro") + ``` + ## Swift 5.9 * [SE-0382][], [SE-0389][], [SE-0394][], [SE-0397][]: @@ -9833,6 +9845,7 @@ using the `.dynamicType` member to retrieve the type of an expression should mig [SE-0389]: https://github.com/apple/swift-evolution/blob/main/proposals/0389-attached-macros.md [SE-0394]: https://github.com/apple/swift-evolution/blob/main/proposals/0394-swiftpm-expression-macros.md [SE-0397]: https://github.com/apple/swift-evolution/blob/main/proposals/0397-freestanding-declaration-macros.md +[SE-0407]: https://github.com/apple/swift-evolution/blob/main/proposals/0407-member-macro-conformances.md [#64927]: [#42697]: [#42728]: diff --git a/SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift b/SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift index c0c7f3cd5767b..678be3e47b04f 100644 --- a/SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift +++ b/SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift @@ -30,8 +30,14 @@ let mandatoryPerformanceOptimizations = ModulePass(name: "mandatory-performance- (moduleContext: ModulePassContext) in var worklist = FunctionWorklist() - worklist.addAllPerformanceAnnotatedFunctions(of: moduleContext) - worklist.addAllAnnotatedGlobalInitOnceFunctions(of: moduleContext) + // For embedded Swift, optimize all the functions (there cannot be any + // generics, type metadata, etc.) + if moduleContext.options.enableEmbeddedSwift { + worklist.addAllNonGenericFunctions(of: moduleContext) + } else { + worklist.addAllPerformanceAnnotatedFunctions(of: moduleContext) + worklist.addAllAnnotatedGlobalInitOnceFunctions(of: moduleContext) + } optimizeFunctionsTopDown(using: &worklist, moduleContext) } @@ -305,6 +311,13 @@ fileprivate struct FunctionWorklist { } } + mutating func addAllNonGenericFunctions(of moduleContext: ModulePassContext) { + for f in moduleContext.functions where f.isGenericFunction { + pushIfNotVisited(f) + } + return + } + mutating func addAllAnnotatedGlobalInitOnceFunctions(of moduleContext: ModulePassContext) { for f in moduleContext.functions where f.isGlobalInitOnceFunction { if let global = f.getInitializedGlobal(), diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/Options.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/Options.swift index 57ac9585ba774..65580bdfcfb44 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/Options.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/Options.swift @@ -28,6 +28,10 @@ struct Options { _bridged.enableSimplificationFor(inst.bridged) } + var enableEmbeddedSwift: Bool { + _bridged.enableEmbeddedSwift() + } + enum AssertConfiguration { case enabled case disabled diff --git a/SwiftCompilerSources/Sources/SIL/Function.swift b/SwiftCompilerSources/Sources/SIL/Function.swift index 2a136cebee9b9..77fde8318c8ac 100644 --- a/SwiftCompilerSources/Sources/SIL/Function.swift +++ b/SwiftCompilerSources/Sources/SIL/Function.swift @@ -137,6 +137,8 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash /// It's called from a `[global_init]` function via a `builtin "once"`. public var isGlobalInitOnceFunction: Bool { bridged.isGlobalInitOnceFunction() } + public var isGenericFunction: Bool { bridged.isGenericFunction() } + /// Kinds of effect attributes which can be defined for a Swift function. public enum EffectAttribute { /// No effect attribute is specified. diff --git a/cmake/modules/AddPureSwift.cmake b/cmake/modules/AddPureSwift.cmake index 1d79a945cc982..6c79fdcf351ce 100644 --- a/cmake/modules/AddPureSwift.cmake +++ b/cmake/modules/AddPureSwift.cmake @@ -269,7 +269,8 @@ function(add_pure_swift_host_tool name) # Option handling set(options) - set(single_parameter_options) + set(single_parameter_options + SWIFT_COMPONENT) set(multiple_parameter_options DEPENDENCIES SWIFT_DEPENDENCIES) @@ -341,6 +342,18 @@ function(add_pure_swift_host_tool name) COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/${name}.swiftmodule" COMMAND_EXPAND_LISTS COMMENT "Update mtime of executable outputs workaround") - # Export this target. - set_property(GLOBAL APPEND PROPERTY SWIFT_EXPORTS ${name}) + + if(NOT APSHT_SWIFT_COMPONENT STREQUAL no_component) + add_dependencies(${APSHT_SWIFT_COMPONENT} ${name}) + swift_install_in_component(TARGETS ${name} + COMPONENT ${APSHT_SWIFT_COMPONENT} + RUNTIME DESTINATION bin) + swift_is_installing_component(${APSHT_SWIFT_COMPONENT} is_installing) + endif() + + if(NOT is_installing) + set_property(GLOBAL APPEND PROPERTY SWIFT_BUILDTREE_EXPORTS ${name}) + else() + set_property(GLOBAL APPEND PROPERTY SWIFT_EXPORTS ${name}) + endif() endfunction() diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index b31370e4ac58b..b55f7d8071656 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -573,6 +573,9 @@ function(_add_swift_runtime_link_flags target relpath_to_lib_dir bootstrapping) else() message(FATAL_ERROR "Unknown BOOTSTRAPPING_MODE '${ASRLF_BOOTSTRAPPING_MODE}'") endif() + else() + target_link_directories(${target} PRIVATE + ${SWIFT_PATH_TO_SWIFT_SDK}/usr/lib/swift/${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}/${SWIFT_HOST_VARIANT_ARCH}) endif() if(SWIFT_SWIFT_PARSER) diff --git a/include/swift-c/DependencyScan/DependencyScan.h b/include/swift-c/DependencyScan/DependencyScan.h index eff7bb4ea444f..91675cf837b89 100644 --- a/include/swift-c/DependencyScan/DependencyScan.h +++ b/include/swift-c/DependencyScan/DependencyScan.h @@ -25,7 +25,7 @@ /// SWIFTSCAN_VERSION_MINOR should increase when there are API additions. /// SWIFTSCAN_VERSION_MAJOR is intended for "major" source/ABI breaking changes. #define SWIFTSCAN_VERSION_MAJOR 0 -#define SWIFTSCAN_VERSION_MINOR 4 +#define SWIFTSCAN_VERSION_MINOR 5 SWIFTSCAN_BEGIN_DECLS @@ -430,6 +430,9 @@ SWIFTSCAN_PUBLIC int invoke_swift_compiler(int argc, const char **argv); //=== Scanner CAS Operations ----------------------------------------------===// +/// Opaque container for a CASOptions that describe how CAS should be created. +typedef struct swiftscan_cas_options_s *swiftscan_cas_options_t; + /// Opaque container for a CAS instance that includes both ObjectStore and /// ActionCache. typedef struct swiftscan_cas_s *swiftscan_cas_t; @@ -445,22 +448,54 @@ typedef enum { SWIFTSCAN_OUTPUT_TYPE_CLANG_PCH = 5 } swiftscan_output_kind_t; -/// Create a \c cas instance that points to path. -SWIFTSCAN_PUBLIC swiftscan_cas_t swiftscan_cas_create(const char *path); +/// Create a \c CASOptions for creating CAS inside scanner specified. +SWIFTSCAN_PUBLIC swiftscan_cas_options_t swiftscan_cas_options_create(void); + +/// Dispose \c CASOptions. +SWIFTSCAN_PUBLIC void +swiftscan_cas_options_dispose(swiftscan_cas_options_t options); + +/// Set on-disk path for the \c cas. +SWIFTSCAN_PUBLIC void +swiftscan_cas_options_set_ondisk_path(swiftscan_cas_options_t options, + const char *path); + +/// Set plugin path for the \c cas. +SWIFTSCAN_PUBLIC void +swiftscan_cas_options_set_plugin_path(swiftscan_cas_options_t options, + const char *path); + +/// Set option using a name/value pair. Return true if error. +/// If error happens, the error message is returned via `error` parameter, and +/// caller needs to free the error message via `swiftscan_string_dispose`. +SWIFTSCAN_PUBLIC bool +swiftscan_cas_options_set_option(swiftscan_cas_options_t options, + const char *name, const char *value, + swiftscan_string_ref_t *error); + +/// Create a \c cas instance from plugin. Return NULL if error. +/// If error happens, the error message is returned via `error` parameter, and +/// caller needs to free the error message via `swiftscan_string_dispose`. +SWIFTSCAN_PUBLIC swiftscan_cas_t swiftscan_cas_create_from_options( + swiftscan_cas_options_t options, swiftscan_string_ref_t *error); /// Dispose the \c cas instance. SWIFTSCAN_PUBLIC void swiftscan_cas_dispose(swiftscan_cas_t cas); -/// Store content into CAS. Return \c CASID as string. -SWIFTSCAN_PUBLIC swiftscan_string_ref_t swiftscan_cas_store(swiftscan_cas_t cas, - uint8_t *data, - unsigned size); +/// Store content into CAS. Return \c CASID as string. Return NULL on error. +/// If error happens, the error message is returned via `error` parameter, and +/// caller needs to free the error message via `swiftscan_string_dispose`. +SWIFTSCAN_PUBLIC swiftscan_string_ref_t +swiftscan_cas_store(swiftscan_cas_t cas, uint8_t *data, unsigned size, + swiftscan_string_ref_t *error); /// Compute \c CacheKey for output of \c kind from the compiler invocation \c /// argc and \c argv with \c input. Return \c CacheKey as string. -SWIFTSCAN_PUBLIC swiftscan_string_ref_t -swiftscan_compute_cache_key(swiftscan_cas_t cas, int argc, const char **argv, - const char *input, swiftscan_output_kind_t kind); +/// If error happens, the error message is returned via `error` parameter, and +/// caller needs to free the error message via `swiftscan_string_dispose`. +SWIFTSCAN_PUBLIC swiftscan_string_ref_t swiftscan_compute_cache_key( + swiftscan_cas_t cas, int argc, const char **argv, const char *input, + swiftscan_output_kind_t kind, swiftscan_string_ref_t *error); //===----------------------------------------------------------------------===// diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 48d7999661d8e..ebb751d3027e4 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -35,6 +35,7 @@ #include "swift/AST/RequirementSignature.h" #include "swift/AST/StorageImpl.h" #include "swift/AST/TypeAlignments.h" +#include "swift/AST/TypeResolutionStage.h" #include "swift/AST/TypeWalker.h" #include "swift/AST/Types.h" #include "swift/Basic/ArrayRefView.h" @@ -662,7 +663,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated { HasAnyUnavailableDuringLoweringValues : 1 ); - SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1, + SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1, /// If the module is compiled as static library. StaticLibrary : 1, @@ -706,6 +707,9 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated { /// Whether this module was built with -experimental-hermetic-seal-at-link. HasHermeticSealAtLink : 1, + /// Whether this module was built with embedded Swift. + IsEmbeddedSwiftModule : 1, + /// Whether this module has been compiled with comprehensive checking for /// concurrency, e.g., Sendable checking. IsConcurrencyChecked : 1, @@ -1547,6 +1551,53 @@ struct InheritedEntry : public TypeLoc { : TypeLoc(typeLoc), isUnchecked(isUnchecked) { } }; +/// A wrapper for the collection of inherited types for either a `TypeDecl` or +/// an `ExtensionDecl`. +class InheritedTypes { + llvm::PointerUnion Decl; + ArrayRef Entries; + +public: + InheritedTypes( + llvm::PointerUnion decl); + InheritedTypes(const class Decl *decl); + InheritedTypes(const TypeDecl *typeDecl); + InheritedTypes(const ExtensionDecl *extensionDecl); + + bool empty() const { return Entries.empty(); } + size_t size() const { return Entries.size(); } + IntRange const getIndices() { return indices(Entries); } + + /// Returns the `TypeRepr *` for the entry of the inheritance clause at the + /// given index. + TypeRepr *getTypeRepr(unsigned i) const { return Entries[i].getTypeRepr(); } + + /// Returns the `Type` for the entry of the inheritance clause at the given + /// index, resolved at the given stage, or `Type()` if resolution fails. + Type getResolvedType(unsigned i, TypeResolutionStage stage = + TypeResolutionStage::Interface) const; + + /// Returns the underlying array of inherited type entries. + /// + /// NOTE: The `Type` associated with an entry may not be resolved yet. + ArrayRef getEntries() const { return Entries; } + + /// Returns the entry of the inheritance clause at the given index. + /// + /// NOTE: The `Type` associated with the entry may not be resolved yet. + const InheritedEntry &getEntry(unsigned i) const { return Entries[i]; } + + /// Returns the source location of the beginning of the inheritance clause. + SourceLoc getStartLoc() const { + return getEntries().front().getSourceRange().Start; + } + + /// Returns the source location of the end of the inheritance clause. + SourceLoc getEndLoc() const { + return getEntries().back().getSourceRange().End; + } +}; + /// ExtensionDecl - This represents a type extension containing methods /// associated with the type. This is not a ValueDecl and has no Type because /// there are no runtime values of the Extension's type. @@ -1582,6 +1633,7 @@ class ExtensionDecl final : public GenericContext, public Decl, friend class MemberLookupTable; friend class ConformanceLookupTable; friend class IterableDeclContext; + friend class InheritedTypes; ExtensionDecl(SourceLoc extensionLoc, TypeRepr *extendedType, ArrayRef inherited, @@ -1662,7 +1714,7 @@ class ExtensionDecl final : public GenericContext, public Decl, /// Retrieve the set of protocols that this type inherits (i.e, /// explicitly conforms to). - ArrayRef getInherited() const { return Inherited; } + InheritedTypes getInherited() const { return InheritedTypes(this); } void setInherited(ArrayRef i) { Inherited = i; } @@ -2994,6 +3046,8 @@ class TypeDecl : public ValueDecl { ArrayRef inherited) : ValueDecl(K, context, name, NameLoc), Inherited(inherited) {} + friend class InheritedTypes; + public: Identifier getName() const { return getBaseIdentifier(); } @@ -3009,7 +3063,7 @@ class TypeDecl : public ValueDecl { /// Retrieve the set of protocols that this type inherits (i.e, /// explicitly conforms to). - ArrayRef getInherited() const { return Inherited; } + InheritedTypes getInherited() const { return InheritedTypes(this); } void setInherited(ArrayRef i) { Inherited = i; } @@ -5178,13 +5232,11 @@ class ProtocolDecl final : public NominalTypeDecl { /// and conformances for tuple types. /// /// - The declared interface type is the special TheTupleType singleton. -/// - The generic parameter list has one pack generic parameter, -/// - The generic signature has no requirements, +/// - The generic parameter list has one pack generic parameter, +/// - The generic signature has no requirements, /// - The self interface type is the tuple type containing a single pack -/// expansion, (Elements...). +/// expansion, (repeat each Element). class BuiltinTupleDecl final : public NominalTypeDecl { - TupleType *TupleSelfType = nullptr; - public: BuiltinTupleDecl(Identifier Name, DeclContext *Parent); @@ -5192,7 +5244,7 @@ class BuiltinTupleDecl final : public NominalTypeDecl { return SourceRange(); } - TupleType *getTupleSelfType() const; + TupleType *getTupleSelfType(const ExtensionDecl *owner) const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { @@ -8650,6 +8702,7 @@ class MacroDecl : public GenericContext, public ValueDecl { /// be added if this macro does not contain an extension role. void getIntroducedConformances( NominalTypeDecl *attachedTo, + MacroRole role, SmallVectorImpl &conformances) const; /// Returns a DeclName that represents arbitrary names. diff --git a/include/swift/AST/DiagnosticsCommon.def b/include/swift/AST/DiagnosticsCommon.def index 0a362e7e523bb..d3623cd6412fc 100644 --- a/include/swift/AST/DiagnosticsCommon.def +++ b/include/swift/AST/DiagnosticsCommon.def @@ -201,6 +201,9 @@ ERROR(scanner_find_cycle, none, ERROR(scanner_arguments_invalid, none, "dependencies scanner cannot be configured with arguments: '%0'", (StringRef)) +ERROR(error_scanner_extra, none, + "failed inside dependency scanner: '%0'", (StringRef)) + WARNING(warn_scanner_deserialize_failed, none, "Failed to load module scanning dependency cache from: '%0', re-building scanner cache from scratch.", (StringRef)) diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def index 8158a0eaa6731..ae4f68b167a17 100644 --- a/include/swift/AST/DiagnosticsFrontend.def +++ b/include/swift/AST/DiagnosticsFrontend.def @@ -554,5 +554,8 @@ ERROR(layout_string_instantiation_without_layout_strings,none, "-enable-layout-string-value-witnesses-instantiation can not be enabled " "without -enable-layout-string-value-witnesses.", ()) +ERROR(evolution_with_embedded,none, + "Library evolution cannot be enabled with embedded Swift.", ()) + #define UNDEFINE_DIAGNOSTIC_MACROS #include "DefineDiagnosticMacros.h" diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 101252466951b..3eddb0799ea58 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -872,6 +872,12 @@ ERROR(need_hermetic_seal_to_import_module,none, "module %0 was built with -experimental-hermetic-seal-at-link, but " "current compilation does not have -experimental-hermetic-seal-at-link", (Identifier)) +ERROR(cannot_import_embedded_module,none, + "module %0 cannot be imported because it was built with embedded Swift", + (Identifier)) +ERROR(cannot_import_non_embedded_module,none, + "module %0 cannot be imported in embedded Swift mode", + (Identifier)) ERROR(need_cxx_interop_to_import_module,none, "module %0 was built with C++ interoperability enabled, but " "current compilation does not enable C++ interoperability", @@ -1931,6 +1937,10 @@ WARNING(access_control_non_objc_open_member,none, ERROR(access_control_requires_package_name, none, "%0 has a package access level but no -package-name was specified: %1", (Identifier, StringRef)) +ERROR(access_control_requires_package_name_import, none, + "package import can only be used from a module with a package name; " + "set it with the compiler flag -package-name", + ()) ERROR(invalid_decl_attribute,none, "'%0' attribute cannot be applied to this declaration", (DeclAttribute)) ERROR(attr_invalid_on_decl_kind,none, @@ -2353,6 +2363,18 @@ ERROR(extension_access_with_conformances,none, ERROR(experimental_tuple_extension,none, "tuple extensions are experimental", ()) +ERROR(tuple_extension_wrong_type,none, + "tuple extension must be written as extension of %0", (Type)) +ERROR(tuple_extension_one_conformance,none, + "tuple extension must declare conformance to exactly one protocol", ()) +ERROR(tuple_extension_extra_requirement,none, + "tuple extension cannot require that %0 " + "%select{conforms to|subclasses|is the same type as|%error|%error}1 %2", + (Type, unsigned, Type)) +ERROR(tuple_extension_missing_requirement,none, + "tuple extension must require that %0 conforms to %1", (Type, Type)) +ERROR(tuple_extension_nested_type,none, + "type %0 cannot be nested in tuple extension", (const NominalTypeDecl *)) ERROR(extension_metatype,none, "cannot extend a metatype %0", (Type)) ERROR(extension_placeholder,none, @@ -2721,10 +2743,23 @@ NOTE(ambiguous_witnesses_wrong_name,none, NOTE(no_witnesses_type,none, "protocol requires nested type %0; add nested type %0 for conformance", (const AssociatedTypeDecl *)) -NOTE(default_associated_type_req_fail,none, +NOTE(no_witnesses_type_tuple,none, + "protocol requires nested type %0; add type alias %0 with underlying type %1 " + "for conformance", + (const AssociatedTypeDecl *, Type)) +NOTE(default_associated_type_unsatisfied_conformance,none, + "default type %0 for associated type %1 (from protocol %2) " + "does not conform to %3", + (Type, const AssociatedTypeDecl *, Type, Type)) +NOTE(default_associated_type_unsatisfied_superclass,none, + "default type %0 for associated type %1 (from protocol %2) " + "does not inherit from %3", + (Type, const AssociatedTypeDecl *, Type, Type)) +NOTE(default_associated_type_tuple,none, "default type %0 for associated type %1 (from protocol %2) " - "does not %select{inherit from|conform to}4 %3", - (Type, const AssociatedTypeDecl *, Type, Type, bool)) + "is unsuitable for tuple conformance; the associated type requirement " + "must be fulfilled by a type alias with underlying type %3", + (Type, const AssociatedTypeDecl *, Type, Type)) ERROR(associated_type_access,none, "associated type in " "%select{a private|a fileprivate|an internal|a package|a public|%error}0 protocol " @@ -2752,10 +2787,19 @@ WARNING(associated_type_not_usable_from_inline_warn,none, NOTE(bad_associated_type_deduction,none, "unable to infer associated type %0 for protocol %1", (const AssociatedTypeDecl *, const ProtocolDecl *)) -NOTE(associated_type_deduction_witness_failed,none, +NOTE(associated_type_deduction_unsatisfied_conformance,none, "candidate would match and infer %0 = %1 if %1 " - "%select{inherited from|conformed to}3 %2", - (const AssociatedTypeDecl *, Type, Type, bool)) + "conformed to %2", + (const AssociatedTypeDecl *, Type, Type)) +NOTE(associated_type_deduction_unsatisfied_superclass,none, + "candidate would match and infer %0 = %1 if %1 " + "inherited from %2", + (const AssociatedTypeDecl *, Type, Type)) +NOTE(associated_type_deduction_tuple,none, + "cannot infer %0 = %1 in tuple conformance because " + "the associated type requirement must be fulfilled by a type alias with " + "underlying type %2", + (const AssociatedTypeDecl *, Type, Type)) NOTE(associated_type_witness_conform_impossible,none, "candidate can not infer %0 = %1 because %1 " "is not a nominal type and so can't conform to %2", @@ -2846,9 +2890,17 @@ NOTE(protocol_witness_enum_case_payload, none, NOTE(protocol_witness_type,none, "possibly intended match", ()) -NOTE(protocol_witness_nonconform_type,none, +NOTE(protocol_type_witness_unsatisfied_conformance,none, + "possibly intended match %0 does not " + "conform to %1", (Type, Type)) +NOTE(protocol_type_witness_unsatisfied_superclass,none, "possibly intended match %0 does not " - "%select{inherit from|conform to}2 %1", (Type, Type, bool)) + "inherit from %1", (Type, Type)) +NOTE(protocol_type_witness_tuple,none, + "possibly intended match %0 is unsuitable for tuple conformance; " + "the associated type requirement must be fulfilled by a type alias " + "with underlying type %1", + (Type, Type)) NOTE(protocol_witness_circularity,none, "candidate references itself", ()) diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index aa1d88cb63882..c5f24ad0f6eec 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -656,6 +656,14 @@ class ModuleDecl Bits.ModuleDecl.HasHermeticSealAtLink = enabled; } + /// Returns true if this module was built with embedded Swift + bool isEmbeddedSwiftModule() const { + return Bits.ModuleDecl.IsEmbeddedSwiftModule; + } + void setIsEmbeddedSwiftModule(bool enabled = true) { + Bits.ModuleDecl.IsEmbeddedSwiftModule = enabled; + } + /// Returns true if this module was built with C++ interoperability enabled. bool hasCxxInteroperability() const { return Bits.ModuleDecl.HasCxxInteroperability; diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h index 14701ef819f7b..d4d78b4538481 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -620,17 +620,6 @@ SelfBounds getSelfBoundsFromWhereClause( /// given protocol or protocol extension. SelfBounds getSelfBoundsFromGenericSignature(const ExtensionDecl *extDecl); -/// Retrieve the TypeLoc at the given \c index from among the set of -/// type declarations that are directly "inherited" by the given declaration. -inline const TypeLoc &getInheritedTypeLocAtIndex( - llvm::PointerUnion decl, - unsigned index) { - if (auto typeDecl = decl.dyn_cast()) - return typeDecl->getInherited()[index]; - - return decl.get()->getInherited()[index]; -} - namespace namelookup { /// Searches through statements and patterns for local variable declarations. diff --git a/include/swift/AST/PluginRegistry.h b/include/swift/AST/PluginRegistry.h index 8ee553c8903c4..ff8406f51b352 100644 --- a/include/swift/AST/PluginRegistry.h +++ b/include/swift/AST/PluginRegistry.h @@ -40,7 +40,7 @@ class LoadedLibraryPlugin { void *getAddressOfSymbol(const char *symbolName); }; -/// Represent a "resolved" exectuable plugin. +/// Represent a "resolved" executable plugin. /// /// Plugin clients usually deal with this object to communicate with the actual /// plugin implementation. diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index ae43a7fb4131e..832a2acba2070 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -96,6 +96,8 @@ class InheritedTypeRequest llvm::PointerUnion decl, unsigned index, TypeResolutionStage stage) const; + const TypeLoc &getTypeLoc() const; + public: // Source location SourceLoc getNearestLoc() const; @@ -3336,10 +3338,10 @@ class ResolveMacroRequest void noteCycleStep(DiagnosticEngine &diags) const; }; -/// Returns the resolved constraint types that an extension macro -/// adds conformances to. -class ResolveExtensionMacroConformances - : public SimpleRequest(const MacroRoleAttr *, const Decl *), RequestFlags::Cached> { public: diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 4f4226dfe2f23..9041db3650211 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -363,7 +363,7 @@ SWIFT_REQUEST(TypeChecker, ResolveImplicitMemberRequest, SWIFT_REQUEST(TypeChecker, ResolveMacroRequest, ConcreteDeclRef(UnresolvedMacroReference, const Decl *), Cached, NoLocationInfo) -SWIFT_REQUEST(TypeChecker, ResolveExtensionMacroConformances, +SWIFT_REQUEST(TypeChecker, ResolveMacroConformances, ArrayRef(const MacroRoleAttr *, const Decl *), Cached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, ResolveTypeEraserTypeRequest, diff --git a/include/swift/Basic/Features.def b/include/swift/Basic/Features.def index 4e1bee0f63aff..a3a65401b48b3 100644 --- a/include/swift/Basic/Features.def +++ b/include/swift/Basic/Features.def @@ -232,6 +232,9 @@ EXPERIMENTAL_FEATURE(ThenStatements, false) /// Enable the `@_rawLayout` attribute. EXPERIMENTAL_FEATURE(RawLayout, true) +/// Enables the "embedded" swift mode (no runtime). +EXPERIMENTAL_FEATURE(Embedded, true) + #undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE #undef EXPERIMENTAL_FEATURE #undef UPCOMING_FEATURE diff --git a/include/swift/Frontend/CachingUtils.h b/include/swift/Frontend/CachingUtils.h index 343de5ccdc3da..43f756b35b5f0 100644 --- a/include/swift/Frontend/CachingUtils.h +++ b/include/swift/Frontend/CachingUtils.h @@ -15,10 +15,11 @@ #include "swift/Frontend/CachedDiagnostics.h" #include "swift/Frontend/FrontendInputsAndOutputs.h" +#include "clang/CAS/CASOptions.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/CAS/ActionCache.h" -#include "llvm/CAS/ObjectStore.h" #include "llvm/CAS/CASReference.h" +#include "llvm/CAS/ObjectStore.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/VirtualOutputBackend.h" #include @@ -58,29 +59,6 @@ llvm::Error storeCachedCompilerOutput(llvm::cas::ObjectStore &CAS, llvm::Expected> createCASFileSystem(llvm::cas::ObjectStore &CAS, ArrayRef FSRoots, ArrayRef IncludeTreeRoots); - -namespace cas { -/// Helper class to manage CAS/Caching from libSwiftScan C APIs. -class CachingTool { -public: - // Create the tool with a list of arguments from compiler invocation. - CachingTool(llvm::StringRef Path); - - // Compute the CASID for PCH output from invocation. - std::string computeCacheKey(llvm::ArrayRef Args, - StringRef InputPath, file_types::ID OutputKind); - - // Store content into CAS. - std::string storeContent(llvm::StringRef Content); - - // Check if the tool is correctly initialized. - bool isValid() const { return CAS && Cache; } - -private: - std::unique_ptr CAS; - std::unique_ptr Cache; -}; -} // namespace cas } #endif diff --git a/include/swift/Frontend/PrintingDiagnosticConsumer.h b/include/swift/Frontend/PrintingDiagnosticConsumer.h index 809b438352286..2db64e8f6d0f8 100644 --- a/include/swift/Frontend/PrintingDiagnosticConsumer.h +++ b/include/swift/Frontend/PrintingDiagnosticConsumer.h @@ -50,7 +50,6 @@ class PrintingDiagnosticConsumer : public DiagnosticConsumer { /// The queued diagnostics structure. void *queuedDiagnostics = nullptr; llvm::DenseMap queuedBuffers; - unsigned queuedDiagnosticsOutermostBufferID; public: PrintingDiagnosticConsumer(llvm::raw_ostream &stream = llvm::errs()); diff --git a/include/swift/IDE/AfterPoundExprCompletion.h b/include/swift/IDE/AfterPoundExprCompletion.h index 68176c823e949..b9dc59b4ac068 100644 --- a/include/swift/IDE/AfterPoundExprCompletion.h +++ b/include/swift/IDE/AfterPoundExprCompletion.h @@ -47,8 +47,7 @@ class AfterPoundExprCompletion : public TypeCheckCompletionCallback { : CompletionExpr(CompletionExpr), DC(DC), ParentStmtKind(ParentStmtKind) { } - void deliverResults(ide::CodeCompletionContext &CompletionCtx, - CodeCompletionConsumer &Consumer); + void collectResults(ide::CodeCompletionContext &CompletionCtx); }; } // end namespace ide diff --git a/include/swift/IDE/ArgumentCompletion.h b/include/swift/IDE/ArgumentCompletion.h index 2425bff45e2e0..757986e1e327a 100644 --- a/include/swift/IDE/ArgumentCompletion.h +++ b/include/swift/IDE/ArgumentCompletion.h @@ -25,31 +25,48 @@ class ArgumentTypeCheckCompletionCallback : public TypeCheckCompletionCallback { struct Result { /// The type associated with the code completion expression itself. Type ExpectedType; + /// The expected return type of the function call. Type ExpectedCallType; + /// True if this is a subscript rather than a function call. bool IsSubscript; + /// The FuncDecl or SubscriptDecl associated with the call. ValueDecl *FuncD; + /// The type of the function being called. AnyFunctionType *FuncTy; + /// The index of the argument containing the completion location unsigned ArgIdx; + /// The index of the parameter corresponding to the completion argument. llvm::Optional ParamIdx; + /// The indices of all params that were bound to non-synthesized /// arguments. Used so we don't suggest them even when the args are out of /// order. std::set ClaimedParamIndices; + /// True if the completion is a noninitial term in a variadic argument. bool IsNoninitialVariadic; + /// The base type of the call/subscript (null for free functions). Type BaseType; + /// True if an argument label precedes the completion location. bool HasLabel; + + /// The argument index of the first trailing closure. + /// + /// \c None if the call doesn't have a trailing closure. + llvm::Optional FirstTrailingClosureIndex; + /// Whether the surrounding context is async and thus calling async /// functions is supported. bool IsInAsyncContext; + /// A bitfield to mark whether the parameter at a given index is optional. /// Parameters can be optional if they have a default argument or belong to /// a parameter pack. @@ -93,9 +110,12 @@ class ArgumentTypeCheckCompletionCallback : public TypeCheckCompletionCallback { /// function signature instead of suggesting individual labels. Used when /// completing after the opening '(' of a function call \param Loc The /// location of the code completion token - void deliverResults(bool IncludeSignature, SourceLoc Loc, DeclContext *DC, - CodeCompletionContext &CompletionCtx, - CodeCompletionConsumer &Consumer); + /// \param IsLabeledTrailingClosure Whether we are completing the label of a + /// labeled trailing closure, ie. if the code completion location is outside + /// the call after the first trailing closure of the call. + void collectResults(bool IncludeSignature, bool IsLabeledTrailingClosure, + SourceLoc Loc, DeclContext *DC, + CodeCompletionContext &CompletionCtx); }; } // end namespace ide diff --git a/include/swift/IDE/CodeCompletion.h b/include/swift/IDE/CodeCompletion.h index ad2b1962749fa..e6d5599412a17 100644 --- a/include/swift/IDE/CodeCompletion.h +++ b/include/swift/IDE/CodeCompletion.h @@ -65,9 +65,10 @@ void postProcessCompletionResults( MutableArrayRef results, CompletionKind Kind, const DeclContext *DC, CodeCompletionResultSink *Sink); -void deliverCompletionResults(CodeCompletionContext &CompletionContext, +void collectCompletionResults(CodeCompletionContext &CompletionContext, CompletionLookup &Lookup, DeclContext *DC, - CodeCompletionConsumer &Consumer); + const ExpectedTypeContext &TypeContext, + bool CanCurrDeclContextHandleAsync); /// Create a factory for code completion callbacks. IDEInspectionCallbacksFactory * diff --git a/include/swift/IDE/CodeCompletionConsumer.h b/include/swift/IDE/CodeCompletionConsumer.h index 5919172f165a2..ad0f2da88ef43 100644 --- a/include/swift/IDE/CodeCompletionConsumer.h +++ b/include/swift/IDE/CodeCompletionConsumer.h @@ -22,30 +22,9 @@ namespace ide { struct RequestedCachedModule; /// An abstract base class for consumers of code completion results. -/// \see \c SimpleCachingCodeCompletionConsumer. class CodeCompletionConsumer { public: virtual ~CodeCompletionConsumer() {} - virtual void - handleResultsAndModules(CodeCompletionContext &context, - ArrayRef requestedModules, - const ExpectedTypeContext *TypeContext, - const DeclContext *DC, - bool CanCurrDeclContextHandleAsync) = 0; -}; - -/// A simplified code completion consumer interface that clients can use to get -/// CodeCompletionResults with automatic caching of top-level completions from -/// imported modules. -struct SimpleCachingCodeCompletionConsumer : public CodeCompletionConsumer { - - // Implement the CodeCompletionConsumer interface. - void handleResultsAndModules(CodeCompletionContext &context, - ArrayRef requestedModules, - const ExpectedTypeContext *TypeContext, - const DeclContext *DCForModules, - bool CanCurrDeclContextHandleAsync) override; - /// Clients should override this method to receive \p Results. virtual void handleResults(CodeCompletionContext &context) = 0; }; diff --git a/include/swift/IDE/CodeCompletionContext.h b/include/swift/IDE/CodeCompletionContext.h index d1efeb8971637..41d22fdfe558c 100644 --- a/include/swift/IDE/CodeCompletionContext.h +++ b/include/swift/IDE/CodeCompletionContext.h @@ -20,6 +20,7 @@ namespace swift { namespace ide { class CodeCompletionCache; +struct RequestedCachedModule; class CodeCompletionContext { friend class CodeCompletionResultBuilder; @@ -103,6 +104,13 @@ class CodeCompletionContext { sortCompletionResults(ArrayRef Results); CodeCompletionResultSink &getResultSink() { return CurrentResults; } + + /// Add code completion results from the given requested modules to this + /// context. + void addResultsFromModules(ArrayRef RequestedModules, + const ExpectedTypeContext &TypeContext, + const DeclContext *DC, + bool CanCurrDeclContextHandleAsync); }; } // end namespace ide diff --git a/include/swift/IDE/CodeCompletionResult.h b/include/swift/IDE/CodeCompletionResult.h index 3b67303aa1f8c..dd2c568381783 100644 --- a/include/swift/IDE/CodeCompletionResult.h +++ b/include/swift/IDE/CodeCompletionResult.h @@ -211,7 +211,6 @@ enum class CompletionKind : uint8_t { EffectsSpecifier, PoundAvailablePlatform, CallArg, - LabeledTrailingClosure, ReturnStmtExpr, ThenStmtExpr, YieldStmtExpr, diff --git a/include/swift/IDE/CodeCompletionResultType.h b/include/swift/IDE/CodeCompletionResultType.h index 280eb61604de9..2c308d1ca69d4 100644 --- a/include/swift/IDE/CodeCompletionResultType.h +++ b/include/swift/IDE/CodeCompletionResultType.h @@ -74,6 +74,23 @@ class ExpectedTypeContext { } } + /// Form a union of this expected type context with \p Other. + /// + /// Any possible type from either type context will be considered a possible + /// type in the merged type context. + void merge(const ExpectedTypeContext &Other) { + PossibleTypes.append(Other.PossibleTypes); + + // We can't merge ideal types. If they are different, setting to a null type + // is the best thing we can do. + if (!IdealType || !Other.IdealType || !IdealType->isEqual(Other.IdealType)) { + IdealType = Type(); + } + IsImplicitSingleExpressionReturn |= Other.IsImplicitSingleExpressionReturn; + PreferNonVoid &= Other.PreferNonVoid; + ExpectedCustomAttributeKinds |= Other.ExpectedCustomAttributeKinds; + } + Type getIdealType() const { return IdealType; } void setIdealType(Type IdealType) { this->IdealType = IdealType; } diff --git a/include/swift/IDE/CompletionLookup.h b/include/swift/IDE/CompletionLookup.h index 9781f5a40ec46..a52a7c2a96587 100644 --- a/include/swift/IDE/CompletionLookup.h +++ b/include/swift/IDE/CompletionLookup.h @@ -534,19 +534,11 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { void addPostfixOperatorCompletion(OperatorDecl *op, Type resultType); - void tryPostfixOperator(Expr *expr, PostfixOperatorDecl *op); - void addAssignmentOperator(Type RHSType); void addInfixOperatorCompletion(OperatorDecl *op, Type resultType, Type RHSType); - void tryInfixOperatorCompletion(Expr *foldedExpr, InfixOperatorDecl *op); - - Expr *typeCheckLeadingSequence(Expr *LHS, ArrayRef leadingSequence); - - void getOperatorCompletions(Expr *LHS, ArrayRef leadingSequence); - void addTypeRelationFromProtocol(CodeCompletionResultBuilder &builder, CodeCompletionLiteralKind kind); diff --git a/include/swift/IDE/ExprCompletion.h b/include/swift/IDE/ExprCompletion.h index 0e99b85c55351..cdee4ffc5e529 100644 --- a/include/swift/IDE/ExprCompletion.h +++ b/include/swift/IDE/ExprCompletion.h @@ -90,9 +90,8 @@ class ExprTypeCheckCompletionCallback : public TypeCheckCompletionCallback { AddUnresolvedMemberCompletions(AddUnresolvedMemberCompletions) {} /// \param CCLoc The location of the code completion token. - void deliverResults(SourceLoc CCLoc, - ide::CodeCompletionContext &CompletionCtx, - CodeCompletionConsumer &Consumer); + void collectResults(SourceLoc CCLoc, + ide::CodeCompletionContext &CompletionCtx); }; } // end namespace ide diff --git a/include/swift/IDE/KeyPathCompletion.h b/include/swift/IDE/KeyPathCompletion.h index b2f001de11cbc..6450ae03beb93 100644 --- a/include/swift/IDE/KeyPathCompletion.h +++ b/include/swift/IDE/KeyPathCompletion.h @@ -37,9 +37,8 @@ class KeyPathTypeCheckCompletionCallback : public TypeCheckCompletionCallback { public: KeyPathTypeCheckCompletionCallback(KeyPathExpr *KeyPath) : KeyPath(KeyPath) {} - void deliverResults(DeclContext *DC, SourceLoc DotLoc, - ide::CodeCompletionContext &CompletionCtx, - CodeCompletionConsumer &Consumer); + void collectResults(DeclContext *DC, SourceLoc DotLoc, + ide::CodeCompletionContext &CompletionCtx); }; } // end namespace ide diff --git a/include/swift/IDE/PostfixCompletion.h b/include/swift/IDE/PostfixCompletion.h index aa11705683c78..aa8d6068b43c9 100644 --- a/include/swift/IDE/PostfixCompletion.h +++ b/include/swift/IDE/PostfixCompletion.h @@ -103,10 +103,9 @@ class PostfixCompletionCallback : public TypeCheckCompletionCallback { /// \p DotLoc is invalid /// \param HasLeadingSpace Whether there is a space separating the exiting /// expression and the code completion token. - void deliverResults(SourceLoc DotLoc, bool IsInSelector, + void collectResults(SourceLoc DotLoc, bool IsInSelector, bool IncludeOperators, bool HasLeadingSpace, - CodeCompletionContext &CompletionCtx, - CodeCompletionConsumer &Consumer); + CodeCompletionContext &CompletionCtx); }; } // end namespace ide diff --git a/include/swift/IDE/UnresolvedMemberCompletion.h b/include/swift/IDE/UnresolvedMemberCompletion.h index 364234595c26e..6ccb980c9c429 100644 --- a/include/swift/IDE/UnresolvedMemberCompletion.h +++ b/include/swift/IDE/UnresolvedMemberCompletion.h @@ -59,9 +59,8 @@ class UnresolvedMemberTypeCheckCompletionCallback CodeCompletionExpr *CompletionExpr, DeclContext *DC) : CompletionExpr(CompletionExpr), DC(DC) {} - void deliverResults(DeclContext *DC, SourceLoc DotLoc, - ide::CodeCompletionContext &CompletionCtx, - CodeCompletionConsumer &Consumer); + void collectResults(DeclContext *DC, SourceLoc DotLoc, + ide::CodeCompletionContext &CompletionCtx); }; } // end namespace ide diff --git a/include/swift/IRGen/Linking.h b/include/swift/IRGen/Linking.h index d52a6c06098e3..5b99afa605d38 100644 --- a/include/swift/IRGen/Linking.h +++ b/include/swift/IRGen/Linking.h @@ -85,6 +85,18 @@ enum class TypeMetadataAddress { FullMetadata, }; +inline bool isEmbedded(CanType t) { + return t->getASTContext().LangOpts.hasFeature(Feature::Embedded); +} + +inline bool isEmbedded(Decl *d) { + return d->getASTContext().LangOpts.hasFeature(Feature::Embedded); +} + +inline bool isEmbedded(const ProtocolConformance *c) { + return c->getType()->getASTContext().LangOpts.hasFeature(Feature::Embedded); +} + /// A link entity is some sort of named declaration, combined with all /// the information necessary to distinguish specific implementations /// of the declaration from each other. @@ -828,6 +840,7 @@ class LinkEntity { static LinkEntity forTypeMetadata(CanType concreteType, TypeMetadataAddress addr) { assert(!isObjCImplementation(concreteType)); + assert(!isEmbedded(concreteType)); LinkEntity entity; entity.setForType(Kind::TypeMetadata, concreteType); entity.Data |= LINKENTITY_SET_FIELD(MetadataAddress, unsigned(addr)); @@ -835,6 +848,7 @@ class LinkEntity { } static LinkEntity forTypeMetadataPattern(NominalTypeDecl *decl) { + assert(!isEmbedded(decl)); LinkEntity entity; entity.setForDecl(Kind::TypeMetadataPattern, decl); return entity; @@ -891,6 +905,7 @@ class LinkEntity { static LinkEntity forNominalTypeDescriptor(NominalTypeDecl *decl) { assert(!isObjCImplementation(decl)); + assert(!isEmbedded(decl)); LinkEntity entity; entity.setForDecl(Kind::NominalTypeDescriptor, decl); return entity; @@ -898,18 +913,21 @@ class LinkEntity { static LinkEntity forNominalTypeDescriptorRecord(NominalTypeDecl *decl) { assert(!isObjCImplementation(decl)); + assert(!isEmbedded(decl)); LinkEntity entity; entity.setForDecl(Kind::NominalTypeDescriptorRecord, decl); return entity; } static LinkEntity forOpaqueTypeDescriptor(OpaqueTypeDecl *decl) { + assert(!isEmbedded(decl)); LinkEntity entity; entity.setForDecl(Kind::OpaqueTypeDescriptor, decl); return entity; } static LinkEntity forOpaqueTypeDescriptorRecord(OpaqueTypeDecl *decl) { + assert(!isEmbedded(decl)); LinkEntity entity; entity.setForDecl(Kind::OpaqueTypeDescriptorRecord, decl); return entity; @@ -990,6 +1008,7 @@ class LinkEntity { } static LinkEntity forValueWitness(CanType concreteType, ValueWitness witness) { + assert(!isEmbedded(concreteType)); LinkEntity entity; entity.Pointer = concreteType.getPointer(); entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::ValueWitness)) @@ -998,6 +1017,7 @@ class LinkEntity { } static LinkEntity forValueWitnessTable(CanType type) { + assert(!isEmbedded(type)); LinkEntity entity; entity.setForType(Kind::ValueWitnessTable, type); return entity; @@ -1027,6 +1047,7 @@ class LinkEntity { } static LinkEntity forProtocolWitnessTable(const RootProtocolConformance *C) { + assert(!isEmbedded(C)); LinkEntity entity; entity.setForProtocolConformance(Kind::ProtocolWitnessTable, C); return entity; @@ -1034,6 +1055,7 @@ class LinkEntity { static LinkEntity forProtocolWitnessTablePattern(const ProtocolConformance *C) { + assert(!isEmbedded(C)); LinkEntity entity; entity.setForProtocolConformance(Kind::ProtocolWitnessTablePattern, C); return entity; diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index c9ec7e7b1bc44..1c457ab6b6d0f 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -14,48 +14,31 @@ // //===----------------------------------------------------------------------===// -let Flags = [FrontendOption, NoDriverOption] in { - -def triple : Separate<["-"], "triple">, Alias; - -def primary_file : Separate<["-"], "primary-file">, - HelpText<"Produce output for this file, not the whole module">; +let Flags = [FrontendOption, NoDriverOption, ArgumentIsFileList] in { def filelist : Separate<["-"], "filelist">, HelpText<"Specify source inputs in a file rather than on the command line">; def primary_filelist : Separate<["-"], "primary-filelist">, HelpText<"Specify primary inputs in a file rather than on the command line">; + +} // end let Flags = [FrontendOption, NoDriverOption, ArgumentIsFileList] + + +let Flags = [FrontendOption, NoDriverOption, CacheInvariant] in { + def output_filelist : Separate<["-"], "output-filelist">, HelpText<"Specify outputs in a file rather than on the command line">; def supplementary_output_file_map : Separate<["-"], "supplementary-output-file-map">, HelpText<"Specify supplementary outputs in a file rather than on the command line">; +def index_unit_output_path_filelist : Separate<["-"], "index-unit-output-path-filelist">, + HelpText<"Specify index unit output paths in a file rather than on the command line">; -def frontend_parseable_output : Flag<["-"], "frontend-parseable-output">, - HelpText<"Emit textual output in a parseable format">; - -def emit_module_doc : Flag<["-"], "emit-module-doc">, - HelpText<"Emit a module documentation file based on documentation " - "comments">; def emit_module_doc_path : Separate<["-"], "emit-module-doc-path">, MetaVarName<"">, HelpText<"Output module documentation file ">; - -def emit_module_source_info : Flag<["-"], "emit-module-source-info">, - HelpText<"Output module source info file">; - -def ignore_module_source_info : Flag<["-"], "ignore-module-source-info">, - HelpText<"Avoid getting source location from .swiftsourceinfo files">; - -def merge_modules - : Flag<["-"], "merge-modules">, ModeOpt, - HelpText<"Merge the input modules without otherwise processing them">; - def emit_dependencies_path : Separate<["-"], "emit-dependencies-path">, MetaVarName<"">, HelpText<"Output basic Make-compatible dependencies file to ">; - -def emit_reference_dependencies : Flag<["-"], "emit-reference-dependencies">, - HelpText<"Emit a Swift-style dependencies file">; def emit_reference_dependencies_path : Separate<["-"], "emit-reference-dependencies-path">, MetaVarName<"">, HelpText<"Output Swift-style dependencies file to ">; @@ -63,15 +46,65 @@ def emit_reference_dependencies_path def emit_fixits_path : Separate<["-"], "emit-fixits-path">, MetaVarName<"">, HelpText<"Output compiler fixits as source edits to ">; - def emit_abi_descriptor_path : Separate<["-"], "emit-abi-descriptor-path">, MetaVarName<"">, HelpText<"Output the ABI descriptor of current module to ">; - def emit_module_semantic_info_path : Separate<["-"], "emit-module-semantic-info-path">, MetaVarName<"">, HelpText<"Output semantic info of current module to ">; +def diagnostic_documentation_path + : Separate<["-"], "diagnostic-documentation-path">, MetaVarName<"">, + HelpText<"Path to diagnostic documentation resources">; + +def dump_api_path : Separate<["-"], "dump-api-path">, + HelpText<"The path to output swift interface files for the compiled source files">; + +def group_info_path : Separate<["-"], "group-info-path">, + HelpText<"The path to collect the group information of the compiled module">; + +def prebuilt_module_cache_path : + Separate<["-"], "prebuilt-module-cache-path">, + HelpText<"Directory of prebuilt modules for loading module interfaces">; +def prebuilt_module_cache_path_EQ : + Joined<["-"], "prebuilt-module-cache-path=">, + Alias; + +def backup_module_interface_path : + Separate<["-"], "backup-module-interface-path">, + HelpText<"Directory of module interfaces as backups to those from SDKs">; +def backup_module_interface_path_EQ : + Joined<["-"], "backup-module-interface-path=">, + Alias; + +} // end let Flags = [FrontendOption, NoDriverOption, CacheInvariant] + + +let Flags = [FrontendOption, NoDriverOption] in { + +def triple : Separate<["-"], "triple">, Alias; + +def primary_file : Separate<["-"], "primary-file">, + HelpText<"Produce output for this file, not the whole module">; + +def frontend_parseable_output : Flag<["-"], "frontend-parseable-output">, + HelpText<"Emit textual output in a parseable format">; + +def emit_module_doc : Flag<["-"], "emit-module-doc">, + HelpText<"Emit a module documentation file based on documentation " + "comments">; + +def emit_module_source_info : Flag<["-"], "emit-module-source-info">, + HelpText<"Output module source info file">; +def ignore_module_source_info : Flag<["-"], "ignore-module-source-info">, + HelpText<"Avoid getting source location from .swiftsourceinfo files">; + +def merge_modules + : Flag<["-"], "merge-modules">, ModeOpt, + HelpText<"Merge the input modules without otherwise processing them">; +def emit_reference_dependencies : Flag<["-"], "emit-reference-dependencies">, + HelpText<"Emit a Swift-style dependencies file">; + def serialize_module_interface_dependency_hashes : Flag<["-"], "serialize-module-interface-dependency-hashes">, Flags<[HelpHidden]>; @@ -129,10 +162,6 @@ def enable_cross_import_overlays : Flag<["-"], "enable-cross-import-overlays">, def disable_cross_import_overlays : Flag<["-"], "disable-cross-import-overlays">, HelpText<"Do not automatically import declared cross-import overlays.">; -def diagnostic_documentation_path - : Separate<["-"], "diagnostic-documentation-path">, MetaVarName<"">, - HelpText<"Path to diagnostic documentation resources">; - def enable_testable_attr_requires_testable_module : Flag<["-"], "enable-testable-attr-requires-testable-module">, HelpText<"Enable checking of @testable">; @@ -904,9 +933,6 @@ def index_ignore_stdlib : Flag<["-"], "index-ignore-stdlib">, HelpText<"Avoid emitting index data for the standard library.">; -def index_unit_output_path_filelist : Separate<["-"], "index-unit-output-path-filelist">, - HelpText<"Specify index unit output paths in a file rather than on the command line">; - def dump_interface_hash : Flag<["-"], "dump-interface-hash">, HelpText<"Parse input file(s) and dump interface token hash(es)">, ModeOpt; @@ -969,29 +995,9 @@ def experimental_one_way_closure_params : Flag<["-"], "experimental-one-way-closure-params">, HelpText<"Enable experimental support for one-way closure parameters">; -def prebuilt_module_cache_path : - Separate<["-"], "prebuilt-module-cache-path">, - HelpText<"Directory of prebuilt modules for loading module interfaces">; -def prebuilt_module_cache_path_EQ : - Joined<["-"], "prebuilt-module-cache-path=">, - Alias; - -def backup_module_interface_path : - Separate<["-"], "backup-module-interface-path">, - HelpText<"Directory of module interfaces as backups to those from SDKs">; -def backup_module_interface_path_EQ : - Joined<["-"], "backup-module-interface-path=">, - Alias; - def force_public_linkage : Flag<["-"], "force-public-linkage">, HelpText<"Force public linkage for private symbols. Used by LLDB.">; -def dump_api_path : Separate<["-"], "dump-api-path">, - HelpText<"The path to output swift interface files for the compiled source files">; - -def group_info_path : Separate<["-"], "group-info-path">, - HelpText<"The path to collect the group information of the compiled module">; - def diagnostics_editor_mode : Flag<["-"], "diagnostics-editor-mode">, HelpText<"Diagnostics will be used in editor">; diff --git a/include/swift/Option/Options.h b/include/swift/Option/Options.h index 8961283d58909..0f24e0bd7d0df 100644 --- a/include/swift/Option/Options.h +++ b/include/swift/Option/Options.h @@ -43,6 +43,8 @@ namespace options { NewDriverOnlyOption = (1 << 18), ModuleInterfaceOptionIgnorable = (1 << 19), ModuleInterfaceOptionIgnorablePrivate = (1 << 20), + ArgumentIsFileList = (1 << 21), + CacheInvariant = (1 << 22), }; enum ID { diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 03c629e494643..e7b3dd1d5d4be 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -77,6 +77,15 @@ def SwiftAPIDigesterOption : OptionFlag; // The option only functions in the new driver. def NewDriverOnlyOption : OptionFlag; +// The option's argument is a path to a file that contains a list of files. +def ArgumentIsFileList : OptionFlag; + +// The option that is cache invariant. Change this option doesn't affect the +// content of any output file. The candidates are options like: `-o` which only +// affects the location of the output file, or `-emit-module` which defines +// which action is performed. +def CacheInvariant : OptionFlag; + ///////// // Options @@ -255,7 +264,7 @@ def _DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>, def o : JoinedOrSeparate<["-"], "o">, Flags<[FrontendOption, AutolinkExtractOption, ModuleWrapOption, NoInteractiveOption, SwiftIndentOption, ArgumentIsPath, - SwiftAPIExtractOption, SwiftAPIDigesterOption]>, + SwiftAPIExtractOption, SwiftAPIDigesterOption, CacheInvariant]>, HelpText<"Write output to ">, MetaVarName<"">; def j : JoinedOrSeparate<["-"], "j">, Flags<[DoesNotAffectIncrementalBuild]>, @@ -360,26 +369,26 @@ def profile_stats_entities: Flag<["-"], "profile-stats-entities">, HelpText<"Profile changes to stats in -stats-output-dir, subdivided by source entity">; def emit_dependencies : Flag<["-"], "emit-dependencies">, - Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>, + Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput, CacheInvariant]>, HelpText<"Emit basic Make-compatible dependencies files">; def track_system_dependencies : Flag<["-"], "track-system-dependencies">, Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>, HelpText<"Track system dependencies while emitting Make-style dependencies">; def emit_loaded_module_trace : Flag<["-"], "emit-loaded-module-trace">, - Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>, + Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput, CacheInvariant]>, HelpText<"Emit a JSON file containing information about what modules were loaded">; def emit_loaded_module_trace_path : Separate<["-"], "emit-loaded-module-trace-path">, Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath, - SupplementaryOutput]>, + SupplementaryOutput, CacheInvariant]>, HelpText<"Emit the loaded module trace JSON to ">, MetaVarName<"">; def emit_loaded_module_trace_path_EQ : Joined<["-"], "emit-loaded-module-trace-path=">, Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath, - SupplementaryOutput]>, + SupplementaryOutput, CacheInvariant]>, Alias; def emit_cross_import_remarks : Flag<["-"], "Rcross-import">, - Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>, + Flags<[FrontendOption, DoesNotAffectIncrementalBuild, CacheInvariant]>, HelpText<"Emit a remark if a cross-import of a module is triggered.">; def remark_loading_module : Flag<["-"], "Rmodule-loading">, @@ -403,15 +412,15 @@ def remark_skip_explicit_interface_build : Flag<["-"], "Rskip-explicit-interface def emit_tbd : Flag<["-"], "emit-tbd">, HelpText<"Emit a TBD file">, - Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>; + Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput, CacheInvariant]>; def emit_tbd_path : Separate<["-"], "emit-tbd-path">, Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath, - SupplementaryOutput]>, + SupplementaryOutput, CacheInvariant]>, HelpText<"Emit the TBD file to ">, MetaVarName<"">; def emit_tbd_path_EQ : Joined<["-"], "emit-tbd-path=">, Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath, - SupplementaryOutput]>, + SupplementaryOutput, CacheInvariant]>, Alias; def embed_tbd_for_module : Separate<["-"], "embed-tbd-for-module">, Flags<[FrontendOption]>, @@ -422,12 +431,12 @@ def serialize_diagnostics : Flag<["-"], "serialize-diagnostics">, HelpText<"Serialize diagnostics in a binary format">; def serialize_diagnostics_path : Separate<["-"], "serialize-diagnostics-path">, Flags<[FrontendOption, SwiftAPIDigesterOption, NoBatchOption, - ArgumentIsPath, SupplementaryOutput]>, + ArgumentIsPath, SupplementaryOutput, CacheInvariant]>, HelpText<"Emit a serialized diagnostics file to ">, MetaVarName<"">; def serialize_diagnostics_path_EQ: Joined<["-"], "serialize-diagnostics-path=">, Flags<[FrontendOption, SwiftAPIDigesterOption, NoBatchOption, - ArgumentIsPath, SupplementaryOutput]>, + ArgumentIsPath, SupplementaryOutput, CacheInvariant]>, Alias; def color_diagnostics : Flag<["-"], "color-diagnostics">, Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>, @@ -540,42 +549,42 @@ def export_as : Separate<["-"], "export-as">, HelpText<"Module name to use when referenced in clients module interfaces">; def emit_module : Flag<["-"], "emit-module">, - Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>, + Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput, CacheInvariant]>, HelpText<"Emit an importable module">; def emit_module_path : Separate<["-"], "emit-module-path">, Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath, - SupplementaryOutput]>, + SupplementaryOutput, CacheInvariant]>, HelpText<"Emit an importable module to ">, MetaVarName<"">; def emit_module_path_EQ : Joined<["-"], "emit-module-path=">, Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath, - SupplementaryOutput]>, + SupplementaryOutput, CacheInvariant]>, Alias; def emit_module_summary : Flag<["-"], "emit-module-summary">, - Flags<[NoInteractiveOption, SupplementaryOutput]>, + Flags<[NoInteractiveOption, SupplementaryOutput, CacheInvariant]>, HelpText<"Output module summary file">; def emit_module_summary_path : Separate<["-"], "emit-module-summary-path">, Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath, - SupplementaryOutput]>, + SupplementaryOutput, CacheInvariant]>, MetaVarName<"">, HelpText<"Output module summary file to ">; def emit_module_interface : Flag<["-"], "emit-module-interface">, - Flags<[NoInteractiveOption, SupplementaryOutput]>, + Flags<[NoInteractiveOption, SupplementaryOutput, CacheInvariant]>, HelpText<"Output module interface file">; def emit_module_interface_path : Separate<["-"], "emit-module-interface-path">, Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath, - SupplementaryOutput]>, + SupplementaryOutput, CacheInvariant]>, MetaVarName<"">, HelpText<"Output module interface file to ">; def emit_private_module_interface_path : Separate<["-"], "emit-private-module-interface-path">, Flags<[FrontendOption, NoInteractiveOption, HelpHidden, - ArgumentIsPath, SupplementaryOutput]>, + ArgumentIsPath, SupplementaryOutput, CacheInvariant]>, MetaVarName<"">, HelpText<"Output private module interface file to ">; def verify_emitted_module_interface : @@ -601,27 +610,27 @@ def emit_module_source_info_path : def emit_parseable_module_interface : Flag<["-"], "emit-parseable-module-interface">, Alias, - Flags<[NoInteractiveOption, HelpHidden, SupplementaryOutput]>; + Flags<[NoInteractiveOption, HelpHidden, SupplementaryOutput, CacheInvariant]>; def emit_parseable_module_interface_path : Separate<["-"], "emit-parseable-module-interface-path">, Alias, Flags<[FrontendOption, NoInteractiveOption, HelpHidden, ArgumentIsPath, - SupplementaryOutput]>; + SupplementaryOutput, CacheInvariant]>; def emit_const_values : Flag<["-"], "emit-const-values">, Flags<[NoInteractiveOption, SupplementaryOutput]>; def emit_const_values_path : Separate<["-"], "emit-const-values-path">, Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath, - SupplementaryOutput]>, + SupplementaryOutput, CacheInvariant]>, MetaVarName<"">, HelpText<"Emit the extracted compile-time known values to ">; def emit_objc_header : Flag<["-"], "emit-objc-header">, - Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>, + Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput, CacheInvariant]>, HelpText<"Emit an Objective-C header file">; def emit_objc_header_path : Separate<["-"], "emit-objc-header-path">, Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath, - SupplementaryOutput]>, + SupplementaryOutput, CacheInvariant]>, MetaVarName<"">, HelpText<"Emit an Objective-C header file to ">; def emit_clang_header_nonmodular_includes : Flag<["-"], "emit-clang-header-nonmodular-includes">, Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>, @@ -629,7 +638,7 @@ def emit_clang_header_nonmodular_includes : Flag<["-"], "emit-clang-header-nonmo def emit_clang_header_path : Separate<["-"], "emit-clang-header-path">, Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath, - SupplementaryOutput]>, + SupplementaryOutput, CacheInvariant]>, HelpText<"Emit an Objective-C and C++ header file to ">, Alias; @@ -1109,45 +1118,39 @@ def modes_Group : OptionGroup<"">, HelpText<"MODES">; class ModeOpt : Group; // Output Modes -def emit_executable : Flag<["-"], "emit-executable">, - HelpText<"Emit a linked executable">, ModeOpt, - Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>; -def emit_library : Flag<["-"], "emit-library">, - HelpText<"Emit a linked library">, ModeOpt, - Flags<[NoInteractiveOption]>; +let Flags = [FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild, CacheInvariant] in { + def emit_object : Flag<["-"], "emit-object">, - HelpText<"Emit object file(s) (-c)">, ModeOpt, - Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; + HelpText<"Emit object file(s) (-c)">, ModeOpt; def emit_assembly : Flag<["-"], "emit-assembly">, - HelpText<"Emit assembly file(s) (-S)">, ModeOpt, - Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; + HelpText<"Emit assembly file(s) (-S)">, ModeOpt; def emit_bc : Flag<["-"], "emit-bc">, - HelpText<"Emit LLVM BC file(s)">, ModeOpt, - Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; + HelpText<"Emit LLVM BC file(s)">, ModeOpt; def emit_irgen : Flag<["-"], "emit-irgen">, - HelpText<"Emit LLVM IR file(s) before LLVM optimizations">, ModeOpt, - Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; + HelpText<"Emit LLVM IR file(s) before LLVM optimizations">, ModeOpt; def emit_ir : Flag<["-"], "emit-ir">, - HelpText<"Emit LLVM IR file(s) after LLVM optimizations">, ModeOpt, - Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; + HelpText<"Emit LLVM IR file(s) after LLVM optimizations">, ModeOpt; def emit_sil : Flag<["-"], "emit-sil">, - HelpText<"Emit canonical SIL file(s)">, ModeOpt, - Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; + HelpText<"Emit canonical SIL file(s)">, ModeOpt; def emit_silgen : Flag<["-"], "emit-silgen">, - HelpText<"Emit raw SIL file(s)">, ModeOpt, - Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; + HelpText<"Emit raw SIL file(s)">, ModeOpt; def emit_sib : Flag<["-"], "emit-sib">, - HelpText<"Emit serialized AST + canonical SIL file(s)">, ModeOpt, - Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; + HelpText<"Emit serialized AST + canonical SIL file(s)">, ModeOpt; def emit_sibgen : Flag<["-"], "emit-sibgen">, - HelpText<"Emit serialized AST + raw SIL file(s)">, ModeOpt, - Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; + HelpText<"Emit serialized AST + raw SIL file(s)">, ModeOpt; def emit_imported_modules : Flag<["-"], "emit-imported-modules">, - HelpText<"Emit a list of the imported modules">, ModeOpt, - Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; + HelpText<"Emit a list of the imported modules">, ModeOpt; def emit_pcm : Flag<["-"], "emit-pcm">, - HelpText<"Emit a precompiled Clang module from a module map">, ModeOpt, - Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; + HelpText<"Emit a precompiled Clang module from a module map">, ModeOpt; + +} // end let Flags = [FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild, CacheInvariant] + +def emit_executable : Flag<["-"], "emit-executable">, + HelpText<"Emit a linked executable">, ModeOpt, + Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>; +def emit_library : Flag<["-"], "emit-library">, + HelpText<"Emit a linked library">, ModeOpt, + Flags<[NoInteractiveOption]>; def c : Flag<["-"], "c">, Alias, Flags<[FrontendOption, NoInteractiveOption]>, ModeOpt; @@ -1240,7 +1243,7 @@ def force_single_frontend_invocation : Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>; def num_threads : Separate<["-"], "num-threads">, - Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>, + Flags<[FrontendOption, DoesNotAffectIncrementalBuild, CacheInvariant]>, HelpText<"Enable multi-threading and specify number of threads">, MetaVarName<"">; @@ -1386,7 +1389,7 @@ def index_store_path : Separate<["-"], "index-store-path">, HelpText<"Store indexing data to ">; def index_unit_output_path : Separate<["-"], "index-unit-output-path">, - Flags<[FrontendOption, ArgumentIsPath]>, MetaVarName<"">, + Flags<[FrontendOption, ArgumentIsPath, CacheInvariant]>, MetaVarName<"">, HelpText<"Use as the output path in the produced index data.">; def index_ignore_clang_modules : Flag<["-"], "index-ignore-clang-modules">, @@ -1827,15 +1830,15 @@ def cache_compile_job: Flag<["-"], "cache-compile-job">, HelpText<"Enable compiler caching">; def cache_remarks: Flag<["-"], "Rcache-compile-job">, - Flags<[FrontendOption, NewDriverOnlyOption]>, + Flags<[FrontendOption, NewDriverOnlyOption, CacheInvariant]>, HelpText<"Show remarks for compiler caching">; def cache_disable_replay: Flag<["-"], "cache-disable-replay">, - Flags<[FrontendOption, NewDriverOnlyOption]>, + Flags<[FrontendOption, NewDriverOnlyOption, CacheInvariant]>, HelpText<"Skip loading the compilation result from cache">; def cas_path: Separate<["-"], "cas-path">, - Flags<[FrontendOption, NewDriverOnlyOption]>, + Flags<[FrontendOption, NewDriverOnlyOption, CacheInvariant]>, HelpText<"Path to CAS">, MetaVarName<"">; def cas_plugin_path: Separate<["-"], "cas-plugin-path">, diff --git a/include/swift/Parse/IDEInspectionCallbacks.h b/include/swift/Parse/IDEInspectionCallbacks.h index 3b757b5ec46ee..10a573f6a03f4 100644 --- a/include/swift/Parse/IDEInspectionCallbacks.h +++ b/include/swift/Parse/IDEInspectionCallbacks.h @@ -230,10 +230,7 @@ class CodeCompletionCallbacks { return false; } - virtual void completeLabeledTrailingClosure(CodeCompletionExpr *E, - bool isAtStartOfLine) {}; - - virtual void completeReturnStmt(CodeCompletionExpr *E) {}; + virtual void completeReturnStmt(CodeCompletionExpr *E){}; virtual void completeThenStmt(CodeCompletionExpr *E) {}; diff --git a/include/swift/RemoteInspection/TypeRefBuilder.h b/include/swift/RemoteInspection/TypeRefBuilder.h index cd562ec8d0b2e..c9f93fca1ad3f 100644 --- a/include/swift/RemoteInspection/TypeRefBuilder.h +++ b/include/swift/RemoteInspection/TypeRefBuilder.h @@ -424,6 +424,18 @@ class TypeRefBuilder { /// Cache for field info lookups. std::unordered_map> FieldTypeInfoCache; + /// Cache for normalized reflection name lookups. + std::unordered_map> + NormalizedReflectionNameCache; + + /// Cache for built-in type descriptor lookups. + std::unordered_map> + BuiltInTypeDescriptorCache; + + /// The index of the last ReflectionInfo cached by BuiltInTypeDescriptorCache. + uint32_t NormalizedReflectionNameCacheLastReflectionInfoCache = 0; + std::vector> SignatureRefPool; TypeConverter TC; diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h index e53deac6390e4..763469260fb69 100644 --- a/include/swift/Runtime/Metadata.h +++ b/include/swift/Runtime/Metadata.h @@ -1046,6 +1046,18 @@ void swift_initRawStructMetadata(StructMetadata *self, const TypeLayout *likeType, int32_t count); +/// Check if the given generic arguments are valid inputs for the generic type +/// context and if so call the metadata access function and return the metadata. +/// +/// Note: This expects the caller to heap allocate all pack pointers within the +/// generic arguments via 'swift_allocateMetadataPack'. +SWIFT_RUNTIME_STDLIB_SPI +SWIFT_CC(swift) +const Metadata *_swift_instantiateCheckedGenericMetadata( + const TypeContextDescriptor *context, + const void * const *genericArgs, + size_t genericArgsSize); + #pragma clang diagnostic pop } // end namespace swift diff --git a/include/swift/SIL/InstWrappers.h b/include/swift/SIL/InstWrappers.h index c94c199124894..ee7ca4a0f11e6 100644 --- a/include/swift/SIL/InstWrappers.h +++ b/include/swift/SIL/InstWrappers.h @@ -252,44 +252,34 @@ class ForwardingOperation { ValueOwnershipKind getForwardingOwnershipKind(); bool preservesOwnership(); - // FIXME: Find a better name. Even unary instructions like struct_extract - // forward "all" operands. - bool canForwardAllOperands() const { + Operand *getSingleForwardingOperand() const { switch (forwardingInst->getKind()) { case SILInstructionKind::StructInst: case SILInstructionKind::TupleInst: case SILInstructionKind::LinearFunctionInst: case SILInstructionKind::DifferentiableFunctionInst: - return true; + return nullptr; default: - return false; + if (forwardingInst->getNumRealOperands() == 0) { + // This can happen with enum instructions that have no payload. + return nullptr; + } + return &forwardingInst->getOperandRef(0); } } - // FIXME: Find a better name. Even instructions that forward all operands can - // forward the first operand. - bool canForwardFirstOperandOnly() const { - return !canForwardAllOperands() && forwardingInst->getNumRealOperands() > 0; - } - ArrayRef getForwardedOperands() const { - if (canForwardAllOperands()) { - return forwardingInst->getAllOperands(); + if (auto *singleForwardingOp = getSingleForwardingOperand()) { + return *singleForwardingOp; } - if (canForwardFirstOperandOnly()) { - return forwardingInst->getOperandRef(0); - } - return {}; + return forwardingInst->getAllOperands(); } MutableArrayRef getForwardedOperands() { - if (canForwardAllOperands()) { - return forwardingInst->getAllOperands(); - } - if (canForwardFirstOperandOnly()) { - return forwardingInst->getOperandRef(0); + if (auto *singleForwardingOp = getSingleForwardingOperand()) { + return *singleForwardingOp; } - return {}; + return forwardingInst->getAllOperands(); } bool canForwardOwnedCompatibleValuesOnly() { @@ -321,6 +311,10 @@ class ForwardingOperation { /// Return true if the forwarded value is address-only either before or after /// forwarding. bool isAddressOnly() const; + + // Call \p visitor on all forwarded results of the current forwarding + // operation. + bool visitForwardedValues(function_ref visitor); }; } // end namespace swift diff --git a/include/swift/SIL/RuntimeEffect.h b/include/swift/SIL/RuntimeEffect.h index 85616a6882dcb..57d95b23b9761 100644 --- a/include/swift/SIL/RuntimeEffect.h +++ b/include/swift/SIL/RuntimeEffect.h @@ -52,6 +52,9 @@ enum class RuntimeEffect : unsigned { /// The runtime function calls ObjectiveC methods. ObjectiveC = 0x40, + /// Witness methods, boxing, unboxing, initializing, etc. + Existential = 0x80, + /// Not modelled currently. Concurrency = 0x0, diff --git a/include/swift/SIL/SILBridging.h b/include/swift/SIL/SILBridging.h index d889112ded7e7..f7492f255920a 100644 --- a/include/swift/SIL/SILBridging.h +++ b/include/swift/SIL/SILBridging.h @@ -260,6 +260,10 @@ struct BridgedFunction { return getFunction()->isGlobalInitOnceFunction(); } + bool isGenericFunction() const { + return getFunction()->getGenericSignature().isNull(); + } + bool hasSemanticsAttr(llvm::StringRef attrName) const { return getFunction()->hasSemanticsAttr(attrName); } diff --git a/include/swift/SILOptimizer/OptimizerBridging.h b/include/swift/SILOptimizer/OptimizerBridging.h index 36292455b94b5..54312f2b204e9 100644 --- a/include/swift/SILOptimizer/OptimizerBridging.h +++ b/include/swift/SILOptimizer/OptimizerBridging.h @@ -494,6 +494,11 @@ struct BridgedPassContext { return mod->getOptions().EnableStackProtection; } + bool enableEmbeddedSwift() const { + swift::SILModule *mod = invocation->getPassManager()->getModule(); + return mod->getASTContext().LangOpts.hasFeature(swift::Feature::Embedded); + } + bool enableMoveInoutStackProtection() const { swift::SILModule *mod = invocation->getPassManager()->getModule(); return mod->getOptions().EnableMoveInoutStackProtection; diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 5227daff14c8b..a4a83ef69d188 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -6238,18 +6238,29 @@ class ConjunctionElementProducer : public BindingProducer { } }; -/// Find any references to not yet resolved outer VarDecls (including closure -/// parameters) used in the body of a conjunction element (e.g closures, taps, -/// if/switch expressions). This is required because isolated conjunctions, just -/// like single-expression closures, have to be connected to type variables they -/// are going to use, otherwise they'll get placed in a separate solver -/// component and would never produce a solution. -class VarRefCollector : public ASTWalker { +/// Find any references to external type variables used in the body of a +/// conjunction element (e.g closures, taps, if/switch expressions). +/// +/// This includes: +/// - Not yet resolved outer VarDecls (including closure parameters) +/// - Return statements with a contextual type that has not yet been resolved +/// +/// This is required because isolated conjunctions, just like single-expression +/// closures, have to be connected to type variables they are going to use, +/// otherwise they'll get placed in a separate solver component and would never +/// produce a solution. +class TypeVarRefCollector : public ASTWalker { ConstraintSystem &CS; + DeclContext *DC; + ConstraintLocator *Locator; + llvm::SmallSetVector TypeVars; + unsigned DCDepth = 0; public: - VarRefCollector(ConstraintSystem &cs) : CS(cs) {} + TypeVarRefCollector(ConstraintSystem &cs, DeclContext *dc, + ConstraintLocator *locator) + : CS(cs), DC(dc), Locator(locator) {} /// Infer the referenced type variables from a given decl. void inferTypeVars(Decl *D); @@ -6259,6 +6270,8 @@ class VarRefCollector : public ASTWalker { } PreWalkResult walkToExprPre(Expr *expr) override; + PostWalkResult walkToExprPost(Expr *expr) override; + PreWalkResult walkToStmtPre(Stmt *stmt) override; PreWalkAction walkToDeclPre(Decl *D) override { // We only need to walk into PatternBindingDecls, other kinds of decls diff --git a/include/swift/Sema/IDETypeChecking.h b/include/swift/Sema/IDETypeChecking.h index f68b6394411a7..5dea28c50998c 100644 --- a/include/swift/Sema/IDETypeChecking.h +++ b/include/swift/Sema/IDETypeChecking.h @@ -128,20 +128,6 @@ namespace swift { ASTContext &Ctx, DeclContext *DC, CompletionTypeCheckKind kind, Expr *&parsedExpr, ConcreteDeclRef &referencedDecl); - /// Resolve type of operator function with \c opName appending it to \c LHS. - /// - /// For \p refKind, use \c DeclRefKind::PostfixOperator for postfix operator, - /// or \c DeclRefKind::BinaryOperator for infix operator. - /// On success, returns resolved function type of the operator. The LHS should - /// already be type-checked. This function guarantees LHS not to be modified. - FunctionType *getTypeOfCompletionOperator(DeclContext *DC, Expr *LHS, - Identifier opName, - DeclRefKind refKind, - ConcreteDeclRef &referencedDecl); - - /// Typecheck the given expression. - bool typeCheckExpression(DeclContext *DC, Expr *&parsedExpr); - /// Type check a function body element which is at \p TagetLoc. bool typeCheckASTNodeAtLoc(TypeCheckASTNodeAtLocContext TypeCheckCtx, SourceLoc TargetLoc); diff --git a/include/swift/Serialization/SerializationOptions.h b/include/swift/Serialization/SerializationOptions.h index 2ae9a961268f9..b1822fa26b264 100644 --- a/include/swift/Serialization/SerializationOptions.h +++ b/include/swift/Serialization/SerializationOptions.h @@ -155,6 +155,7 @@ namespace swift { bool DisableCrossModuleIncrementalInfo = false; bool StaticLibrary = false; bool HermeticSealAtLink = false; + bool EmbeddedSwiftModule = false; bool IsOSSA = false; bool SerializeExternalDeclsOnly = false; }; diff --git a/include/swift/Serialization/Validation.h b/include/swift/Serialization/Validation.h index c1481ecf1bf47..8fab29d5001db 100644 --- a/include/swift/Serialization/Validation.h +++ b/include/swift/Serialization/Validation.h @@ -128,6 +128,7 @@ class ExtendedValidationInfo { unsigned IsSIB : 1; unsigned IsStaticLibrary : 1; unsigned HasHermeticSealAtLink : 1; + unsigned IsEmbeddedSwiftModule : 1; unsigned IsTestable : 1; unsigned ResilienceStrategy : 2; unsigned IsImplicitDynamicEnabled : 1; @@ -181,6 +182,10 @@ class ExtendedValidationInfo { void setHasHermeticSealAtLink(bool val) { Bits.HasHermeticSealAtLink = val; } + bool isEmbeddedSwiftModule() const { return Bits.IsEmbeddedSwiftModule; } + void setIsEmbeddedSwiftModule(bool val) { + Bits.IsEmbeddedSwiftModule = val; + } bool isTestable() const { return Bits.IsTestable; } void setIsTestable(bool val) { Bits.IsTestable = val; diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 80e458e546027..a023f831adae6 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -569,11 +569,11 @@ namespace { PrintWithColorRAII(OS, DeclModifierColor) << " trailing_semi"; } - void printInherited(ArrayRef Inherited) { + void printInherited(InheritedTypes Inherited) { if (Inherited.empty()) return; OS << " inherits: "; - interleave(Inherited, + interleave(Inherited.getEntries(), [&](InheritedEntry Super) { Super.getType().print(OS); }, [&] { OS << ", "; }); } diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index f699d042b6dc9..2d7e6b9b5f079 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -2954,8 +2954,8 @@ static bool usesFeatureRethrowsProtocol( return false; // Check an inheritance clause for a marker protocol. - auto checkInherited = [&](ArrayRef inherited) -> bool { - for (const auto &inheritedEntry : inherited) { + auto checkInherited = [&](InheritedTypes inherited) -> bool { + for (const auto &inheritedEntry : inherited.getEntries()) { if (auto inheritedType = inheritedEntry.getType()) { if (inheritedType->isExistentialType()) { auto layout = inheritedType->getExistentialLayout(); @@ -3148,6 +3148,10 @@ static bool usesFeatureBuiltinStackAlloc(Decl *decl) { return false; } +static bool usesFeatureEmbedded(Decl *decl) { + return false; +} + static bool usesFeatureBuiltinUnprotectedStackAlloc(Decl *decl) { return false; } @@ -7681,15 +7685,10 @@ void swift::getInheritedForPrinting( const Decl *decl, const PrintOptions &options, llvm::SmallVectorImpl &Results) { - ArrayRef inherited; - if (auto td = dyn_cast(decl)) { - inherited = td->getInherited(); - } else if (auto ed = dyn_cast(decl)) { - inherited = ed->getInherited(); - } + InheritedTypes inherited = InheritedTypes(decl); // Collect explicit inherited types. - for (auto entry: inherited) { + for (auto entry : inherited.getEntries()) { if (auto ty = entry.getType()) { bool foundUnprintable = ty.findIf([&](Type subTy) { if (auto aliasTy = dyn_cast(subTy.getPointer())) @@ -7831,7 +7830,7 @@ void GenericParamList::print(ASTPrinter &Printer, if (!P->getInherited().empty()) { Printer << " : "; - auto loc = P->getInherited()[0]; + auto loc = P->getInherited().getEntry(0); if (willUseTypeReprPrinting(loc, nullptr, PO)) { loc.getTypeRepr()->print(Printer, PO); } else { diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp index 8c4c3d2c8adf1..89ef8706486af 100644 --- a/lib/AST/ASTWalker.cpp +++ b/lib/AST/ASTWalker.cpp @@ -164,8 +164,9 @@ class Traversal : public ASTVisitorgetExtendedTypeRepr()) if (doIt(typeRepr)) return true; - for (auto &Inherit : ED->getInherited()) { - if (auto *const TyR = Inherit.getTypeRepr()) + auto inheritedTypes = ED->getInherited(); + for (auto i : inheritedTypes.getIndices()) { + if (auto *const TyR = inheritedTypes.getTypeRepr(i)) if (doIt(TyR)) return true; } @@ -276,7 +277,7 @@ class Traversal : public ASTVisitorgetInherited()) { + for (const auto &Inherit : GTPD->getInherited().getEntries()) { if (auto *const TyR = Inherit.getTypeRepr()) if (doIt(TyR)) return true; @@ -285,7 +286,7 @@ class Traversal : public ASTVisitorgetInherited()) { + for (const auto &Inherit : ATD->getInherited().getEntries()) { if (auto *const TyR = Inherit.getTypeRepr()) if (doIt(TyR)) return true; @@ -310,9 +311,10 @@ class Traversal : public ASTVisitorgetInherited()) { - if (auto *const TyR = Inherit.getTypeRepr()) - if (doIt(Inherit.getTypeRepr())) + auto inheritedTypes = NTD->getInherited(); + for (auto i : inheritedTypes.getIndices()) { + if (auto *const TyR = inheritedTypes.getTypeRepr(i)) + if (doIt(TyR)) return true; } diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp index baa78d15a3345..f462542918be9 100644 --- a/lib/AST/Attr.cpp +++ b/lib/AST/Attr.cpp @@ -1393,7 +1393,7 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options, // Print conformances, if present. auto conformances = evaluateOrDefault( D->getASTContext().evaluator, - ResolveExtensionMacroConformances{Attr, D}, + ResolveMacroConformances{Attr, D}, {}); if (!conformances.empty()) { Printer << ", conformances: "; diff --git a/lib/AST/ConformanceLookupTable.cpp b/lib/AST/ConformanceLookupTable.cpp index 2e07e6b57d22c..971ba5557eef7 100644 --- a/lib/AST/ConformanceLookupTable.cpp +++ b/lib/AST/ConformanceLookupTable.cpp @@ -226,7 +226,7 @@ void ConformanceLookupTable::inheritConformances(ClassDecl *classDecl, if (superclassLoc.isValid()) return superclassLoc; - for (const auto &inherited : classDecl->getInherited()) { + for (const auto &inherited : classDecl->getInherited().getEntries()) { if (auto inheritedType = inherited.getType()) { if (inheritedType->getClassOrBoundGenericClass()) { superclassLoc = inherited.getSourceRange().Start; @@ -506,7 +506,8 @@ void ConformanceLookupTable::addMacroGeneratedProtocols( MacroRole::Extension, [&](CustomAttr *attr, MacroDecl *macro) { SmallVector conformances; - macro->getIntroducedConformances(nominal, conformances); + macro->getIntroducedConformances( + nominal, MacroRole::Extension, conformances); for (auto *protocol : conformances) { addProtocol(protocol, attr->getLocation(), source); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 44aa5ab327da5..a8724f18fc261 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1527,6 +1527,47 @@ InheritedEntry::InheritedEntry(const TypeLoc &typeLoc) isUnchecked = typeRepr->findUncheckedAttrLoc().isValid(); } +InheritedTypes::InheritedTypes( + llvm::PointerUnion decl) + : Decl(decl) { + if (auto *typeDecl = decl.dyn_cast()) { + Entries = typeDecl->Inherited; + } else { + Entries = decl.get()->Inherited; + } +} + +InheritedTypes::InheritedTypes(const class Decl *decl) { + if (auto typeDecl = dyn_cast(decl)) { + Decl = typeDecl; + Entries = typeDecl->Inherited; + } else if (auto extensionDecl = dyn_cast(decl)) { + Decl = extensionDecl; + Entries = extensionDecl->Inherited; + } else { + Decl = nullptr; + Entries = ArrayRef(); + } +} + +InheritedTypes::InheritedTypes(const TypeDecl *typeDecl) : Decl(typeDecl) { + Entries = typeDecl->Inherited; +} + +InheritedTypes::InheritedTypes(const ExtensionDecl *extensionDecl) + : Decl(extensionDecl) { + Entries = extensionDecl->Inherited; +} + +Type InheritedTypes::getResolvedType(unsigned i, + TypeResolutionStage stage) const { + ASTContext &ctx = Decl.is() + ? Decl.get()->getASTContext() + : Decl.get()->getASTContext(); + return evaluateOrDefault(ctx.evaluator, InheritedTypeRequest{Decl, i, stage}, + Type()); +} + ExtensionDecl::ExtensionDecl(SourceLoc extensionLoc, TypeRepr *extendedType, ArrayRef inherited, @@ -5182,7 +5223,7 @@ SourceRange GenericTypeParamDecl::getSourceRange() const { startLoc = eachLoc; if (!getInherited().empty()) - endLoc = getInherited().back().getSourceRange().End; + endLoc = getInherited().getEndLoc(); return {startLoc, endLoc}; } @@ -5220,7 +5261,7 @@ SourceRange AssociatedTypeDecl::getSourceRange() const { } else if (auto defaultDefinition = getDefaultDefinitionTypeRepr()) { endLoc = defaultDefinition->getEndLoc(); } else if (!getInherited().empty()) { - endLoc = getInherited().back().getSourceRange().End; + endLoc = getInherited().getEndLoc(); } else { endLoc = getNameLoc(); } @@ -7861,27 +7902,30 @@ Type DeclContext::getSelfTypeInContext() const { return mapTypeIntoContext(getSelfInterfaceType()); } -TupleType *BuiltinTupleDecl::getTupleSelfType() const { - if (TupleSelfType) - return TupleSelfType; - +TupleType *BuiltinTupleDecl::getTupleSelfType(const ExtensionDecl *owner) const { auto &ctx = getASTContext(); - // Get the generic parameter type 'Elements'. - auto paramType = getGenericParams()->getParams()[0] - ->getDeclaredInterfaceType(); + // Get the generic parameter type 'each T'. + GenericParamList *genericParams; + if (owner != nullptr) { + genericParams = owner->getGenericParams(); + } else { + genericParams = getGenericParams(); + } + + assert(genericParams != nullptr); + assert(genericParams->getParams().size() == 1); + assert(genericParams->getOuterParameters() == nullptr); + auto paramType = genericParams->getParams()[0]->getDeclaredInterfaceType(); - // Build the pack expansion type 'Elements...'. + // Build the pack expansion type 'repeat each T'. Type packExpansionType = PackExpansionType::get(paramType, paramType); - // Build the one-element tuple type '(Elements...)'. + // Build the one-element tuple type '(repeat each T)'. SmallVector elts; elts.push_back(packExpansionType); - const_cast(this)->TupleSelfType = - TupleType::get(elts, ctx); - - return TupleSelfType; + return TupleType::get(elts, ctx); } /// Retrieve the interface type of 'self' for the given context. @@ -7890,7 +7934,7 @@ Type DeclContext::getSelfInterfaceType() const { if (auto *nominalDecl = getSelfNominalTypeDecl()) { if (auto *builtinTupleDecl = dyn_cast(nominalDecl)) - return builtinTupleDecl->getTupleSelfType(); + return builtinTupleDecl->getTupleSelfType(dyn_cast(this)); if (isa(nominalDecl)) { auto *genericParams = nominalDecl->getGenericParams(); @@ -10845,15 +10889,16 @@ void MacroDecl::getIntroducedNames(MacroRole role, ValueDecl *attachedTo, void MacroDecl::getIntroducedConformances( NominalTypeDecl *attachedTo, + MacroRole role, SmallVectorImpl &conformances) const { - auto *attr = getMacroRoleAttr(MacroRole::Extension); + auto *attr = getMacroRoleAttr(role); if (!attr) return; auto &ctx = getASTContext(); auto constraintTypes = evaluateOrDefault( ctx.evaluator, - ResolveExtensionMacroConformances{attr, this}, + ResolveMacroConformances{attr, this}, {}); for (auto constraint : constraintTypes) { diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 56ab0ccdf9980..788345943ad67 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -718,6 +718,7 @@ ModuleDecl::ModuleDecl(Identifier name, ASTContext &ctx, Bits.ModuleDecl.IsMainModule = 0; Bits.ModuleDecl.HasIncrementalInfo = 0; Bits.ModuleDecl.HasHermeticSealAtLink = 0; + Bits.ModuleDecl.IsEmbeddedSwiftModule = 0; Bits.ModuleDecl.IsConcurrencyChecked = 0; Bits.ModuleDecl.ObjCNameLookupCachePopulated = 0; Bits.ModuleDecl.HasCxxInteroperability = 0; diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index 7dcf8dda36677..ea621cb885cb5 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -1071,12 +1071,19 @@ directReferencesForTypeRepr(Evaluator &evaluator, ASTContext &ctx, /// the given type. static DirectlyReferencedTypeDecls directReferencesForType(Type type); +enum class ResolveToNominalFlags : uint8_t { + AllowTupleType = 0x1 +}; + +using ResolveToNominalOptions = OptionSet; + /// Given a set of type declarations, find all of the nominal type declarations /// that they reference, looking through typealiases as appropriate. static TinyPtrVector resolveTypeDeclsToNominal(Evaluator &evaluator, ASTContext &ctx, ArrayRef typeDecls, + ResolveToNominalOptions options, SmallVectorImpl &modulesFound, bool &anyObject); @@ -1130,6 +1137,7 @@ SelfBounds SelfBoundsFromWhereClauseRequest::evaluate( SmallVector modulesFound; auto rhsNominals = resolveTypeDeclsToNominal(evaluator, ctx, rhsDecls, + ResolveToNominalOptions(), modulesFound, result.anyObject); result.decls.insert(result.decls.end(), @@ -1168,7 +1176,8 @@ SelfBounds SelfBoundsFromGenericSignatureRequest::evaluate( auto rhsDecls = directReferencesForType(req.getSecondType()); SmallVector modulesFound; auto rhsNominals = resolveTypeDeclsToNominal( - evaluator, ctx, rhsDecls, modulesFound, result.anyObject); + evaluator, ctx, rhsDecls, ResolveToNominalOptions(), + modulesFound, result.anyObject); result.decls.insert(result.decls.end(), rhsNominals.begin(), rhsNominals.end()); } @@ -2651,6 +2660,7 @@ static TinyPtrVector resolveTypeDeclsToNominal(Evaluator &evaluator, ASTContext &ctx, ArrayRef typeDecls, + ResolveToNominalOptions options, SmallVectorImpl &modulesFound, bool &anyObject, llvm::SmallPtrSetImpl &typealiases) { @@ -2664,6 +2674,14 @@ resolveTypeDeclsToNominal(Evaluator &evaluator, for (auto typeDecl : typeDecls) { // Nominal type declarations get copied directly. if (auto nominalDecl = dyn_cast(typeDecl)) { + // ... unless it's the special Builtin.TheTupleType that we return + // when resolving a TupleTypeRepr, and the caller isn't asking for + // that. + if (!options.contains(ResolveToNominalFlags::AllowTupleType) && + isa(nominalDecl)) { + continue; + } + addNominalDecl(nominalDecl); continue; } @@ -2680,7 +2698,7 @@ resolveTypeDeclsToNominal(Evaluator &evaluator, auto underlyingNominalReferences = resolveTypeDeclsToNominal(evaluator, ctx, underlyingTypeReferences, - modulesFound, anyObject, typealiases); + options, modulesFound, anyObject, typealiases); std::for_each(underlyingNominalReferences.begin(), underlyingNominalReferences.end(), addNominalDecl); @@ -2731,11 +2749,12 @@ static TinyPtrVector resolveTypeDeclsToNominal(Evaluator &evaluator, ASTContext &ctx, ArrayRef typeDecls, + ResolveToNominalOptions options, SmallVectorImpl &modulesFound, bool &anyObject) { llvm::SmallPtrSet typealiases; - return resolveTypeDeclsToNominal(evaluator, ctx, typeDecls, modulesFound, - anyObject, typealiases); + return resolveTypeDeclsToNominal(evaluator, ctx, typeDecls, options, + modulesFound, anyObject, typealiases); } /// Perform unqualified name lookup for types at the given location. @@ -2839,8 +2858,9 @@ directReferencesForQualifiedTypeLookup(Evaluator &evaluator, SmallVector moduleDecls; bool anyObject = false; auto nominalTypeDecls = - resolveTypeDeclsToNominal(ctx.evaluator, ctx, baseTypes, moduleDecls, - anyObject); + resolveTypeDeclsToNominal(ctx.evaluator, ctx, baseTypes, + ResolveToNominalOptions(), + moduleDecls, anyObject); dc->lookupQualified(nominalTypeDecls, name, loc, options, members); @@ -2956,6 +2976,8 @@ directReferencesForTypeRepr(Evaluator &evaluator, return directReferencesForTypeRepr(evaluator, ctx, tupleRepr->getElementType(0), dc, allowUsableFromInline); + } else { + return { 1, ctx.getBuiltinTupleDecl() }; } return { }; } @@ -3019,6 +3041,9 @@ static DirectlyReferencedTypeDecls directReferencesForType(Type type) { if (auto genericDecl = type->getAnyGeneric()) return { 1, genericDecl }; + if (dyn_cast(type.getPointer())) + return { 1, type->getASTContext().getBuiltinTupleDecl() }; + if (type->isExistentialType()) { DirectlyReferencedTypeDecls result; const auto &layout = type->getExistentialLayout(); @@ -3045,7 +3070,7 @@ DirectlyReferencedTypeDecls InheritedDeclsReferencedRequest::evaluate( unsigned index) const { // Prefer syntactic information when we have it. - const TypeLoc &typeLoc = getInheritedTypeLocAtIndex(decl, index); + const TypeLoc &typeLoc = InheritedTypes(decl).getEntry(index); if (auto typeRepr = typeLoc.getTypeRepr()) { // Figure out the context in which name lookup will occur. DeclContext *dc; @@ -3112,7 +3137,7 @@ SuperclassDeclRequest::evaluate(Evaluator &evaluator, return classDecl; } - for (unsigned i : indices(subject->getInherited())) { + for (unsigned i : subject->getInherited().getIndices()) { // Find the inherited declarations referenced at this position. auto inheritedTypes = evaluateOrDefault(evaluator, InheritedDeclsReferencedRequest{subject, i}, {}); @@ -3122,7 +3147,8 @@ SuperclassDeclRequest::evaluate(Evaluator &evaluator, bool anyObject = false; auto inheritedNominalTypes = resolveTypeDeclsToNominal(evaluator, Ctx, - inheritedTypes, modulesFound, anyObject); + inheritedTypes, ResolveToNominalOptions(), + modulesFound, anyObject); // Look for a class declaration. ClassDecl *superclass = nullptr; @@ -3191,9 +3217,10 @@ NominalTypeDecl * ExtendedNominalRequest::evaluate(Evaluator &evaluator, ExtensionDecl *ext) const { auto typeRepr = ext->getExtendedTypeRepr(); - if (!typeRepr) + if (!typeRepr) { // We must've seen 'extension { ... }' during parsing. return nullptr; + } ASTContext &ctx = ext->getASTContext(); DirectlyReferencedTypeDecls referenced = @@ -3204,8 +3231,9 @@ ExtendedNominalRequest::evaluate(Evaluator &evaluator, SmallVector modulesFound; bool anyObject = false; auto nominalTypes - = resolveTypeDeclsToNominal(evaluator, ctx, referenced, modulesFound, - anyObject); + = resolveTypeDeclsToNominal(evaluator, ctx, referenced, + ResolveToNominalFlags::AllowTupleType, + modulesFound, anyObject); // If there is more than 1 element, we will emit a warning or an error // elsewhere, so don't handle that case here. @@ -3251,10 +3279,10 @@ bool TypeRepr::isProtocolOrProtocolComposition(DeclContext *dc){ static GenericParamList * createExtensionGenericParams(ASTContext &ctx, ExtensionDecl *ext, - NominalTypeDecl *nominal) { + DeclContext *source) { // Collect generic parameters from all outer contexts. SmallVector allGenericParams; - nominal->forEachGenericContext([&](GenericParamList *gpList) { + source->forEachGenericContext([&](GenericParamList *gpList) { allGenericParams.push_back(gpList->clone(ext)); }); @@ -3267,6 +3295,28 @@ createExtensionGenericParams(ASTContext &ctx, return toParams; } +/// If the extended type is a generic typealias whose underlying type is +/// a tuple, the extension inherits the generic paramter list from the +/// typealias. +static GenericParamList * +createTupleExtensionGenericParams(ASTContext &ctx, + ExtensionDecl *ext, + TypeRepr *extendedTypeRepr) { + DirectlyReferencedTypeDecls referenced = + directReferencesForTypeRepr(ctx.evaluator, ctx, + extendedTypeRepr, + ext->getParent()); + + if (referenced.size() != 1 || !isa(referenced[0])) + return nullptr; + + auto *typeAlias = cast(referenced[0]); + if (!typeAlias->isGeneric()) + return nullptr; + + return createExtensionGenericParams(ctx, ext, typeAlias); +} + CollectedOpaqueReprs swift::collectOpaqueTypeReprs(TypeRepr *r, ASTContext &ctx, DeclContext *d) { class Walker : public ASTWalker { @@ -3388,9 +3438,9 @@ GenericParamListRequest::evaluate(Evaluator &evaluator, GenericContext *value) c if (auto *tupleDecl = dyn_cast(value)) { auto &ctx = value->getASTContext(); - // Builtin.TheTupleType has a single pack generic parameter: + // Builtin.TheTupleType has a single pack generic parameter: auto *genericParam = GenericTypeParamDecl::createImplicit( - tupleDecl->getDeclContext(), ctx.Id_Elements, /*depth*/ 0, /*index*/ 0, + tupleDecl->getDeclContext(), ctx.Id_Element, /*depth*/ 0, /*index*/ 0, /*isParameterPack*/ true); return GenericParamList::create(ctx, SourceLoc(), genericParam, @@ -3405,6 +3455,21 @@ GenericParamListRequest::evaluate(Evaluator &evaluator, GenericContext *value) c if (!nominal) { return nullptr; } + + // For a tuple extension, the generic parameter list comes from the + // extended type alias. + if (isa(nominal)) { + if (auto *extendedTypeRepr = ext->getExtendedTypeRepr()) { + auto *genericParams = createTupleExtensionGenericParams( + ctx, ext, extendedTypeRepr); + if (genericParams) + return genericParams; + + // Otherwise, just clone the generic parameter list of the + // Builtin.TheTupleType. We'll diagnose later. + } + } + auto *genericParams = createExtensionGenericParams(ctx, ext, nominal); // Protocol extensions need an inheritance clause due to how name lookup @@ -3518,6 +3583,7 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator, SmallVector modulesFound; bool anyObject = false; auto nominals = resolveTypeDeclsToNominal(evaluator, ctx, decls, + ResolveToNominalOptions(), modulesFound, anyObject); if (nominals.size() == 1 && !isa(nominals.front())) return nominals.front(); @@ -3535,6 +3601,7 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator, identTypeRepr->getNameRef(), identTypeRepr->getLoc(), dc, LookupOuterResults::Included); nominals = resolveTypeDeclsToNominal(evaluator, ctx, decls, + ResolveToNominalOptions(), modulesFound, anyObject); if (nominals.size() == 1 && !isa(nominals.front())) { auto nominal = nominals.front(); @@ -3584,16 +3651,17 @@ void swift::getDirectlyInheritedNominalTypeDecls( // Resolve those type declarations to nominal type declarations. SmallVector modulesFound; auto nominalTypes - = resolveTypeDeclsToNominal(ctx.evaluator, ctx, referenced, modulesFound, - anyObject); + = resolveTypeDeclsToNominal(ctx.evaluator, ctx, referenced, + ResolveToNominalOptions(), + modulesFound, anyObject); // Dig out the source location // FIXME: This is a hack. We need cooperation from // InheritedDeclsReferencedRequest to make this work. SourceLoc loc; SourceLoc uncheckedLoc; - if (TypeRepr *typeRepr = typeDecl ? typeDecl->getInherited()[i].getTypeRepr() - : extDecl->getInherited()[i].getTypeRepr()){ + auto inheritedTypes = InheritedTypes(decl); + if (TypeRepr *typeRepr = inheritedTypes.getTypeRepr(i)) { loc = typeRepr->getLoc(); uncheckedLoc = typeRepr->findUncheckedAttrLoc(); } @@ -3608,17 +3676,15 @@ SmallVector swift::getDirectlyInheritedNominalTypeDecls( llvm::PointerUnion decl, bool &anyObject) { - auto typeDecl = decl.dyn_cast(); - auto extDecl = decl.dyn_cast(); + auto inheritedTypes = InheritedTypes(decl); // Gather results from all of the inherited types. - unsigned numInherited = typeDecl ? typeDecl->getInherited().size() - : extDecl->getInherited().size(); SmallVector result; - for (unsigned i : range(numInherited)) { + for (unsigned i : inheritedTypes.getIndices()) { getDirectlyInheritedNominalTypeDecls(decl, i, result, anyObject); } + auto *typeDecl = decl.dyn_cast(); auto *protoDecl = dyn_cast_or_null(typeDecl); if (protoDecl == nullptr) return result; @@ -3772,8 +3838,9 @@ ProtocolDecl *ImplementsAttrProtocolRequest::evaluate( SmallVector modulesFound; bool anyObject = false; auto nominalTypes - = resolveTypeDeclsToNominal(evaluator, ctx, referenced, modulesFound, - anyObject); + = resolveTypeDeclsToNominal(evaluator, ctx, referenced, + ResolveToNominalOptions(), + modulesFound, anyObject); if (nominalTypes.empty()) return nullptr; diff --git a/lib/AST/NameLookupRequests.cpp b/lib/AST/NameLookupRequests.cpp index 06b3408f3d461..a5851b03b39b1 100644 --- a/lib/AST/NameLookupRequests.cpp +++ b/lib/AST/NameLookupRequests.cpp @@ -40,9 +40,8 @@ namespace swift { SourceLoc InheritedDeclsReferencedRequest::getNearestLoc() const { const auto &storage = getStorage(); - auto &typeLoc = getInheritedTypeLocAtIndex(std::get<0>(storage), - std::get<1>(storage)); - return typeLoc.getLoc(); + auto inheritedTypes = InheritedTypes(std::get<0>(storage)); + return inheritedTypes.getEntry(std::get<1>(storage)).getLoc(); } //----------------------------------------------------------------------------// diff --git a/lib/AST/RequirementMachine/RequirementLowering.cpp b/lib/AST/RequirementMachine/RequirementLowering.cpp index d383d076f9cde..96a769e67b98a 100644 --- a/lib/AST/RequirementMachine/RequirementLowering.cpp +++ b/lib/AST/RequirementMachine/RequirementLowering.cpp @@ -729,17 +729,14 @@ void swift::rewriting::realizeInheritedRequirements( TypeDecl *decl, Type type, bool shouldInferRequirements, SmallVectorImpl &result, SmallVectorImpl &errors) { - auto &ctx = decl->getASTContext(); auto inheritedTypes = decl->getInherited(); auto *dc = decl->getInnermostDeclContext(); auto *moduleForInference = dc->getParentModule(); - for (unsigned index : indices(inheritedTypes)) { - Type inheritedType - = evaluateOrDefault(ctx.evaluator, - InheritedTypeRequest{decl, index, - TypeResolutionStage::Structural}, - Type()); + for (auto index : inheritedTypes.getIndices()) { + Type inheritedType = + inheritedTypes.getResolvedType(index, TypeResolutionStage::Structural); + if (!inheritedType) continue; // Ignore trivially circular protocol refinement (protocol P : P) @@ -750,7 +747,7 @@ void swift::rewriting::realizeInheritedRequirements( continue; } - auto *typeRepr = inheritedTypes[index].getTypeRepr(); + auto *typeRepr = inheritedTypes.getTypeRepr(index); SourceLoc loc = (typeRepr ? typeRepr->getStartLoc() : SourceLoc()); if (shouldInferRequirements) { inferRequirements(inheritedType, loc, moduleForInference, @@ -959,7 +956,7 @@ TypeAliasRequirementsRequest::evaluate(Evaluator &evaluator, return { ", ", trailing->getRequirements().back().getSourceRange().End }; // Inheritance clause. - return { " where ", proto->getInherited().back().getSourceRange().End }; + return { " where ", proto->getInherited().getEndLoc() }; }; // Retrieve the set of requirements that a given associated type declaration @@ -970,15 +967,16 @@ TypeAliasRequirementsRequest::evaluate(Evaluator &evaluator, { llvm::raw_string_ostream out(result); out << start; - interleave(assocType->getInherited(), [&](TypeLoc inheritedType) { - out << assocType->getName() << ": "; - if (auto inheritedTypeRepr = inheritedType.getTypeRepr()) - inheritedTypeRepr->print(out); - else - inheritedType.getType().print(out); - }, [&] { - out << ", "; - }); + llvm::interleave( + assocType->getInherited().getEntries(), + [&](TypeLoc inheritedType) { + out << assocType->getName() << ": "; + if (auto inheritedTypeRepr = inheritedType.getTypeRepr()) + inheritedTypeRepr->print(out); + else + inheritedType.getType().print(out); + }, + [&] { out << ", "; }); if (const auto whereClause = assocType->getTrailingWhereClause()) { if (!assocType->getInherited().empty()) diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index e2108c072879b..cc44b632404a5 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -103,11 +103,14 @@ void swift::simple_display(llvm::raw_ostream &out, const TypeLoc source) { // Inherited type computation. //----------------------------------------------------------------------------// -SourceLoc InheritedTypeRequest::getNearestLoc() const { +const TypeLoc &InheritedTypeRequest::getTypeLoc() const { const auto &storage = getStorage(); - auto &typeLoc = getInheritedTypeLocAtIndex(std::get<0>(storage), - std::get<1>(storage)); - return typeLoc.getLoc(); + auto inheritedTypes = InheritedTypes(std::get<0>(storage)); + return inheritedTypes.getEntry(std::get<1>(storage)); +} + +SourceLoc InheritedTypeRequest::getNearestLoc() const { + return getTypeLoc().getLoc(); } bool InheritedTypeRequest::isCached() const { @@ -115,9 +118,7 @@ bool InheritedTypeRequest::isCached() const { } llvm::Optional InheritedTypeRequest::getCachedResult() const { - const auto &storage = getStorage(); - auto &typeLoc = getInheritedTypeLocAtIndex(std::get<0>(storage), - std::get<1>(storage)); + auto &typeLoc = getTypeLoc(); if (typeLoc.wasValidated()) return typeLoc.getType(); @@ -125,10 +126,7 @@ llvm::Optional InheritedTypeRequest::getCachedResult() const { } void InheritedTypeRequest::cacheResult(Type value) const { - const auto &storage = getStorage(); - auto &typeLoc = getInheritedTypeLocAtIndex(std::get<0>(storage), - std::get<1>(storage)); - const_cast(typeLoc).setType(value); + const_cast(getTypeLoc()).setType(value); } //----------------------------------------------------------------------------// diff --git a/lib/AST/USRGeneration.cpp b/lib/AST/USRGeneration.cpp index 3fd7b573a22f7..23811cb9b8c87 100644 --- a/lib/AST/USRGeneration.cpp +++ b/lib/AST/USRGeneration.cpp @@ -343,7 +343,7 @@ bool ide::printExtensionUSR(const ExtensionDecl *ED, raw_ostream &OS) { } OS << getUSRSpacePrefix() << "e:"; printValueDeclUSR(nominal, OS); - for (auto Inherit : ED->getInherited()) { + for (auto Inherit : ED->getInherited().getEntries()) { if (auto T = Inherit.getType()) { if (T->getAnyNominal()) return printValueDeclUSR(T->getAnyNominal(), OS); diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index e76023e5c3311..8853e61dae54b 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -46,6 +46,12 @@ if (SWIFT_SWIFT_PARSER) "${CMAKE_SHARED_LIBRARY_SUFFIX}" OUTPUT_VARIABLE SWIFT_SYNTAX_SHARED_LIBRARIES) + list(TRANSFORM SWIFT_SYNTAX_MODULES PREPEND "${CMAKE_IMPORT_LIBRARY_PREFIX}" + OUTPUT_VARIABLE SWIFT_SYNTAX_IMPORT_LIBRARIES) + list(TRANSFORM SWIFT_SYNTAX_IMPORT_LIBRARIES APPEND + "${CMAKE_IMPORT_LIBRARY_SUFFIX}" OUTPUT_VARIABLE + SWIFT_SYNTAX_IMPORT_LIBRARIES) + # Interface library to collect swiftinterfaces and swiftmodules from # SwiftSyntax add_library(swiftSyntaxLibraries INTERFACE) @@ -64,27 +70,47 @@ if (SWIFT_SWIFT_PARSER) ) endif() - add_custom_command( - OUTPUT "${SWIFT_HOST_LIBRARIES_DEST_DIR}/${sharedlib}" - DEPENDS "${SWIFT_SYNTAX_LIBRARIES_BUILD_DIR}/${sharedlib}" - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SWIFT_SYNTAX_LIBRARIES_BUILD_DIR}/${sharedlib} ${SWIFT_HOST_LIBRARIES_DEST_DIR}/${sharedlib} - ${add_origin_rpath} - ) - - add_custom_target(copy_swiftSyntaxLibrary_${sharedlib} - DEPENDS "${SWIFT_HOST_LIBRARIES_DEST_DIR}/${sharedlib}" - COMMENT "Copying ${sharedlib}" - ) - - swift_install_in_component( - PROGRAMS "${SWIFT_HOST_LIBRARIES_DEST_DIR}/${sharedlib}" - DESTINATION "lib${LLVM_LIBDIR_SUFFIX}/swift/host" - COMPONENT compiler - ) + if(CMAKE_SYSTEM_NAME MATCHES Windows) + add_custom_command(OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${sharedlib} + DEPENDS "${SWIFT_PATH_TO_EARLYSWIFTSYNTAX_BUILD_DIR}/bin/${sharedlib}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SWIFT_PATH_TO_EARLYSWIFTSYNTAX_BUILD_DIR}/bin/${sharedlib} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${sharedlib}) + add_custom_target(copy_swiftSyntaxLibrary_${sharedlib} + DEPENDS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${sharedlib} + COMMENT "copying ${sharedlib}") + swift_install_in_component(PROGRAMS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${sharedlib} + DESTINATION bin + COMPONENT compiler) + else() + add_custom_command(OUTPUT "${SWIFT_HOST_LIBRARIES_DEST_DIR}/${sharedlib}" + DEPENDS "${SWIFT_SYNTAX_LIBRARIES_BUILD_DIR}/${sharedlib}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SWIFT_SYNTAX_LIBRARIES_BUILD_DIR}/${sharedlib} ${SWIFT_HOST_LIBRARIES_DEST_DIR}/${sharedlib} + ${add_origin_rpath}) + add_custom_target(copy_swiftSyntaxLibrary_${sharedlib} + DEPENDS "${SWIFT_HOST_LIBRARIES_DEST_DIR}/${sharedlib}" + COMMENT "Copying ${sharedlib}") + swift_install_in_component(PROGRAMS "${SWIFT_HOST_LIBRARIES_DEST_DIR}/${sharedlib}" + DESTINATION "lib${LLVM_LIBDIR_SUFFIX}/swift/host" + COMPONENT compiler) + endif() add_dependencies(swiftSyntaxLibraries copy_swiftSyntaxLibrary_${sharedlib}) endforeach() + if(CMAKE_SYSTEM_NAME MATCHES Windows) + foreach(implib ${SWIFT_SYNTAX_IMPORT_LIBRARIES}) + add_custom_command(OUTPUT ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib/swift/windows/${implib} + DEPENDS ${SWIFT_PATH_TO_EARLYSWIFTSYNTAX_BUILD_DIR}/lib/swift/host/${implib} + COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${SWIFT_PATH_TO_EARLYSWIFTSYNTAX_BUILD_DIR}/lib/swift/host/${implib} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib/swift/windows/${implib}) + add_custom_target(copy_swiftSyntaxLibrary_${implib} + DEPENDS ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib/swift/windows/${implib} + COMMENT "Copying ${implib}") + swift_install_in_component(PROGRAMS ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib/swift/windows/${implib} + DESTINATION lib + COMPONENT compiler) + add_dependencies(swiftSyntaxLibraries copy_swiftSyntaxLibrary_${implib}) + endforeach() + endif() + # Copy all of the Swift modules from earlyswiftsyntax so they can be found # in the same relative place within the build directory as in the final # toolchain. diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 909024909a1c1..f3b045539f579 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -8621,7 +8621,7 @@ GenericSignature ClangImporter::Implementation::buildGenericSignature( SmallVector requirements; for (auto param : *genericParams) { Type paramType = param->getDeclaredInterfaceType(); - for (const auto &inherited : param->getInherited()) { + for (const auto &inherited : param->getInherited().getEntries()) { Type inheritedType = inherited.getType(); if (inheritedType->isAnyObject()) { requirements.push_back( diff --git a/lib/Frontend/CachingUtils.cpp b/lib/Frontend/CachingUtils.cpp index 660df18bc1592..40e33c1595efc 100644 --- a/lib/Frontend/CachingUtils.cpp +++ b/lib/Frontend/CachingUtils.cpp @@ -15,6 +15,7 @@ #include "swift/AST/DiagnosticsFrontend.h" #include "swift/Basic/FileTypes.h" #include "swift/Frontend/CompileJobCacheKey.h" +#include "clang/CAS/CASOptions.h" #include "clang/CAS/IncludeTree.h" #include "clang/Frontend/CompileJobCacheResult.h" #include "llvm/ADT/STLExtras.h" @@ -422,51 +423,4 @@ createCASFileSystem(ObjectStore &CAS, ArrayRef FSRoots, return CASFS; } -namespace cas { - -CachingTool::CachingTool(StringRef Path) { - auto DB = llvm::cas::createOnDiskUnifiedCASDatabases(Path); - if (!DB) { - llvm::errs() << "Failed to create CAS at " << Path << ": " - << toString(DB.takeError()) << "\n"; - return; - } - - CAS = std::move(DB->first); - Cache = std::move(DB->second); -} - -std::string CachingTool::computeCacheKey(ArrayRef Args, - StringRef InputPath, - file_types::ID OutputKind) { - auto BaseKey = createCompileJobBaseCacheKey(*CAS, Args); - if (!BaseKey) { - llvm::errs() << "Failed to create cache key: " - << toString(BaseKey.takeError()) << "\n"; - return ""; - } - - auto Key = - createCompileJobCacheKeyForOutput(*CAS, *BaseKey, InputPath, OutputKind); - if (!Key) { - llvm::errs() << "Failed to create cache key: " << toString(Key.takeError()) - << "\n"; - return ""; - } - - return CAS->getID(*Key).toString(); -} - -std::string CachingTool::storeContent(StringRef Content) { - auto Result = CAS->storeFromString({}, Content); - if (!Result) { - llvm::errs() << "Failed to store to CAS: " << toString(Result.takeError()) - << "\n"; - return ""; - } - - return CAS->getID(*Result).toString(); -} - -} // namespace cas } // namespace swift diff --git a/lib/Frontend/CompileJobCacheKey.cpp b/lib/Frontend/CompileJobCacheKey.cpp index a143acd71405e..06b94d82bf789 100644 --- a/lib/Frontend/CompileJobCacheKey.cpp +++ b/lib/Frontend/CompileJobCacheKey.cpp @@ -14,12 +14,15 @@ // //===----------------------------------------------------------------------===// +#include "swift/Option/Options.h" #include #include #include #include "llvm/ADT/STLExtras.h" #include "llvm/CAS/HierarchicalTreeBuilder.h" #include "llvm/CAS/ObjectStore.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/OptTable.h" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" @@ -28,52 +31,37 @@ using namespace swift; // TODO: Rewrite this into CASNodeSchema. llvm::Expected swift::createCompileJobBaseCacheKey( llvm::cas::ObjectStore &CAS, ArrayRef Args) { - SmallString<256> CommandLine; - - // TODO: Improve this list. - static const std::vector removeArgAndNext = { - "-o", - "-output-filelist", - "-supplementary-output-file-map", - "-index-unit-output-path", - "-index-unit-output-path-filelist", - "-serialize-diagnostics-path", - "-num-threads", - "-cas-path"}; - // Don't count the `-frontend` in the first location since only frontend // invocation can have a cache key. if (Args.size() > 1 && StringRef(Args.front()) == "-frontend") Args = Args.drop_front(); - for (unsigned I = 0, IE =Args.size(); I < IE; ++I) { - StringRef Arg = Args[I]; - if (llvm::is_contained(removeArgAndNext, Arg)) { - ++I; - continue; - } - // FIXME: Use a heuristic to remove all the flags that affect output paths. - // Those should not affect compile cache key. - if (Arg.startswith("-emit-")) { - if (Arg.endswith("-path")) - ++I; + unsigned MissingIndex; + unsigned MissingCount; + std::unique_ptr Table = createSwiftOptTable(); + llvm::opt::InputArgList ParsedArgs = Table->ParseArgs( + Args, MissingIndex, MissingCount, options::FrontendOption); + + SmallString<256> CommandLine; + for (auto *Arg : ParsedArgs) { + const auto &Opt = Arg->getOption(); + + // Skip the options that doesn't affect caching. + if (Opt.hasFlag(options::CacheInvariant)) continue; - } - // Handle -file-list option. Need to drop the option but adds the file - // content instead. - // FIXME: will be nice if the same list of files gets the same key no matter - // going through command-line or filelist. - if (Arg == "-filelist" || Arg == "-primary-filelist") { - auto FileList = llvm::MemoryBuffer::getFile(Args[++I]); + + if (Opt.hasFlag(options::ArgumentIsFileList)) { + auto FileList = llvm::MemoryBuffer::getFile(Arg->getValue()); if (!FileList) return llvm::errorCodeToError(FileList.getError()); - CommandLine.append(Arg); + CommandLine.append(Opt.getRenderName()); CommandLine.push_back(0); CommandLine.append((*FileList)->getBuffer()); CommandLine.push_back(0); continue; } - CommandLine.append(Arg); + + CommandLine.append(Arg->getAsString(ParsedArgs)); CommandLine.push_back(0); } diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index c64e0292aed6f..f06fa46122eb2 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1316,6 +1316,11 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, } Opts.BypassResilienceChecks |= Args.hasArg(OPT_bypass_resilience); + if (FrontendOpts.EnableLibraryEvolution && Opts.hasFeature(Feature::Embedded)) { + Diags.diagnose(SourceLoc(), diag::evolution_with_embedded); + HadError = true; + } + return HadError || UnsupportedOS || UnsupportedArch; } diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index c543af3c96293..8eb743b2acc3b 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -223,6 +223,9 @@ SerializationOptions CompilerInvocation::computeSerializationOptions( serializationOpts.HermeticSealAtLink = opts.HermeticSealAtLink; + serializationOpts.EmbeddedSwiftModule = + LangOpts.hasFeature(Feature::Embedded); + serializationOpts.IsOSSA = getSILOptions().EnableOSSAModules; serializationOpts.SerializeExternalDeclsOnly = diff --git a/lib/Frontend/ModuleInterfaceSupport.cpp b/lib/Frontend/ModuleInterfaceSupport.cpp index 7287deb0ff022..e3fc0c8078833 100644 --- a/lib/Frontend/ModuleInterfaceSupport.cpp +++ b/lib/Frontend/ModuleInterfaceSupport.cpp @@ -479,11 +479,11 @@ class InheritedProtocolCollector { /// If \p skipExtra is true then avoid recording any extra protocols to /// print, such as synthesized conformances or conformances to non-public /// protocols. - void recordProtocols(ArrayRef directlyInherited, - const Decl *D, bool skipExtra = false) { + void recordProtocols(InheritedTypes directlyInherited, const Decl *D, + bool skipExtra = false) { llvm::Optional availableAttrs; - for (InheritedEntry inherited : directlyInherited) { + for (InheritedEntry inherited : directlyInherited.getEntries()) { Type inheritedTy = inherited.getType(); if (!inheritedTy || !inheritedTy->isExistentialType()) continue; @@ -526,7 +526,7 @@ class InheritedProtocolCollector { /// For each type directly inherited by \p extension, record any protocols /// that we would have printed in ConditionalConformanceProtocols. void recordConditionalConformances(const ExtensionDecl *extension) { - for (TypeLoc inherited : extension->getInherited()) { + for (TypeLoc inherited : extension->getInherited().getEntries()) { Type inheritedTy = inherited.getType(); if (!inheritedTy || !inheritedTy->isExistentialType()) continue; @@ -551,7 +551,7 @@ class InheritedProtocolCollector { /// /// \sa recordProtocols static void collectProtocols(PerTypeMap &map, const Decl *D) { - ArrayRef directlyInherited; + InheritedTypes directlyInherited = InheritedTypes(D); const NominalTypeDecl *nominal; const IterableDeclContext *memberContext; @@ -565,7 +565,6 @@ class InheritedProtocolCollector { return true; }; if ((nominal = dyn_cast(D))) { - directlyInherited = nominal->getInherited(); memberContext = nominal; } else if (auto *extension = dyn_cast(D)) { @@ -573,7 +572,6 @@ class InheritedProtocolCollector { return; } nominal = extension->getExtendedNominal(); - directlyInherited = extension->getInherited(); memberContext = extension; } else { return; diff --git a/lib/Frontend/PrintingDiagnosticConsumer.cpp b/lib/Frontend/PrintingDiagnosticConsumer.cpp index 846321335d431..9f6a8976c3aef 100644 --- a/lib/Frontend/PrintingDiagnosticConsumer.cpp +++ b/lib/Frontend/PrintingDiagnosticConsumer.cpp @@ -458,16 +458,10 @@ void PrintingDiagnosticConsumer::handleDiagnostic(SourceManager &SM, // Use the swift-syntax formatter. auto bufferStack = getSourceBufferStack(SM, Info.Loc); if (!bufferStack.empty()) { - // If there are no enqueued diagnostics, they are from a different - // outermost buffer, or we have hit a non-note diagnostic, flush any - // enqueued diagnostics and start fresh. - unsigned outermostBufferID = bufferStack.back(); - if (!queuedDiagnostics || - outermostBufferID != queuedDiagnosticsOutermostBufferID || - Info.Kind != DiagnosticKind::Note) { + // If there are no enqueued diagnostics, or we have hit a non-note + // diagnostic, flush any enqueued diagnostics and start fresh. + if (!queuedDiagnostics || Info.Kind != DiagnosticKind::Note) { flush(/*includeTrailingBreak*/ true); - - queuedDiagnosticsOutermostBufferID = outermostBufferID; queuedDiagnostics = swift_ASTGen_createQueuedDiagnostics(); } diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 9a0d9a3ad5179..76f697a75dcc6 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -1557,6 +1557,11 @@ static bool validateTBDIfNeeded(const CompilerInvocation &Invocation, return false; } + // Embedded Swift does not support TBD. + if (Invocation.getLangOptions().hasFeature(Feature::Embedded)) { + return false; + } + // Cross-module optimization does not support TBD. if (Invocation.getSILOptions().CMOMode == CrossModuleOptimizationMode::Aggressive) { return false; diff --git a/lib/IDE/AfterPoundExprCompletion.cpp b/lib/IDE/AfterPoundExprCompletion.cpp index 41ae1772b1201..3150752139d81 100644 --- a/lib/IDE/AfterPoundExprCompletion.cpp +++ b/lib/IDE/AfterPoundExprCompletion.cpp @@ -37,15 +37,18 @@ void AfterPoundExprCompletion::sawSolutionImpl(const constraints::Solution &S) { } } -void AfterPoundExprCompletion::deliverResults( - ide::CodeCompletionContext &CompletionCtx, - CodeCompletionConsumer &Consumer) { +void AfterPoundExprCompletion::collectResults( + ide::CodeCompletionContext &CompletionCtx) { ASTContext &Ctx = DC->getASTContext(); CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC, &CompletionCtx); Lookup.shouldCheckForDuplicates(Results.size() > 1); + // The type context that is being used for global results. + ExpectedTypeContext UnifiedTypeContext; + UnifiedTypeContext.setPreferNonVoid(true); + for (auto &Result : Results) { Lookup.setExpectedTypes({Result.ExpectedTy}, Result.IsImplicitSingleExpressionReturn, @@ -53,7 +56,10 @@ void AfterPoundExprCompletion::deliverResults( Lookup.addPoundAvailable(ParentStmtKind); Lookup.addObjCPoundKeywordCompletions(/*needPound=*/false); Lookup.getMacroCompletions(CodeCompletionMacroRole::Expression); + + UnifiedTypeContext.merge(*Lookup.getExpectedTypeContext()); } - deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer); + collectCompletionResults(CompletionCtx, Lookup, DC, UnifiedTypeContext, + /*CanCurrDeclContextHandleAsync=*/false); } diff --git a/lib/IDE/ArgumentCompletion.cpp b/lib/IDE/ArgumentCompletion.cpp index e0c7169bdbbe5..095e3e8fab73d 100644 --- a/lib/IDE/ArgumentCompletion.cpp +++ b/lib/IDE/ArgumentCompletion.cpp @@ -50,6 +50,24 @@ bool ArgumentTypeCheckCompletionCallback::addPossibleParams( const AnyFunctionType::Param *TypeParam = &ParamsToPass[Idx]; bool Required = !Res.DeclParamIsOptional[Idx]; + if (Res.FirstTrailingClosureIndex && Idx > *Res.FirstTrailingClosureIndex && + !TypeParam->getPlainType() + ->lookThroughAllOptionalTypes() + ->is()) { + // We are completing an argument after the first trailing closure, i.e. + // a multitple trailing closure label but the parameter is not a function + // type. Since we only allow labeled trailing closures after the first + // trailing closure, we cannot pass an argument for this parameter. + // If the parameter is required, stop here since we cannot pass an argument + // for the parameter. If it's optional, keep looking for more trailing + // closures that can be passed. + if (Required) { + break; + } else { + continue; + } + } + if (TypeParam->hasLabel() && !(IsCompletion && Res.IsNoninitialVariadic)) { // Suggest parameter label if parameter has label, we are completing in it // and it is not a variadic parameter that already has arguments @@ -198,9 +216,11 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) { } bool HasLabel = false; + llvm::Optional FirstTrailingClosureIndex = llvm::None; if (auto PE = CS.getParentExpr(CompletionExpr)) { if (auto Args = PE->getArgs()) { HasLabel = !Args->getLabel(ArgIdx).empty(); + FirstTrailingClosureIndex = Args->getFirstTrailingClosureIndex(); } } @@ -258,11 +278,11 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) { } } - Results.push_back({ExpectedTy, ExpectedCallType, - isa(ParentCall), Info.getValue(), FuncTy, - ArgIdx, ParamIdx, std::move(ClaimedParams), - IsNoninitialVariadic, Info.BaseTy, HasLabel, IsAsync, - DeclParamIsOptional, SolutionSpecificVarTypes}); + Results.push_back( + {ExpectedTy, ExpectedCallType, isa(ParentCall), + Info.getValue(), FuncTy, ArgIdx, ParamIdx, std::move(ClaimedParams), + IsNoninitialVariadic, Info.BaseTy, HasLabel, FirstTrailingClosureIndex, + IsAsync, DeclParamIsOptional, SolutionSpecificVarTypes}); } void ArgumentTypeCheckCompletionCallback::computeShadowedDecls( @@ -295,10 +315,9 @@ void ArgumentTypeCheckCompletionCallback::computeShadowedDecls( } } -void ArgumentTypeCheckCompletionCallback::deliverResults( - bool IncludeSignature, SourceLoc Loc, DeclContext *DC, - ide::CodeCompletionContext &CompletionCtx, - CodeCompletionConsumer &Consumer) { +void ArgumentTypeCheckCompletionCallback::collectResults( + bool IncludeSignature, bool IsLabeledTrailingClosure, SourceLoc Loc, + DeclContext *DC, ide::CodeCompletionContext &CompletionCtx) { ASTContext &Ctx = DC->getASTContext(); CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC, &CompletionCtx); @@ -375,7 +394,7 @@ void ArgumentTypeCheckCompletionCallback::deliverResults( shouldPerformGlobalCompletion |= addPossibleParams(Ret, Params, ExpectedTypes); } - Lookup.addCallArgumentCompletionResults(Params); + Lookup.addCallArgumentCompletionResults(Params, IsLabeledTrailingClosure); } if (shouldPerformGlobalCompletion) { @@ -402,5 +421,7 @@ void ArgumentTypeCheckCompletionCallback::deliverResults( addExprKeywords(CompletionCtx.getResultSink(), DC); } - deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer); + collectCompletionResults(CompletionCtx, Lookup, DC, + *Lookup.getExpectedTypeContext(), + Lookup.canCurrDeclContextHandleAsync()); } diff --git a/lib/IDE/CMakeLists.txt b/lib/IDE/CMakeLists.txt index b48e3346a43ad..efdc50aaff361 100644 --- a/lib/IDE/CMakeLists.txt +++ b/lib/IDE/CMakeLists.txt @@ -5,7 +5,6 @@ add_swift_host_library(swiftIDE STATIC ArgumentCompletion.cpp CodeCompletion.cpp CodeCompletionCache.cpp - CodeCompletionConsumer.cpp CodeCompletionContext.cpp CodeCompletionDiagnostics.cpp CodeCompletionResult.cpp diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index f6fcf501f3b3b..362d0619152da 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -133,7 +133,6 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks, bool ShouldCompleteCallPatternAfterParen = true; bool PreferFunctionReferencesToCalls = false; bool AttTargetIsIndependent = false; - bool IsAtStartOfLine = false; llvm::Optional AttTargetDK; llvm::Optional ParentStmtKind; @@ -285,8 +284,6 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks, void completeUnresolvedMember(CodeCompletionExpr *E, SourceLoc DotLoc) override; void completeCallArg(CodeCompletionExpr *E, bool isFirst) override; - void completeLabeledTrailingClosure(CodeCompletionExpr *E, - bool isAtStartOfLine) override; bool canPerformCompleteLabeledTrailingClosure() const override { return true; @@ -578,14 +575,6 @@ void CodeCompletionCallbacksImpl::completeCallArg(CodeCompletionExpr *E, } } -void CodeCompletionCallbacksImpl::completeLabeledTrailingClosure( - CodeCompletionExpr *E, bool isAtStartOfLine) { - CurDeclContext = P.CurDeclContext; - CodeCompleteTokenExpr = E; - Kind = CompletionKind::LabeledTrailingClosure; - IsAtStartOfLine = isAtStartOfLine; -} - void CodeCompletionCallbacksImpl::completeReturnStmt(CodeCompletionExpr *E) { CurDeclContext = P.CurDeclContext; CodeCompleteTokenExpr = E; @@ -1004,7 +993,6 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink, case CompletionKind::PoundAvailablePlatform: case CompletionKind::Import: case CompletionKind::UnresolvedMember: - case CompletionKind::LabeledTrailingClosure: case CompletionKind::AfterPoundExpr: case CompletionKind::AfterPoundDirective: case CompletionKind::PlatformConditon: @@ -1332,9 +1320,10 @@ void swift::ide::postProcessCompletionResults( } } -void swift::ide::deliverCompletionResults( +void swift::ide::collectCompletionResults( CodeCompletionContext &CompletionContext, CompletionLookup &Lookup, - DeclContext *DC, CodeCompletionConsumer &Consumer) { + DeclContext *DC, const ExpectedTypeContext &TypeContext, + bool CanCurrDeclContextHandleAsync) { auto &SF = *DC->getParentSourceFile(); llvm::SmallPtrSet seenModuleNames; std::vector RequestedModules; @@ -1454,9 +1443,8 @@ void swift::ide::deliverCompletionResults( CompletionContext.CodeCompletionKind, DC, /*Sink=*/nullptr); - Consumer.handleResultsAndModules(CompletionContext, RequestedModules, - Lookup.getExpectedTypeContext(), DC, - Lookup.canCurrDeclContextHandleAsync()); + CompletionContext.addResultsFromModules(RequestedModules, TypeContext, DC, + CanCurrDeclContextHandleAsync); } bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) { @@ -1523,8 +1511,46 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) { bool IncludeOperators = (Kind == CompletionKind::PostfixExpr); - Lookup.deliverResults(DotLoc, isInsideObjCSelector(), IncludeOperators, - HasSpace, CompletionContext, Consumer); + Lookup.collectResults(DotLoc, isInsideObjCSelector(), IncludeOperators, + HasSpace, CompletionContext); + + // Check if we are completing after a call that already has a trailing + // closure. In that case, also suggest labels for additional trailing + // closures. + if (auto AE = dyn_cast(ParsedExpr)) { + if (AE->getArgs()->hasAnyTrailingClosures()) { + ASTContext &Ctx = CurDeclContext->getASTContext(); + + // Modify the call that has the code completion expression as an + // additional argument, restore the original arguments afterwards. + auto OriginalArgs = AE->getArgs(); + llvm::SmallVector ArgsWithCC(OriginalArgs->begin(), + OriginalArgs->end()); + auto CC = new (Ctx) CodeCompletionExpr(CodeCompleteTokenExpr->getLoc()); + ArgsWithCC.emplace_back(SourceLoc(), Identifier(), CC); + auto ArgList = + ArgumentList::create(Ctx, OriginalArgs->getLParenLoc(), ArgsWithCC, + OriginalArgs->getRParenLoc(), + OriginalArgs->getFirstTrailingClosureIndex(), + OriginalArgs->isImplicit()); + AE->setArgs(ArgList); + SWIFT_DEFER { AE->setArgs(OriginalArgs); }; + + // Perform argument label completions on the newly created call. + ArgumentTypeCheckCompletionCallback Lookup(CC, CurDeclContext); + + llvm::SaveAndRestore CompletionCollector( + Context.CompletionCallback, &Lookup); + typeCheckContextAt( + TypeCheckASTNodeAtLocContext::node(CurDeclContext, AE), + CompletionLoc); + Lookup.collectResults(/*IncludeSignature=*/false, + /*IsLabeledTrailingClosure=*/true, CompletionLoc, + CurDeclContext, CompletionContext); + } + } + + Consumer.handleResults(CompletionContext); return true; } case CompletionKind::UnresolvedMember: { @@ -1536,7 +1562,8 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) { typeCheckWithLookup(Lookup); addKeywords(CompletionContext.getResultSink(), MaybeFuncBody); - Lookup.deliverResults(CurDeclContext, DotLoc, CompletionContext, Consumer); + Lookup.collectResults(CurDeclContext, DotLoc, CompletionContext); + Consumer.handleResults(CompletionContext); return true; } case CompletionKind::KeyPathExprSwift: { @@ -1548,7 +1575,8 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) { KeyPathTypeCheckCompletionCallback Lookup(KeyPath); typeCheckWithLookup(Lookup); - Lookup.deliverResults(CurDeclContext, DotLoc, CompletionContext, Consumer); + Lookup.collectResults(CurDeclContext, DotLoc, CompletionContext); + Consumer.handleResults(CompletionContext); return true; } case CompletionKind::PostfixExprParen: @@ -1559,8 +1587,10 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) { CurDeclContext); typeCheckWithLookup(Lookup); - Lookup.deliverResults(ShouldCompleteCallPatternAfterParen, CompletionLoc, - CurDeclContext, CompletionContext, Consumer); + Lookup.collectResults(ShouldCompleteCallPatternAfterParen, + /*IsLabeledTrailingClosure=*/false, CompletionLoc, + CurDeclContext, CompletionContext); + Consumer.handleResults(CompletionContext); return true; } case CompletionKind::AccessorBeginning: @@ -1600,7 +1630,8 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) { addKeywords(CompletionContext.getResultSink(), MaybeFuncBody); SourceLoc CCLoc = P.Context.SourceMgr.getIDEInspectionTargetLoc(); - Lookup.deliverResults(CCLoc, CompletionContext, Consumer); + Lookup.collectResults(CCLoc, CompletionContext); + Consumer.handleResults(CompletionContext); return true; } case CompletionKind::AfterPoundExpr: { @@ -1613,7 +1644,8 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) { addKeywords(CompletionContext.getResultSink(), MaybeFuncBody); - Lookup.deliverResults(CompletionContext, Consumer); + Lookup.collectResults(CompletionContext); + Consumer.handleResults(CompletionContext); return true; } default: @@ -1729,12 +1761,6 @@ void CodeCompletionCallbacksImpl::doneParsing(SourceFile *SrcFile) { if (PreferFunctionReferencesToCalls) Lookup.setPreferFunctionReferencesToCalls(); - auto DoPostfixExprBeginning = [&] (){ - SourceLoc Loc = P.Context.SourceMgr.getIDEInspectionTargetLoc(); - Lookup.getValueCompletionsInDeclContext(Loc); - Lookup.getSelfTypeCompletionInDeclContext(Loc, /*isForDeclResult=*/false); - }; - switch (Kind) { case CompletionKind::None: case CompletionKind::DotExpr: @@ -1889,116 +1915,6 @@ void CodeCompletionCallbacksImpl::doneParsing(SourceFile *SrcFile) { Lookup.addImportModuleNames(); break; } - case CompletionKind::LabeledTrailingClosure: { - ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr); - - SmallVector params; - // Only complete function type parameters - llvm::copy_if(ContextInfo.getPossibleParams(), std::back_inserter(params), - [](const PossibleParamInfo &P) { - // nullptr indicates out of bounds. - if (!P.Param) - return true; - return P.Param->getPlainType() - ->lookThroughAllOptionalTypes() - ->is(); - }); - - bool allRequired = false; - if (!params.empty()) { - Lookup.addCallArgumentCompletionResults( - params, /*isLabeledTrailingClosure=*/true); - allRequired = llvm::all_of( - params, [](const PossibleParamInfo &P) { return P.IsRequired; }); - } - - // If there're optional parameters, do global completion or member - // completion depending on the completion is happening at the start of line. - if (!allRequired) { - if (IsAtStartOfLine) { - // foo() {} - // - - auto &Sink = CompletionContext.getResultSink(); - if (isa(CurDeclContext)) - CurDeclContext = CurDeclContext->getParent(); - - if (CurDeclContext->isTypeContext()) { - // Override completion (CompletionKind::NominalMemberBeginning). - addDeclKeywords(Sink, CurDeclContext, - Context.LangOpts.EnableExperimentalConcurrency); - addLetVarKeywords(Sink); - SmallVector ParsedKeywords; - CompletionOverrideLookup OverrideLookup(Sink, Context, CurDeclContext, - ParsedKeywords, SourceLoc()); - OverrideLookup.getOverrideCompletions(SourceLoc()); - } else { - // Global completion (CompletionKind::PostfixExprBeginning). - addDeclKeywords(Sink, CurDeclContext, - Context.LangOpts.EnableExperimentalConcurrency); - addStmtKeywords(Sink, CurDeclContext, MaybeFuncBody); - addSuperKeyword(Sink, CurDeclContext); - addLetVarKeywords(Sink); - addExprKeywords(Sink, CurDeclContext); - addAnyTypeKeyword(Sink, Context.TheAnyType); - DoPostfixExprBeginning(); - } - } else { - // foo() {} - // Member completion. - Expr *analyzedExpr = ContextInfo.getAnalyzedExpr(); - if (!analyzedExpr) - break; - - // Only if the completion token is the last token in the call. - if (analyzedExpr->getEndLoc() != CodeCompleteTokenExpr->getLoc()) - break; - - Type resultTy = analyzedExpr->getType(); - // If the call expression doesn't have a type, fallback to: - if (!resultTy || resultTy->is()) { - // 1) Try to type check removing CodeCompletionExpr from the call. - Expr *removedExpr = analyzedExpr; - removeCodeCompletionExpr(CurDeclContext->getASTContext(), - removedExpr); - ConcreteDeclRef referencedDecl; - auto optT = getTypeOfCompletionContextExpr( - CurDeclContext->getASTContext(), CurDeclContext, - CompletionTypeCheckKind::Normal, removedExpr, referencedDecl); - if (optT) { - resultTy = *optT; - analyzedExpr->setType(resultTy); - } - } - if (!resultTy || resultTy->is()) { - // 2) Infer it from the possible callee info. - if (!ContextInfo.getPossibleCallees().empty()) { - auto calleeInfo = ContextInfo.getPossibleCallees()[0]; - resultTy = calleeInfo.Type->getResult(); - analyzedExpr->setType(resultTy); - } - } - if (!resultTy || resultTy->is()) { - // 3) Give up providing postfix completions. - break; - } - - auto &SM = CurDeclContext->getASTContext().SourceMgr; - auto leadingChar = SM.extractText( - {SM.getIDEInspectionTargetLoc().getAdvancedLoc(-1), 1}); - Lookup.setHaveLeadingSpace(leadingChar.find_first_of(" \t\f\v") != - StringRef::npos); - - if (isDynamicLookup(resultTy)) - Lookup.setIsDynamicLookup(); - Lookup.getValueExprCompletions(resultTy, /*VD=*/nullptr, - /*IncludeFunctionCallCompletions=*/true); - Lookup.getOperatorCompletions(analyzedExpr, leadingSequenceExprs); - Lookup.getPostfixKeywordCompletions(resultTy, analyzedExpr); - } - } - break; - } case CompletionKind::AfterPoundDirective: { addPoundDirectives(CompletionContext.getResultSink()); @@ -2065,7 +1981,10 @@ void CodeCompletionCallbacksImpl::doneParsing(SourceFile *SrcFile) { break; } - deliverCompletionResults(CompletionContext, Lookup, CurDeclContext, Consumer); + collectCompletionResults(CompletionContext, Lookup, CurDeclContext, + *Lookup.getExpectedTypeContext(), + Lookup.canCurrDeclContextHandleAsync()); + Consumer.handleResults(CompletionContext); } namespace { diff --git a/lib/IDE/CodeCompletionConsumer.cpp b/lib/IDE/CodeCompletionConsumer.cpp deleted file mode 100644 index 1836bcf3705a0..0000000000000 --- a/lib/IDE/CodeCompletionConsumer.cpp +++ /dev/null @@ -1,160 +0,0 @@ -//===--- CodeCompletionConsumer.cpp ---------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2022 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#include "swift/IDE/CodeCompletionConsumer.h" -#include "swift/IDE/CodeCompletionCache.h" - -using namespace swift; -using namespace swift::ide; - -static MutableArrayRef copyCodeCompletionResults( - CodeCompletionResultSink &targetSink, CodeCompletionCache::Value &source, - CodeCompletionFilter filter, const ExpectedTypeContext *TypeContext, - const DeclContext *DC, bool CanCurrDeclContextHandleAsync) { - assert(filter && "Should never have an empty filter"); - - // We will be adding foreign results (from another sink) into TargetSink. - // TargetSink should have an owning pointer to the allocator that keeps the - // results alive. - targetSink.ForeignAllocators.push_back(source.Allocator); - auto startSize = targetSink.Results.size(); - - CodeCompletionMacroRoles expectedMacroRoles = getCompletionMacroRoles(filter); - std::function - shouldIncludeResult = - [filter, expectedMacroRoles]( - const ContextFreeCodeCompletionResult *R) -> bool { - if (R->getKind() != CodeCompletionResultKind::Declaration) - return false; - - switch (R->getAssociatedDeclKind()) { - case CodeCompletionDeclKind::EnumElement: - case CodeCompletionDeclKind::Constructor: - case CodeCompletionDeclKind::Destructor: - case CodeCompletionDeclKind::Subscript: - case CodeCompletionDeclKind::StaticMethod: - case CodeCompletionDeclKind::InstanceMethod: - case CodeCompletionDeclKind::PrefixOperatorFunction: - case CodeCompletionDeclKind::PostfixOperatorFunction: - case CodeCompletionDeclKind::InfixOperatorFunction: - case CodeCompletionDeclKind::FreeFunction: - case CodeCompletionDeclKind::StaticVar: - case CodeCompletionDeclKind::InstanceVar: - case CodeCompletionDeclKind::LocalVar: - case CodeCompletionDeclKind::GlobalVar: - return filter.contains(CodeCompletionFilterFlag::Expr); - - case CodeCompletionDeclKind::Module: - case CodeCompletionDeclKind::Class: - case CodeCompletionDeclKind::Actor: - case CodeCompletionDeclKind::Struct: - case CodeCompletionDeclKind::Enum: - case CodeCompletionDeclKind::Protocol: - case CodeCompletionDeclKind::TypeAlias: - case CodeCompletionDeclKind::AssociatedType: - case CodeCompletionDeclKind::GenericTypeParam: - return filter.contains(CodeCompletionFilterFlag::Type); - - case CodeCompletionDeclKind::PrecedenceGroup: - return filter.contains(CodeCompletionFilterFlag::PrecedenceGroup); - - case CodeCompletionDeclKind::Macro: - return (bool)(R->getMacroRoles() & expectedMacroRoles); - } - - llvm_unreachable("Unhandled associated decl kind"); - }; - - USRBasedTypeContext USRTypeContext(TypeContext, source.USRTypeArena); - - for (auto contextFreeResult : source.Results) { - if (!shouldIncludeResult(contextFreeResult)) { - continue; - } - - CodeCompletionResultTypeRelation typeRelation = - contextFreeResult->calculateContextualTypeRelation(DC, TypeContext, - &USRTypeContext); - ContextualNotRecommendedReason notRecommendedReason = - contextFreeResult->calculateContextualNotRecommendedReason( - ContextualNotRecommendedReason::None, - CanCurrDeclContextHandleAsync); - - auto contextualResult = new (*targetSink.Allocator) CodeCompletionResult( - *contextFreeResult, SemanticContextKind::OtherModule, - CodeCompletionFlair(), - /*numBytesToErase=*/0, typeRelation, notRecommendedReason); - targetSink.Results.push_back(contextualResult); - } - - return llvm::makeMutableArrayRef(targetSink.Results.data() + startSize, - targetSink.Results.size() - startSize); -} - -void SimpleCachingCodeCompletionConsumer::handleResultsAndModules( - CodeCompletionContext &context, - ArrayRef requestedModules, - const ExpectedTypeContext *TypeContext, const DeclContext *DC, - bool CanCurrDeclContextHandleAsync) { - - // Use the current SourceFile as the DeclContext so that we can use it to - // perform qualified lookup, and to get the correct visibility for - // @testable imports. Also it cannot use 'DC' since it would apply decl - // context changes to cached results. - const SourceFile *SF = DC->getParentSourceFile(); - - for (auto &R : requestedModules) { - // FIXME(thread-safety): lock the whole AST context. We might load a - // module. - llvm::Optional V = - context.Cache.get(R.Key); - if (!V.has_value()) { - // No cached results found. Fill the cache. - V = context.Cache.createValue(); - // Temporary sink in which we gather the result. The cache value retains - // the sink's allocator. - CodeCompletionResultSink Sink; - Sink.annotateResult = context.getAnnotateResult(); - Sink.addInitsToTopLevel = context.getAddInitsToTopLevel(); - Sink.enableCallPatternHeuristics = context.getCallPatternHeuristics(); - Sink.includeObjectLiterals = context.includeObjectLiterals(); - Sink.addCallWithNoDefaultArgs = context.addCallWithNoDefaultArgs(); - Sink.setProduceContextFreeResults((*V)->USRTypeArena); - lookupCodeCompletionResultsFromModule(Sink, R.TheModule, R.Key.AccessPath, - R.Key.ResultsHaveLeadingDot, SF); - (*V)->Allocator = Sink.Allocator; - auto &CachedResults = (*V)->Results; - CachedResults.reserve(Sink.Results.size()); - // Instead of copying the context free results out of the sink's allocator - // retain the sink's entire allocator (which also includes the contextual - // properities) and simply store pointers to the context free results that - // back the contextual results. - for (auto Result : Sink.Results) { - assert( - Result->getContextFreeResult().getResultType().isBackedByUSRs() && - "Results stored in the cache should have their result types backed " - "by a USR because the cache might outlive the ASTContext the " - "results were created from."); - CachedResults.push_back(&Result->getContextFreeResult()); - } - context.Cache.set(R.Key, *V); - } - assert(V.has_value()); - auto newItems = copyCodeCompletionResults(context.getResultSink(), **V, - R.Filter, TypeContext, DC, - CanCurrDeclContextHandleAsync); - postProcessCompletionResults(newItems, context.CodeCompletionKind, DC, - &context.getResultSink()); - } - - handleResults(context); -} diff --git a/lib/IDE/CodeCompletionContext.cpp b/lib/IDE/CodeCompletionContext.cpp index 06687dc3bebbd..849d0c45bd2b7 100644 --- a/lib/IDE/CodeCompletionContext.cpp +++ b/lib/IDE/CodeCompletionContext.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "swift/IDE/CodeCompletionContext.h" +#include "swift/IDE/CodeCompletionCache.h" using namespace swift; using namespace swift::ide; @@ -34,3 +35,141 @@ CodeCompletionContext::sortCompletionResults( return SortedResults; } + +static MutableArrayRef copyCodeCompletionResults( + CodeCompletionResultSink &targetSink, CodeCompletionCache::Value &source, + CodeCompletionFilter filter, const ExpectedTypeContext *TypeContext, + const DeclContext *DC, bool CanCurrDeclContextHandleAsync) { + assert(filter && "Should never have an empty filter"); + + // We will be adding foreign results (from another sink) into TargetSink. + // TargetSink should have an owning pointer to the allocator that keeps the + // results alive. + targetSink.ForeignAllocators.push_back(source.Allocator); + auto startSize = targetSink.Results.size(); + + CodeCompletionMacroRoles expectedMacroRoles = getCompletionMacroRoles(filter); + std::function + shouldIncludeResult = + [filter, expectedMacroRoles]( + const ContextFreeCodeCompletionResult *R) -> bool { + if (R->getKind() != CodeCompletionResultKind::Declaration) + return false; + + switch (R->getAssociatedDeclKind()) { + case CodeCompletionDeclKind::EnumElement: + case CodeCompletionDeclKind::Constructor: + case CodeCompletionDeclKind::Destructor: + case CodeCompletionDeclKind::Subscript: + case CodeCompletionDeclKind::StaticMethod: + case CodeCompletionDeclKind::InstanceMethod: + case CodeCompletionDeclKind::PrefixOperatorFunction: + case CodeCompletionDeclKind::PostfixOperatorFunction: + case CodeCompletionDeclKind::InfixOperatorFunction: + case CodeCompletionDeclKind::FreeFunction: + case CodeCompletionDeclKind::StaticVar: + case CodeCompletionDeclKind::InstanceVar: + case CodeCompletionDeclKind::LocalVar: + case CodeCompletionDeclKind::GlobalVar: + return filter.contains(CodeCompletionFilterFlag::Expr); + + case CodeCompletionDeclKind::Module: + case CodeCompletionDeclKind::Class: + case CodeCompletionDeclKind::Actor: + case CodeCompletionDeclKind::Struct: + case CodeCompletionDeclKind::Enum: + case CodeCompletionDeclKind::Protocol: + case CodeCompletionDeclKind::TypeAlias: + case CodeCompletionDeclKind::AssociatedType: + case CodeCompletionDeclKind::GenericTypeParam: + return filter.contains(CodeCompletionFilterFlag::Type); + + case CodeCompletionDeclKind::PrecedenceGroup: + return filter.contains(CodeCompletionFilterFlag::PrecedenceGroup); + + case CodeCompletionDeclKind::Macro: + return (bool)(R->getMacroRoles() & expectedMacroRoles); + } + + llvm_unreachable("Unhandled associated decl kind"); + }; + + USRBasedTypeContext USRTypeContext(TypeContext, source.USRTypeArena); + + for (auto contextFreeResult : source.Results) { + if (!shouldIncludeResult(contextFreeResult)) { + continue; + } + + CodeCompletionResultTypeRelation typeRelation = + contextFreeResult->calculateContextualTypeRelation(DC, TypeContext, + &USRTypeContext); + ContextualNotRecommendedReason notRecommendedReason = + contextFreeResult->calculateContextualNotRecommendedReason( + ContextualNotRecommendedReason::None, + CanCurrDeclContextHandleAsync); + + auto contextualResult = new (*targetSink.Allocator) CodeCompletionResult( + *contextFreeResult, SemanticContextKind::OtherModule, + CodeCompletionFlair(), + /*numBytesToErase=*/0, typeRelation, notRecommendedReason); + targetSink.Results.push_back(contextualResult); + } + + return llvm::makeMutableArrayRef(targetSink.Results.data() + startSize, + targetSink.Results.size() - startSize); +} + +void CodeCompletionContext::addResultsFromModules( + ArrayRef RequestedModules, + const ExpectedTypeContext &TypeContext, const DeclContext *DC, + bool CanCurrDeclContextHandleAsync) { + // Use the current SourceFile as the DeclContext so that we can use it to + // perform qualified lookup, and to get the correct visibility for + // @testable imports. Also it cannot use 'DC' since it would apply decl + // context changes to cached results. + const SourceFile *SF = DC->getParentSourceFile(); + + for (auto &R : RequestedModules) { + // FIXME(thread-safety): lock the whole AST context. We might load a + // module. + llvm::Optional V = Cache.get(R.Key); + if (!V.has_value()) { + // No cached results found. Fill the cache. + V = Cache.createValue(); + // Temporary sink in which we gather the result. The cache value retains + // the sink's allocator. + CodeCompletionResultSink Sink; + Sink.annotateResult = getAnnotateResult(); + Sink.addInitsToTopLevel = getAddInitsToTopLevel(); + Sink.enableCallPatternHeuristics = getCallPatternHeuristics(); + Sink.includeObjectLiterals = includeObjectLiterals(); + Sink.addCallWithNoDefaultArgs = addCallWithNoDefaultArgs(); + Sink.setProduceContextFreeResults((*V)->USRTypeArena); + lookupCodeCompletionResultsFromModule(Sink, R.TheModule, R.Key.AccessPath, + R.Key.ResultsHaveLeadingDot, SF); + (*V)->Allocator = Sink.Allocator; + auto &CachedResults = (*V)->Results; + CachedResults.reserve(Sink.Results.size()); + // Instead of copying the context free results out of the sink's allocator + // retain the sink's entire allocator (which also includes the contextual + // properities) and simply store pointers to the context free results that + // back the contextual results. + for (auto Result : Sink.Results) { + assert( + Result->getContextFreeResult().getResultType().isBackedByUSRs() && + "Results stored in the cache should have their result types backed " + "by a USR because the cache might outlive the ASTContext the " + "results were created from."); + CachedResults.push_back(&Result->getContextFreeResult()); + } + Cache.set(R.Key, *V); + } + assert(V.has_value()); + auto newItems = + copyCodeCompletionResults(getResultSink(), **V, R.Filter, &TypeContext, + DC, CanCurrDeclContextHandleAsync); + postProcessCompletionResults(newItems, CodeCompletionKind, DC, + &getResultSink()); + } +} diff --git a/lib/IDE/CompletionLookup.cpp b/lib/IDE/CompletionLookup.cpp index a3107512ca861..faec684cd39ab 100644 --- a/lib/IDE/CompletionLookup.cpp +++ b/lib/IDE/CompletionLookup.cpp @@ -2416,18 +2416,6 @@ void CompletionLookup::addPostfixOperatorCompletion(OperatorDecl *op, addTypeAnnotation(builder, resultType); } -void CompletionLookup::tryPostfixOperator(Expr *expr, PostfixOperatorDecl *op) { - ConcreteDeclRef referencedDecl; - FunctionType *funcTy = getTypeOfCompletionOperator( - const_cast(CurrDeclContext), expr, op->getName(), - DeclRefKind::PostfixOperator, referencedDecl); - if (!funcTy) - return; - - // TODO: Use referencedDecl (FuncDecl) instead of 'op' (OperatorDecl). - addPostfixOperatorCompletion(op, funcTy->getResult()); -} - void CompletionLookup::addAssignmentOperator(Type RHSType) { CodeCompletionResultBuilder builder = makeResultBuilder( CodeCompletionResultKind::BuiltinOperator, SemanticContextKind::None); @@ -2472,104 +2460,6 @@ void CompletionLookup::addInfixOperatorCompletion(OperatorDecl *op, addTypeAnnotation(builder, resultType); } -void CompletionLookup::tryInfixOperatorCompletion(Expr *foldedExpr, - InfixOperatorDecl *op) { - ConcreteDeclRef referencedDecl; - FunctionType *funcTy = getTypeOfCompletionOperator( - const_cast(CurrDeclContext), foldedExpr, op->getName(), - DeclRefKind::BinaryOperator, referencedDecl); - if (!funcTy) - return; - - Type lhsTy = funcTy->getParams()[0].getPlainType(); - Type rhsTy = funcTy->getParams()[1].getPlainType(); - Type resultTy = funcTy->getResult(); - - // Don't complete optional operators on non-optional types. - if (!lhsTy->getRValueType()->getOptionalObjectType()) { - // 'T ?? T' - if (op->getName().str() == "??") - return; - // 'T == nil' - if (auto NT = rhsTy->getNominalOrBoundGenericNominal()) - if (NT->getName() == - CurrDeclContext->getASTContext().Id_OptionalNilComparisonType) - return; - } - - // If the right-hand side and result type are both type parameters, we're - // not providing a useful completion. - if (resultTy->isTypeParameter() && rhsTy->isTypeParameter()) - return; - - // TODO: Use referencedDecl (FuncDecl) instead of 'op' (OperatorDecl). - addInfixOperatorCompletion(op, funcTy->getResult(), - funcTy->getParams()[1].getPlainType()); -} - -Expr * -CompletionLookup::typeCheckLeadingSequence(Expr *LHS, - ArrayRef leadingSequence) { - if (leadingSequence.empty()) - return LHS; - - SourceRange sequenceRange(leadingSequence.front()->getStartLoc(), - LHS->getEndLoc()); - auto *expr = findParsedExpr(CurrDeclContext, sequenceRange); - if (!expr) - return LHS; - - if (expr->getType() && !expr->getType()->hasError()) - return expr; - - if (!typeCheckExpression(const_cast(CurrDeclContext), expr)) - return expr; - return LHS; -} - -void CompletionLookup::getOperatorCompletions( - Expr *LHS, ArrayRef leadingSequence) { - if (IsSuperRefExpr) - return; - - Expr *foldedExpr = typeCheckLeadingSequence(LHS, leadingSequence); - - SmallVector operators; - collectOperators(operators); - // FIXME: this always chooses the first operator with the given name. - llvm::DenseSet seenPostfixOperators; - llvm::DenseSet seenInfixOperators; - - for (auto op : operators) { - switch (op->getKind()) { - case DeclKind::PrefixOperator: - // Don't insert prefix operators in postfix position. - // FIXME: where should these get completed? - break; - case DeclKind::PostfixOperator: - if (seenPostfixOperators.insert(op->getName()).second) - tryPostfixOperator(LHS, cast(op)); - break; - case DeclKind::InfixOperator: - if (seenInfixOperators.insert(op->getName()).second) - tryInfixOperatorCompletion(foldedExpr, cast(op)); - break; - default: - llvm_unreachable("unexpected operator kind"); - } - } - - if (leadingSequence.empty() && LHS->getType() && - LHS->getType()->hasLValueType()) { - addAssignmentOperator(LHS->getType()->getRValueType()); - } - - // FIXME: unify this with the ?.member completions. - if (auto T = LHS->getType()) - if (auto ValueT = T->getRValueType()->getOptionalObjectType()) - addPostfixBang(ValueT); -} - void CompletionLookup::addTypeRelationFromProtocol( CodeCompletionResultBuilder &builder, CodeCompletionLiteralKind kind) { Type literalType; diff --git a/lib/IDE/ExprCompletion.cpp b/lib/IDE/ExprCompletion.cpp index 47ec43b365d64..acea1c64c4559 100644 --- a/lib/IDE/ExprCompletion.cpp +++ b/lib/IDE/ExprCompletion.cpp @@ -96,14 +96,18 @@ void ExprTypeCheckCompletionCallback::sawSolutionImpl( } } -void ExprTypeCheckCompletionCallback::deliverResults( - SourceLoc CCLoc, ide::CodeCompletionContext &CompletionCtx, - CodeCompletionConsumer &Consumer) { +void ExprTypeCheckCompletionCallback::collectResults( + SourceLoc CCLoc, ide::CodeCompletionContext &CompletionCtx) { ASTContext &Ctx = DC->getASTContext(); CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC, &CompletionCtx); Lookup.shouldCheckForDuplicates(Results.size() > 1); + // The type context that is being used for global results. + ExpectedTypeContext UnifiedTypeContext; + UnifiedTypeContext.setPreferNonVoid(true); + bool UnifiedCanHandleAsync = false; + for (auto &Result : Results) { WithSolutionSpecificVarTypesRAII VarTypes(Result.SolutionSpecificVarTypes); @@ -117,7 +121,11 @@ void ExprTypeCheckCompletionCallback::deliverResults( if (Result.UnresolvedMemberBaseType) { Lookup.getUnresolvedMemberCompletions(Result.UnresolvedMemberBaseType); } + + UnifiedTypeContext.merge(*Lookup.getExpectedTypeContext()); + UnifiedCanHandleAsync |= Result.IsInAsyncContext; } - deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer); + collectCompletionResults(CompletionCtx, Lookup, DC, UnifiedTypeContext, + UnifiedCanHandleAsync); } diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index cccf20e337f56..975242028b27e 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -152,1243 +152,3 @@ Expr *swift::ide::findParsedExpr(const DeclContext *DC, const_cast(DC)->walkContext(finder); return finder.get(); } - -//===----------------------------------------------------------------------===// -// removeCodeCompletionExpr(ASTContext, Expr) -//===----------------------------------------------------------------------===// - -namespace { -// TODO: Implement other expressions? -class CCExprRemover: public ASTWalker, public ExprVisitor { - ASTContext &Ctx; - -public: - bool Removed = false; - - CCExprRemover(ASTContext &Ctx) : Ctx(Ctx) {} - - MacroWalking getMacroWalkingBehavior() const override { - return MacroWalking::ArgumentsAndExpansion; - } - - Expr *visitCallExpr(CallExpr *E) { - auto *args = E->getArgs()->getOriginalArgs(); - - llvm::Optional newTrailingClosureIdx; - SmallVector newArgs; - for (auto idx : indices(*args)) { - // Update the trailing closure index if we have one. - if (args->hasAnyTrailingClosures() && - idx == *args->getFirstTrailingClosureIndex()) { - newTrailingClosureIdx = newArgs.size(); - } - auto arg = args->get(idx); - if (!isa(arg.getExpr())) - newArgs.push_back(arg); - } - if (newArgs.size() == args->size()) - return E; - - // If we ended up removing the last trailing closure, drop the index. - if (newTrailingClosureIdx && *newTrailingClosureIdx == newArgs.size()) - newTrailingClosureIdx = llvm::None; - - Removed = true; - - auto *argList = ArgumentList::create( - Ctx, args->getLParenLoc(), newArgs, args->getRParenLoc(), - newTrailingClosureIdx, E->isImplicit()); - return CallExpr::create(Ctx, E->getFn(), argList, E->isImplicit()); - } - - Expr *visitExpr(Expr *E) { - return E; - } - - PreWalkResult walkToExprPre(Expr *E) override { - if (Removed) - return Action::Stop(); - E = visit(E); - return Action::SkipChildrenIf(Removed, E); - } - - PreWalkResult walkToStmtPre(Stmt *S) override { - if (Removed) - return Action::Stop(); - return Action::Continue(S); - } - - PreWalkAction walkToDeclPre(Decl *D) override { - return Action::SkipChildrenIf(Removed); - } -}; -} - -bool swift::ide::removeCodeCompletionExpr(ASTContext &Ctx, Expr *&expr) { - CCExprRemover remover(Ctx); - expr = expr->walk(remover); - return remover.Removed; -} - -//===----------------------------------------------------------------------===// -// collectPossibleReturnTypesFromContext(DeclContext, SmallVectorImpl) -//===----------------------------------------------------------------------===// - -void swift::ide::collectPossibleReturnTypesFromContext( - DeclContext *DC, SmallVectorImpl &candidates) { - if (auto FD = dyn_cast(DC)) { - auto Ty = FD->getInterfaceType(); - if (FD->getDeclContext()->isTypeContext()) - Ty = FD->getMethodInterfaceType(); - if (auto FT = Ty->getAs()) { - candidates.push_back(DC->mapTypeIntoContext(FT->getResult())); - } - } - - if (auto ACE = dyn_cast(DC)) { - // Use the type checked type if it has. - if (ACE->getType() && !ACE->getType()->hasError() && - !ACE->getResultType()->hasUnresolvedType()) { - candidates.push_back(ACE->getResultType()); - return; - } - - if (auto CE = dyn_cast(ACE)) { - if (CE->hasExplicitResultType()) { - // If the closure has a explicit return type, use it. - if (auto ty = CE->getExplicitResultType()) { - candidates.push_back(ty); - return; - } else { - const auto type = swift::performTypeResolution( - CE->getExplicitResultTypeRepr(), DC->getASTContext(), - DC->getGenericSignatureOfContext(), /*SILContext=*/nullptr, - const_cast(DC), /*diagnostics=*/false); - - if (!type->hasError()) { - candidates.push_back(DC->mapTypeIntoContext(type)); - return; - } - } - } else { - // Otherwise, check the context type of the closure. - ExprContextInfo closureCtxInfo(CE->getParent(), CE); - for (auto closureTy : closureCtxInfo.getPossibleTypes()) { - if (auto funcTy = closureTy->getAs()) - candidates.push_back(funcTy->getResult()); - } - if (!candidates.empty()) - return; - } - } - - // Even if the type checked type has unresolved types, it's better than - // nothing. - if (ACE->getType() && !ACE->getType()->hasError()) - candidates.push_back(ACE->getResultType()); - } -} - -//===----------------------------------------------------------------------===// -// ExprContextInfo(DeclContext, SourceRange) -//===----------------------------------------------------------------------===// - -namespace { -class ExprParentFinder : public ASTWalker { - friend class ExprContextAnalyzer; - Expr *ChildExpr; - std::function Predicate; - - bool arePositionsSame(Expr *E1, Expr *E2) { - return E1->getSourceRange().Start == E2->getSourceRange().Start && - E1->getSourceRange().End == E2->getSourceRange().End; - } - -public: - llvm::SmallVector Ancestors; - ExprParentFinder(Expr *ChildExpr, - std::function Predicate) - : ChildExpr(ChildExpr), Predicate(Predicate) {} - - MacroWalking getMacroWalkingBehavior() const override { - return MacroWalking::ArgumentsAndExpansion; - } - - PreWalkResult walkToExprPre(Expr *E) override { - // Finish if we found the target. 'ChildExpr' might have been replaced - // with typechecked expression. In that case, match the position. - if (E == ChildExpr || arePositionsSame(E, ChildExpr)) - return Action::Stop(); - - if (E != ChildExpr && Predicate(E, Parent)) { - Ancestors.push_back(E); - return Action::Continue(E); - } - return Action::Continue(E); - } - - PostWalkResult walkToExprPost(Expr *E) override { - if (Predicate(E, Parent)) - Ancestors.pop_back(); - return Action::Continue(E); - } - - PreWalkResult walkToStmtPre(Stmt *S) override { - if (Predicate(S, Parent)) - Ancestors.push_back(S); - return Action::Continue(S); - } - - PostWalkResult walkToStmtPost(Stmt *S) override { - if (Predicate(S, Parent)) - Ancestors.pop_back(); - return Action::Continue(S); - } - - PreWalkAction walkToDeclPre(Decl *D) override { - if (Predicate(D, Parent)) - Ancestors.push_back(D); - return Action::Continue(); - } - - PostWalkAction walkToDeclPost(Decl *D) override { - if (Predicate(D, Parent)) - Ancestors.pop_back(); - return Action::Continue(); - } - - PreWalkResult walkToPatternPre(Pattern *P) override { - if (Predicate(P, Parent)) - Ancestors.push_back(P); - return Action::Continue(P); - } - - PostWalkResult walkToPatternPost(Pattern *P) override { - if (Predicate(P, Parent)) - Ancestors.pop_back(); - return Action::Continue(P); - } -}; - -/// Collect function (or subscript) members with the given \p name on \p baseTy. -static void collectPossibleCalleesByQualifiedLookup( - DeclContext &DC, Type baseTy, DeclNameRef name, SourceLoc loc, - SmallVectorImpl &candidates) { - auto baseInstanceTy = baseTy->getMetatypeInstanceType(); - if (!baseInstanceTy->mayHaveMembers()) - return; - - if (name == DeclNameRef::createConstructor()) { - // Existential types cannot be instantiated. e.g. 'MyProtocol()'. - if (baseInstanceTy->isExistentialType()) - return; - - // 'AnyObject' is not initializable. - if (baseInstanceTy->isAnyObject()) - return; - } - - // Make sure we've resolved implicit members. - namelookup::installSemanticMembersIfNeeded(baseInstanceTy, name); - - bool isOnMetaType = baseTy->is(); - - SmallVector decls; - if (!DC.lookupQualified(baseInstanceTy, - name.withoutArgumentLabels(), loc, - NL_QualifiedDefault | NL_ProtocolMembers, - decls)) - return; - - llvm::DenseMap, size_t> known; - auto *baseNominal = baseInstanceTy->getAnyNominal(); - for (auto *VD : decls) { - if ((!isa(VD) && !isa(VD) && - !isa(VD)) || - VD->shouldHideFromEditor()) - continue; - if (!isMemberDeclApplied(&DC, baseInstanceTy, VD)) - continue; - Type declaredMemberType = VD->getInterfaceType(); - if (!declaredMemberType->is()) - continue; - if (VD->getDeclContext()->isTypeContext()) { - if (isa(VD)) { - if (!isOnMetaType && VD->isStatic()) - continue; - if (isOnMetaType == VD->isStatic()) - declaredMemberType = - declaredMemberType->castTo()->getResult(); - } else if (isa(VD)) { - if (!isOnMetaType) - continue; - declaredMemberType = - declaredMemberType->castTo()->getResult(); - } else if (isa(VD)) { - if (isOnMetaType != VD->isStatic()) - continue; - } else if (isa(VD)) { - if (!isOnMetaType) - continue; - declaredMemberType = - declaredMemberType->castTo()->getResult(); - } - } - - auto subs = baseInstanceTy->getMemberSubstitutionMap( - DC.getParentModule(), VD, - VD->getInnermostDeclContext()->getGenericEnvironmentOfContext()); - auto fnType = declaredMemberType.subst(subs); - if (!fnType || !fnType->is()) - continue; - - // If we are calling on a type alias type, replace the canonicalized type - // in the function type with the type alias. - if (isa(baseInstanceTy.getPointer())) { - auto canBaseTy = baseInstanceTy->getCanonicalType(); - fnType = fnType.transform([&](Type t) -> Type { - if (t->getCanonicalType()->isEqual(canBaseTy)) - return baseInstanceTy; - return t; - }); - } - - auto semanticContext = SemanticContextKind::CurrentNominal; - if (baseNominal && - VD->getDeclContext()->getSelfNominalTypeDecl() != baseNominal) - semanticContext = SemanticContextKind::Super; - - FunctionTypeAndDecl entry(fnType->castTo(), VD, - semanticContext); - // Remember the index of the entry. - auto knownResult = known.insert( - {{VD->isStatic(), fnType->getCanonicalType()}, candidates.size()}); - if (knownResult.second) { - candidates.push_back(entry); - continue; - } - - auto idx = knownResult.first->second; - if (AvailableAttr::isUnavailable(candidates[idx].Decl) && - !AvailableAttr::isUnavailable(VD)) { - // Replace the previously found "unavailable" with the "available" one. - candidates[idx] = entry; - } - - // Otherwise, skip redundant results. - } -} - -/// Collect function (or subscript) members with the given \p name on -/// \p baseExpr expression. -static void collectPossibleCalleesByQualifiedLookup( - DeclContext &DC, Expr *baseExpr, DeclNameRef name, - SmallVectorImpl &candidates) { - ConcreteDeclRef ref = nullptr; - - if (auto ice = dyn_cast(baseExpr)) - baseExpr = ice->getSyntacticSubExpr(); - - // Re-typecheck TypeExpr so it's typechecked without the arguments which may - // affects the inference of the generic arguments. - if (TypeExpr *tyExpr = dyn_cast(baseExpr)) { - if (!tyExpr->isImplicit()) - tyExpr->setType(nullptr); - } - - Type baseTy = baseExpr->getType(); - if (!baseTy || baseTy->is()) { - auto baseTyOpt = getTypeOfCompletionContextExpr( - DC.getASTContext(), &DC, CompletionTypeCheckKind::Normal, baseExpr, - ref); - if (!baseTyOpt) - return; - baseTy = *baseTyOpt; - } - baseTy = baseTy->getWithoutSpecifierType(); - - // Use metatype for lookup 'super.init' and 'self.init' if it's inside - // constructors. - if (name == DeclNameRef::createConstructor() && isa(DC)) { - bool isSuperCall = isa(baseExpr); - bool isSelfCall = false; - if (auto declRef = dyn_cast(baseExpr)) { - if (declRef->getDecl()->getName() == DC.getASTContext().Id_self) { - isSelfCall = true; - } - } - if (isSuperCall || isSelfCall) { - baseTy = MetatypeType::get(baseTy); - } - } - - collectPossibleCalleesByQualifiedLookup(DC, baseTy, name, - baseExpr->getLoc(), - candidates); - - // Add virtual 'subscript(keyPath: KeyPath) -> Value'. - if (name.getBaseName() == DeclBaseName::createSubscript() && - (baseTy->getAnyNominal() || baseTy->is() || - baseTy->is())) { - auto &Ctx = DC.getASTContext(); - - auto *kpDecl = Ctx.getKeyPathDecl(); - Type kpTy = kpDecl->mapTypeIntoContext(kpDecl->getDeclaredInterfaceType()); - Type kpValueTy = kpTy->castTo()->getGenericArgs()[1]; - kpTy = BoundGenericType::get(kpDecl, Type(), {baseTy, kpValueTy}); - - // FIXME: Verify ExtInfo state is correct, not working by accident. - FunctionType::ExtInfo info; - Type fnTy = FunctionType::get( - {AnyFunctionType::Param(kpTy, Ctx.Id_keyPath)}, kpValueTy, info); - candidates.emplace_back(fnTy->castTo(), nullptr); - } -} - -/// For the given \p unresolvedMemberExpr, collect possible callee types and -/// declarations. -static bool collectPossibleCalleesForUnresolvedMember( - DeclContext &DC, UnresolvedMemberExpr *unresolvedMemberExpr, - SmallVectorImpl &candidates) { - auto collectMembers = [&](Type expectedTy) { - if (!expectedTy->mayHaveMembers()) - return; - collectPossibleCalleesByQualifiedLookup(DC, MetatypeType::get(expectedTy), - unresolvedMemberExpr->getName(), - unresolvedMemberExpr->getLoc(), - candidates); - }; - - // Get the context of the expression itself. - ExprContextInfo contextInfo(&DC, unresolvedMemberExpr); - for (auto expectedTy : contextInfo.getPossibleTypes()) { - collectMembers(expectedTy); - // If this is an optional type, let's also check its base type. - if (auto baseTy = expectedTy->getOptionalObjectType()) { - collectMembers(baseTy->lookThroughAllOptionalTypes()); - } - } - return !candidates.empty(); -} - -/// For the given \c callExpr, collect possible callee types and declarations. -static bool collectPossibleCalleesForApply( - DeclContext &DC, ApplyExpr *callExpr, - SmallVectorImpl &candidates) { - auto *fnExpr = callExpr->getFn(); - - if (auto *DRE = dyn_cast(fnExpr)) { - if (auto *decl = DRE->getDecl()) { - Type declTy = fnExpr->getType(); - if ((!declTy || declTy->hasError() || declTy->hasUnresolvedType()) && - decl->hasInterfaceType()) { - declTy = decl->getInterfaceType(); - declTy = decl->getInnermostDeclContext()->mapTypeIntoContext(declTy); - } - if (declTy) { - declTy = declTy->getWithoutSpecifierType(); - if (auto *funcTy = declTy->getAs()) - candidates.emplace_back(funcTy, decl); - } - } - } else if (auto *OSRE = dyn_cast(fnExpr)) { - for (auto *decl : OSRE->getDecls()) { - if (decl->hasInterfaceType()) { - auto declTy = decl->getInterfaceType(); - declTy = decl->getInnermostDeclContext()->mapTypeIntoContext(declTy); - if (auto *funcType = declTy->getAs()) - candidates.emplace_back(funcType, decl); - } - } - } else if (auto *UDE = dyn_cast(fnExpr)) { - collectPossibleCalleesByQualifiedLookup(DC, UDE->getBase(), UDE->getName(), - candidates); - } else if (auto *DSCE = dyn_cast(fnExpr)) { - if (auto *DRE = dyn_cast(DSCE->getFn())) { - collectPossibleCalleesByQualifiedLookup( - DC, DSCE->getBase(), DeclNameRef(DRE->getDecl()->getName()), - candidates); - } - } else if (auto CRCE = dyn_cast(fnExpr)) { - collectPossibleCalleesByQualifiedLookup( - DC, CRCE->getBase(), DeclNameRef::createConstructor(), candidates); - } else if (auto TE = dyn_cast(fnExpr)) { - collectPossibleCalleesByQualifiedLookup( - DC, TE, DeclNameRef::createConstructor(), candidates); - } else if (auto *UME = dyn_cast(fnExpr)) { - collectPossibleCalleesForUnresolvedMember(DC, UME, candidates); - } - - if (!candidates.empty()) - return true; - - ConcreteDeclRef refDecl = nullptr; - Type fnType = fnExpr->getType(); - if (fnType) { - refDecl = fnExpr->getReferencedDecl(); - if (!refDecl) - if (auto apply = dyn_cast(fnExpr)) - refDecl = apply->getFn()->getReferencedDecl(); - } - if (!fnType) { - auto fnTypeOpt = getTypeOfCompletionContextExpr( - DC.getASTContext(), &DC, CompletionTypeCheckKind::Normal, fnExpr, - refDecl); - if (fnTypeOpt) - fnType = *fnTypeOpt; - } - - if (!fnType || fnType->hasError()) - return false; - fnType = fnType->getWithoutSpecifierType(); - - if (auto *AFT = fnType->getAs()) { - candidates.emplace_back(AFT, refDecl.getDecl()); - } else if (auto *AMT = fnType->getAs()) { - auto baseTy = AMT->getInstanceType(); - if (isa(fnExpr) && baseTy->mayHaveMembers()) { - collectPossibleCalleesByQualifiedLookup( - DC, fnExpr, DeclNameRef::createConstructor(), candidates); - } - } else { - // Otherwise, look for `callAsFunction` (SE-0253). - collectPossibleCalleesByQualifiedLookup( - DC, fnExpr, DeclNameRef(DC.getASTContext().Id_callAsFunction), - candidates); - } - - return !candidates.empty(); -} - -/// For the given \c subscriptExpr, collect possible callee types and -/// declarations. -static bool collectPossibleCalleesForSubscript( - DeclContext &DC, SubscriptExpr *subscriptExpr, - SmallVectorImpl &candidates) { - if (subscriptExpr->hasDecl()) { - if (auto SD = dyn_cast(subscriptExpr->getDecl().getDecl())) { - auto declType = SD->getInterfaceType(); - declType = declType.subst(subscriptExpr->getDecl().getSubstitutions()); - if (auto *funcType = declType->getAs()) - candidates.emplace_back(funcType, SD); - } - } else { - collectPossibleCalleesByQualifiedLookup(DC, subscriptExpr->getBase(), - DeclNameRef::createSubscript(), - candidates); - } - return !candidates.empty(); -} - -/// Get index of \p CCExpr in \p Args. -/// \returns \c true if success, \c false if \p CCExpr is not a part of \p Args. -static bool getPositionInArgs(DeclContext &DC, ArgumentList *Args, Expr *CCExpr, - unsigned &Position, bool &HasName) { - auto &SM = DC.getASTContext().SourceMgr; - for (auto idx : indices(*Args)) { - auto arg = Args->get(idx); - if (SM.isBeforeInBuffer(arg.getExpr()->getEndLoc(), CCExpr->getStartLoc())) - continue; - HasName = arg.getLabelLoc().isValid(); - Position = idx; - return true; - } - return false; -} - -/// Get index of \p CCExpr in \p TE. -/// \returns \c true if success, \c false if \p CCExpr is not a part of \p Args. -static bool getPositionInTuple(DeclContext &DC, TupleExpr *TE, Expr *CCExpr, - unsigned &Position, bool &HasName) { - auto &SM = DC.getASTContext().SourceMgr; - for (auto idx : indices(TE->getElements())) { - if (SM.isBeforeInBuffer(TE->getElement(idx)->getEndLoc(), - CCExpr->getStartLoc())) - continue; - HasName = TE->getElementNameLoc(idx).isValid(); - Position = idx; - return true; - } - return false; -} - -/// Get index of \p CCExpr in \p Params. Note that the position in \p Params may -/// be different than the position in \p Args if there are defaulted arguments -/// in \p Params which don't occur in \p Args. -/// -/// \returns the position index number on success, \c None if \p CCExpr is not -/// a part of \p Args. -static llvm::Optional -getPositionInParams(DeclContext &DC, const ArgumentList *Args, Expr *CCExpr, - ArrayRef Params, bool Lenient) { - auto &SM = DC.getASTContext().SourceMgr; - unsigned PosInParams = 0; - unsigned PosInArgs = 0; - bool LastParamWasVariadic = false; - // We advance PosInArgs until we find argument that is after the code - // completion token, which is when we stop. - // For each argument, we try to find a matching parameter either by matching - // argument labels, in which case PosInParams may be advanced by more than 1, - // or by advancing PosInParams and PosInArgs both by 1. - for (; PosInArgs < Args->size(); ++PosInArgs) { - if (!SM.isBeforeInBuffer(Args->getExpr(PosInArgs)->getEndLoc(), - CCExpr->getStartLoc())) { - // The arg is after the code completion position. Stop. - if (LastParamWasVariadic && Args->getLabel(PosInArgs).empty()) { - // If the last parameter was variadic and this argument stands by itself - // without a label, assume that it belongs to the previous vararg - // list. - PosInParams--; - } - break; - } - - auto ArgName = Args->getLabel(PosInArgs); - // If the last parameter we matched was variadic, we claim all following - // unlabeled arguments for that variadic parameter -> advance PosInArgs but - // not PosInParams. - if (LastParamWasVariadic && ArgName.empty()) { - continue; - } else { - LastParamWasVariadic = false; - } - - // Look for a matching parameter label. - bool AdvancedPosInParams = false; - for (unsigned i = PosInParams; i < Params.size(); ++i) { - if (Params[i].getLabel() == ArgName) { - // We have found a label match. Advance the position in the params - // to point to the param after the one with this label. - PosInParams = i + 1; - AdvancedPosInParams = true; - if (Params[i].isVariadic()) { - LastParamWasVariadic = true; - } - break; - } - } - - if (!AdvancedPosInParams && Args->isTrailingClosureIndex(PosInArgs)) { - // If the argument is a trailing closure, it can't match non-function - // parameters. Advance to the next function parameter. - for (unsigned i = PosInParams; i < Params.size(); ++i) { - if (Params[i].getParameterType()->is()) { - PosInParams = i + 1; - AdvancedPosInParams = true; - break; - } - } - } - - if (!AdvancedPosInParams) { - if (Lenient) { - // We haven't performed any special advance logic. Assume the argument - // and parameter match, so advance PosInParams by 1. - PosInParams += 1; - } else { - // If there is no matching argument label. These arguments can't be - // applied to the params. - return llvm::None; - } - } - } - if (PosInArgs < Args->size() && PosInParams < Params.size()) { - // We didn't search until the end, so we found a position in Params. Success - return PosInParams; - } else { - return llvm::None; - } -} - -/// Given an expression and its context, the analyzer tries to figure out the -/// expected type of the expression by analyzing its context. -class ExprContextAnalyzer { - DeclContext *DC; - Expr *ParsedExpr; - SourceManager &SM; - ASTContext &Context; - - // Results populated by Analyze() - SmallVectorImpl &PossibleTypes; - SmallVectorImpl &PossibleParams; - SmallVectorImpl &PossibleCallees; - Expr *&AnalyzedExpr; - bool &implicitSingleExpressionReturn; - - void recordPossibleType(Type ty) { - if (!ty || ty->is()) - return; - - PossibleTypes.push_back(ty->getRValueType()); - } - - void recordPossibleParam(const AnyFunctionType::Param *arg, bool isRequired) { - PossibleParams.emplace_back(arg, isRequired); - } - - /// Collect context information at call argument position. - bool analyzeApplyExpr(Expr *E) { - // Collect parameter lists for possible func decls. - SmallVector Candidates; - ArgumentList *Args = nullptr; - if (auto *applyExpr = dyn_cast(E)) { - if (!collectPossibleCalleesForApply(*DC, applyExpr, Candidates)) - return false; - Args = applyExpr->getArgs(); - } else if (auto *subscriptExpr = dyn_cast(E)) { - if (!collectPossibleCalleesForSubscript(*DC, subscriptExpr, Candidates)) - return false; - Args = subscriptExpr->getArgs(); - } else { - llvm_unreachable("unexpected expression kind"); - } - assert(!Candidates.empty()); - PossibleCallees.assign(Candidates.begin(), Candidates.end()); - - // Determine the position of code completion token in call argument. - unsigned PositionInArgs; - bool HasName; - if (!getPositionInArgs(*DC, Args, ParsedExpr, PositionInArgs, HasName)) - return false; - - // Collect possible types (or labels) at the position. - { - bool MayBeArgForLabeledParam = - HasName || E->isImplicit() || - (!isa(E) && !isa(E) && - !isa(E)); - - // If the completion position cannot be the actual argument, it must be - // able to be an argument label. - bool MayBeLabel = !MayBeArgForLabeledParam; - - // Alternatively, the code completion position may complete to an argument - // label if we are currently completing variadic args. - // E.g. - // func foo(x: Int..., y: Int...) {} - // foo(x: 1, #^COMPLETE^#) - // #^COMPLETE^# may complete to either an additional variadic arg or to - // the argument label `y`. - // - // Varargs are represented by a VarargExpansionExpr that contains an - // ArrayExpr on the call side. - if (auto Vararg = - dyn_cast(Args->getExpr(PositionInArgs))) { - if (auto Array = dyn_cast_or_null(Vararg->getSubExpr())) { - if (Array->getNumElements() > 0 && - !isa(Array->getElement(0))) { - // We can only complete as argument label if we have at least one - // proper vararg before the code completion token. We shouldn't be - // suggesting labels for: - // foo(x: #^COMPLETE^#) - MayBeLabel = true; - } - } - } - SmallPtrSet seenTypes; - llvm::SmallSet, 4> seenArgs; - llvm::SmallVector, 2> posInParams; - { - bool found = false; - auto *originalArgs = Args->getOriginalArgs(); - for (auto &typeAndDecl : Candidates) { - llvm::Optional pos = getPositionInParams( - *DC, originalArgs, ParsedExpr, typeAndDecl.Type->getParams(), - /*lenient=*/false); - posInParams.push_back(pos); - found |= pos.has_value(); - } - if (!found) { - // If applicable overload is not found, retry with considering - // non-matching argument labels mis-typed. - for (auto i : indices(Candidates)) { - posInParams[i] = getPositionInParams( - *DC, originalArgs, ParsedExpr, Candidates[i].Type->getParams(), - /*lenient=*/true); - } - } - } - assert(posInParams.size() == Candidates.size()); - - for (auto i : indices(Candidates)) { - if (!posInParams[i].has_value()) { - // If the argument doesn't have a matching position in the parameters, - // indicate that with optional nullptr param. - if (seenArgs.insert({Identifier(), CanType()}).second) - recordPossibleParam(nullptr, /*isRequired=*/false); - continue; - } - - auto &typeAndDecl = Candidates[i]; - DeclContext *memberDC = nullptr; - if (typeAndDecl.Decl) - memberDC = typeAndDecl.Decl->getInnermostDeclContext(); - - auto Params = typeAndDecl.Type->getParams(); - auto PositionInParams = *posInParams[i]; - - ParameterList *paramList = nullptr; - if (auto VD = typeAndDecl.Decl) { - paramList = getParameterList(VD); - if (paramList && paramList->size() != Params.size()) - paramList = nullptr; - } - for (auto Pos = PositionInParams; Pos < Params.size(); ++Pos) { - const auto ¶mType = Params[Pos]; - Type ty = paramType.getPlainType(); - if (memberDC && ty->hasTypeParameter()) - ty = memberDC->mapTypeIntoContext(ty); - - bool canSkip = - paramList && (paramList->get(Pos)->isDefaultArgument() || - paramList->get(Pos)->isVariadic()); - - if (MayBeLabel && paramType.hasLabel()) { - if (seenArgs.insert({paramType.getLabel(), ty->getCanonicalType()}) - .second) - recordPossibleParam(¶mType, !canSkip); - } - - if (MayBeArgForLabeledParam || !paramType.hasLabel()) { - auto argTy = ty; - if (paramType.isInOut()) - argTy = InOutType::get(argTy); - else if (paramType.isAutoClosure() && argTy->is()) - argTy = argTy->castTo()->getResult(); - if (seenTypes.insert(argTy->getCanonicalType()).second) - recordPossibleType(argTy); - } - if (!canSkip) - break; - } - } - } - return !PossibleTypes.empty() || !PossibleParams.empty(); - } - - void analyzeExpr(Expr *Parent) { - AnalyzedExpr = Parent; - switch (Parent->getKind()) { - case ExprKind::Call: - case ExprKind::Subscript: - case ExprKind::Binary: - case ExprKind::PrefixUnary: { - analyzeApplyExpr(Parent); - break; - } - case ExprKind::Array: { - if (auto type = ParsedExpr->getType()) { - if (!type->is()) { - recordPossibleType(type); - break; - } - } - - // Check context types of the array literal expression. - ExprContextInfo arrayCtxtInfo(DC, Parent); - for (auto arrayT : arrayCtxtInfo.getPossibleTypes()) { - if (auto boundGenericT = arrayT->getAs()) { - // let _: [Element] = [#HERE#] - // In this case, 'Element' is the expected type. - if (boundGenericT->isArray()) - recordPossibleType(boundGenericT->getGenericArgs()[0]); - - // let _: [Key : Value] = [#HERE#] - // In this case, 'Key' is the expected type. - if (boundGenericT->isDictionary()) - recordPossibleType(boundGenericT->getGenericArgs()[0]); - } - } - break; - } - case ExprKind::Dictionary: { - // Check context types of the dictionary literal expression. - ExprContextInfo dictCtxtInfo(DC, Parent); - - for (auto dictT : dictCtxtInfo.getPossibleTypes()) { - if (auto boundGenericT = dictT->getAs()) { - if (boundGenericT->isDictionary()) { - if (ParsedExpr->isImplicit() && isa(ParsedExpr)) { - // let _: [Key : Value] = [#HERE#:] - // let _: [Key : Value] = [#HERE#:val] - // let _: [Key : Value] = [key:#HERE#] - // In this case, this is called by 'ExprKind::Tuple' case. Return - // '(Key,Value)' here, 'ExprKind::Tuple' branch can decide which - // type in the tuple type is the exprected type. - SmallVector elts; - for (auto genericArg : boundGenericT->getGenericArgs()) - elts.emplace_back(genericArg); - recordPossibleType(TupleType::get(elts, DC->getASTContext())); - } else { - // let _: [Key : Value] = [key: val, #HERE#] - // In this case, assume 'Key' is the expected type. - if (boundGenericT->isDictionary()) - recordPossibleType(boundGenericT->getGenericArgs()[0]); - } - } - } - } - break; - } - case ExprKind::Ternary: { - auto *IE = cast(Parent); - if (IE->isFolded() && - SM.rangeContains(IE->getCondExpr()->getSourceRange(), - ParsedExpr->getSourceRange())) { - recordPossibleType(Context.getBoolType()); - break; - } - ExprContextInfo ternaryCtxtInfo(DC, Parent); - for (auto ternaryT : ternaryCtxtInfo.getPossibleTypes()) - recordPossibleType(ternaryT); - break; - } - case ExprKind::Assign: { - auto *AE = cast(Parent); - - // Make sure code completion is on the right hand side. - if (SM.isBeforeInBuffer(AE->getEqualLoc(), ParsedExpr->getStartLoc())) { - - // The destination is of the expected type. - auto *destExpr = AE->getDest(); - if (auto type = destExpr->getType()) { - recordPossibleType(type); - } else if (auto *DRE = dyn_cast(destExpr)) { - if (auto *decl = DRE->getDecl()) { - if (decl->hasInterfaceType()) - recordPossibleType(decl->getDeclContext()->mapTypeIntoContext( - decl->getInterfaceType())); - } - } - } - break; - } - case ExprKind::Tuple: { - TupleType *tupleT = nullptr; - if (Parent->getType() && Parent->getType()->is()) { - tupleT = Parent->getType()->castTo(); - } else { - ExprContextInfo tupleCtxtInfo(DC, Parent); - for (auto possibleT : tupleCtxtInfo.getPossibleTypes()) { - if (auto possibleTupleT = possibleT->getAs()) { - tupleT = possibleTupleT; - break; - } - } - if (!tupleT) - return; - } - - unsigned Position = 0; - bool HasName; - if (getPositionInTuple(*DC, cast(Parent), ParsedExpr, Position, - HasName)) { - // The expected type may have fewer number of elements. - if (Position < tupleT->getNumElements()) - recordPossibleType(tupleT->getElementType(Position)); - } - break; - } - case ExprKind::Closure: { - auto *CE = cast(Parent); - assert(hasImplicitSingleExpressionReturn(CE->getBody())); - implicitSingleExpressionReturn = true; - SmallVector candidates; - collectPossibleReturnTypesFromContext(CE, candidates); - for (auto ty : candidates) - recordPossibleType(ty); - break; - } - default: - llvm_unreachable("Unhandled expression kind."); - } - } - - void analyzeStmt(Stmt *Parent) { - switch (Parent->getKind()) { - case StmtKind::Return: { - SmallVector candidates; - collectPossibleReturnTypesFromContext(DC, candidates); - for (auto ty : candidates) - recordPossibleType(ty); - break; - } - case StmtKind::ForEach: - if (auto SEQ = cast(Parent)->getParsedSequence()) { - if (containsTarget(SEQ)) { - recordPossibleType(Context.getSequenceType()); - } - } - break; - case StmtKind::RepeatWhile: - case StmtKind::If: - case StmtKind::While: - case StmtKind::Guard: - if (isBoolConditionOf(Parent)) { - recordPossibleType(Context.getBoolType()); - } - break; - default: - llvm_unreachable("Unhandled statement kind."); - } - } - - bool isBoolConditionOf(Stmt *parent) { - if (auto *repeat = dyn_cast(parent)) { - return repeat->getCond() && containsTarget(repeat->getCond()); - } - if (auto *conditional = dyn_cast(parent)) { - for (StmtConditionElement cond : conditional->getCond()) { - if (auto *E = cond.getBooleanOrNull()) { - if (containsTarget(E)) { - return true; - } - } - } - } - return false; - } - - bool containsTarget(Expr *E) { - assert(E && "expected parent expression"); - return SM.rangeContains(E->getSourceRange(), ParsedExpr->getSourceRange()); - } - - void analyzeDecl(Decl *D) { - switch (D->getKind()) { - case DeclKind::PatternBinding: { - auto PBD = cast(D); - for (unsigned I : range(PBD->getNumPatternEntries())) { - if (auto Init = PBD->getInit(I)) { - if (containsTarget(Init)) { - if (PBD->getPattern(I)->hasType()) { - recordPossibleType(PBD->getPattern(I)->getType()); - break; - } - } - } - } - break; - } - default: - if (auto *FD = dyn_cast(D)) { - assert(hasImplicitSingleExpressionReturn(FD->getBody())); - implicitSingleExpressionReturn = true; - SmallVector candidates; - collectPossibleReturnTypesFromContext(DC, candidates); - for (auto ty : candidates) - recordPossibleType(ty); - break; - } - llvm_unreachable("Unhandled decl kind."); - } - } - - void analyzePattern(Pattern *P) { - switch (P->getKind()) { - case PatternKind::Expr: { - auto ExprPat = cast(P); - if (!ExprPat->isResolved()) - break; - - auto D = ExprPat->getMatchVar(); - if (!D || !D->hasInterfaceType()) - break; - - auto *DC = D->getDeclContext(); - recordPossibleType(DC->mapTypeIntoContext(D->getInterfaceType())); - break; - } - default: - llvm_unreachable("Unhandled pattern kind."); - } - } - - void analyzeInitializer(Initializer *initDC) { - switch (initDC->getInitializerKind()) { - case swift::InitializerKind::PatternBinding: { - auto initDC = cast(DC); - auto PBD = initDC->getBinding(); - if (!PBD) - break; - auto pat = PBD->getPattern(initDC->getBindingIndex()); - if (pat->hasType()) - recordPossibleType(pat->getType()); - break; - } - case InitializerKind::DefaultArgument: { - auto initDC = cast(DC); - auto AFD = dyn_cast(initDC->getParent()); - if (!AFD) - return; - auto param = AFD->getParameters()->get(initDC->getIndex()); - recordPossibleType(AFD->mapTypeIntoContext(param->getInterfaceType())); - break; - } - case InitializerKind::PropertyWrapper: { - auto initDC = cast(DC); - auto AFD = dyn_cast(initDC->getParent()); - if (!AFD) - return; - auto *var = initDC->getWrappedVar(); - recordPossibleType(AFD->mapTypeIntoContext(var->getInterfaceType())); - break; - } - } - } - - /// Whether the given \c BraceStmt, which must be the body of a function or - /// closure, contains a single expression that would be implicitly returned if - /// the single-expression-body transform had been performed. - /// - /// We cannot use hasSingleExpressionBody, because we explicitly do not use - /// the single-expression-body transform when there is a code-completion in - /// the expression in order to avoid a base expression affecting the type, and - /// need to distinguish whether the single expression body was explicitly - /// returned (in which case the expression's type *must* match the expected - /// return type) or not (in which case it *may* match, as the user could intend - /// it only as the first statement of many that they haven't finished writing - /// yet. - static bool hasImplicitSingleExpressionReturn(BraceStmt *body) { - if (body->getNumElements() == 2) { - if (auto *D = body->getFirstElement().dyn_cast()) { - // Step into nested active clause. - while (auto *ICD = dyn_cast(D)) { - auto ACE = ICD->getActiveClauseElements(); - if (ACE.size() == 1) { - return body->getLastElement().is(); - } else if (ACE.size() == 2) { - if (auto *ND = ACE.front().dyn_cast()) { - D = ND; - continue; - } - } - break; - } - } - } - return body->getNumElements() == 1 && body->getLastElement().is(); - } - -public: - ExprContextAnalyzer( - DeclContext *DC, Expr *ParsedExpr, SmallVectorImpl &PossibleTypes, - SmallVectorImpl &PossibleArgs, - SmallVectorImpl &PossibleCallees, - Expr *&AnalyzedExpr, bool &implicitSingleExpressionReturn) - : DC(DC), ParsedExpr(ParsedExpr), SM(DC->getASTContext().SourceMgr), - Context(DC->getASTContext()), PossibleTypes(PossibleTypes), - PossibleParams(PossibleArgs), PossibleCallees(PossibleCallees), - AnalyzedExpr(AnalyzedExpr), - implicitSingleExpressionReturn(implicitSingleExpressionReturn) {} - - void Analyze() { - // We cannot analyze without target. - if (!ParsedExpr) - return; - - ExprParentFinder Finder(ParsedExpr, [&](ASTWalker::ParentTy Node, - ASTWalker::ParentTy Parent) { - if (auto E = Node.getAsExpr()) { - switch (E->getKind()) { - case ExprKind::Call: { - // Iff the cursor is in argument position. - auto call = cast(E); - auto fnRange = call->getFn()->getSourceRange(); - auto argsRange = call->getArgs()->getSourceRange(); - auto exprRange = ParsedExpr->getSourceRange(); - return !SM.rangeContains(fnRange, exprRange) && - SM.rangeContains(argsRange, exprRange); - } - case ExprKind::Subscript: { - // Iff the cursor is in index position. - auto argsRange = cast(E)->getArgs()->getSourceRange(); - return SM.rangeContains(argsRange, ParsedExpr->getSourceRange()); - } - case ExprKind::Binary: - case ExprKind::PrefixUnary: - case ExprKind::Assign: - case ExprKind::Dictionary: - case ExprKind::Ternary: - return true; - case ExprKind::Array: - return (!Parent.getAsExpr() || - !isa(Parent.getAsExpr())); - case ExprKind::Tuple: { - auto ParentE = Parent.getAsExpr(); - return !ParentE || - (!isa(ParentE) && !isa(ParentE) && - !isa(ParentE)); - } - case ExprKind::Closure: - return hasImplicitSingleExpressionReturn( - cast(E)->getBody()); - default: - return false; - } - } else if (auto S = Node.getAsStmt()) { - switch (S->getKind()) { - case StmtKind::Return: - case StmtKind::ForEach: - case StmtKind::RepeatWhile: - case StmtKind::If: - case StmtKind::While: - case StmtKind::Guard: - return true; - default: - return false; - } - } else if (auto D = Node.getAsDecl()) { - switch (D->getKind()) { - case DeclKind::PatternBinding: - return true; - default: - if (auto *FD = dyn_cast(D)) - if (auto *body = FD->getBody()) - return hasImplicitSingleExpressionReturn(body); - return false; - } - } else if (auto P = Node.getAsPattern()) { - switch (P->getKind()) { - case PatternKind::Expr: - return true; - default: - return false; - } - } else - return false; - }); - - // For 'Initializer' context, we need to look into its parent. - auto analyzeDC = isa(DC) ? DC->getParent() : DC; - analyzeDC->walkContext(Finder); - - if (Finder.Ancestors.empty()) { - // There's no parent context in DC. But still, the parent of the - // initializer might constrain the initializer's type. - if (auto initDC = dyn_cast(DC)) - analyzeInitializer(initDC); - return; - } - - auto &P = Finder.Ancestors.back(); - if (auto Parent = P.getAsExpr()) { - analyzeExpr(Parent); - } else if (auto Parent = P.getAsStmt()) { - analyzeStmt(Parent); - } else if (auto Parent = P.getAsDecl()) { - analyzeDecl(Parent); - } else if (auto Parent = P.getAsPattern()) { - analyzePattern(Parent); - } - } -}; - -} // end anonymous namespace - -ExprContextInfo::ExprContextInfo(DeclContext *DC, Expr *TargetExpr) { - ExprContextAnalyzer Analyzer(DC, TargetExpr, PossibleTypes, PossibleParams, - PossibleCallees, AnalyzedExpr, - implicitSingleExpressionReturn); - Analyzer.Analyze(); -} diff --git a/lib/IDE/ExprContextAnalysis.h b/lib/IDE/ExprContextAnalysis.h index 7688e64612e0a..f8256e3d7936c 100644 --- a/lib/IDE/ExprContextAnalysis.h +++ b/lib/IDE/ExprContextAnalysis.h @@ -37,13 +37,6 @@ void typeCheckContextAt(TypeCheckASTNodeAtLocContext TypeCheckCtx, /// exact the same as \p TargetRange. Returns \c nullptr if not found. Expr *findParsedExpr(const DeclContext *DC, SourceRange TargetRange); -/// Remove \c CodeCompletionExpr from \p expr . Returns \c true if it actually -/// mutated the expression. -/// -/// NOTE: Currently, this only removes CodeCompletionExpr at call argument -/// position. -bool removeCodeCompletionExpr(ASTContext &Ctx, Expr *&expr); - /// Collects possible expected return types of the given decl context. /// \p DC should be an \c AbstractFunctionDecl or an \c AbstractClosureExpr. void collectPossibleReturnTypesFromContext(DeclContext *DC, @@ -61,47 +54,6 @@ struct FunctionTypeAndDecl { : Type(Type), Decl(Decl), SemanticContext(SemanticContext) {} }; -/// Given an expression and its decl context, the analyzer tries to figure out -/// the expected type of the expression by analyzing its context. -class ExprContextInfo { - SmallVector PossibleTypes; - SmallVector PossibleParams; - SmallVector PossibleCallees; - Expr *AnalyzedExpr = nullptr; - bool implicitSingleExpressionReturn = false; - -public: - ExprContextInfo(DeclContext *DC, Expr *TargetExpr); - - // Returns a list of possible context types. - ArrayRef getPossibleTypes() const { return PossibleTypes; } - - /// Whether the type context comes from a single-expression body without - /// and explicit return e.g. `foo({ })` and not foo({ return }). - /// - /// Since the input may be incomplete, such as in code-completion, take into - /// account that the types returned by `getPossibleTypes()` are only a hint. - bool isImplicitSingleExpressionReturn() const { - return implicitSingleExpressionReturn; - } - - // Returns a list of possible argument label names. - // Valid only if \c getKind() is \c CallArgument. - ArrayRef getPossibleParams() const { - return PossibleParams; - } - - // Returns a list of possible callee - // Valid only if \c getKind() is \c CallArgument. - ArrayRef getPossibleCallees() const { - return PossibleCallees; - } - - Expr *getAnalyzedExpr() const { - return AnalyzedExpr; - } -}; - } // namespace ide } // namespace swift diff --git a/lib/IDE/Formatting.cpp b/lib/IDE/Formatting.cpp index 320ad64b35a40..628021fe2195f 100644 --- a/lib/IDE/Formatting.cpp +++ b/lib/IDE/Formatting.cpp @@ -2059,12 +2059,11 @@ class FormatWalker : public ASTWalker { } llvm::Optional - getIndentContextFromInherits(ArrayRef Inherits, - SourceLoc ContextLoc) { + getIndentContextFromInherits(InheritedTypes Inherits, SourceLoc ContextLoc) { if (Inherits.empty()) return llvm::None; - SourceLoc StartLoc = Inherits.front().getSourceRange().Start; + SourceLoc StartLoc = Inherits.getStartLoc(); if (StartLoc.isInvalid()) return llvm::None; @@ -2074,7 +2073,7 @@ class FormatWalker : public ASTWalker { assert(ColonLoc.has_value() && "inherits list without leading colon?"); ListAligner Aligner(SM, TargetLocation, ContextLoc, ColonLoc->getLoc()); - for (auto TL: Inherits) + for (auto TL : Inherits.getEntries()) Aligner.updateAlignment(TL.getSourceRange(), TL.getTypeRepr()); return Aligner.getContextAndSetAlignment(CtxOverride); } diff --git a/lib/IDE/KeyPathCompletion.cpp b/lib/IDE/KeyPathCompletion.cpp index 1588bfbf837bc..029250dde8a70 100644 --- a/lib/IDE/KeyPathCompletion.cpp +++ b/lib/IDE/KeyPathCompletion.cpp @@ -73,10 +73,9 @@ void KeyPathTypeCheckCompletionCallback::sawSolutionImpl( Results.push_back({BaseType, /*OnRoot=*/(ComponentIndex == 0)}); } -void KeyPathTypeCheckCompletionCallback::deliverResults( +void KeyPathTypeCheckCompletionCallback::collectResults( DeclContext *DC, SourceLoc DotLoc, - ide::CodeCompletionContext &CompletionCtx, - CodeCompletionConsumer &Consumer) { + ide::CodeCompletionContext &CompletionCtx) { ASTContext &Ctx = DC->getASTContext(); CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC, &CompletionCtx); @@ -91,5 +90,6 @@ void KeyPathTypeCheckCompletionCallback::deliverResults( Lookup.getValueExprCompletions(Result.BaseType); } - deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer); + collectCompletionResults(CompletionCtx, Lookup, DC, ExpectedTypeContext(), + /*CanCurrDeclContextHandleAsync=*/false); } diff --git a/lib/IDE/PostfixCompletion.cpp b/lib/IDE/PostfixCompletion.cpp index e7bf5acc46a20..9ff2031d08959 100644 --- a/lib/IDE/PostfixCompletion.cpp +++ b/lib/IDE/PostfixCompletion.cpp @@ -394,10 +394,9 @@ static void addOperatorResults(Type LHSType, ArrayRef Operators, } } -void PostfixCompletionCallback::deliverResults( +void PostfixCompletionCallback::collectResults( SourceLoc DotLoc, bool IsInSelector, bool IncludeOperators, - bool HasLeadingSpace, CodeCompletionContext &CompletionCtx, - CodeCompletionConsumer &Consumer) { + bool HasLeadingSpace, CodeCompletionContext &CompletionCtx) { ASTContext &Ctx = DC->getASTContext(); CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC, &CompletionCtx); @@ -427,12 +426,25 @@ void PostfixCompletionCallback::deliverResults( Lookup.collectOperators(Operators); } + // The type context that is being used for global results. + ExpectedTypeContext UnifiedTypeContext; + UnifiedTypeContext.setPreferNonVoid(true); + bool UnifiedCanHandleAsync = false; + + // The base types of the result for which we already returned results. + // Used so we only return keyword and operator completions once for each base + // type. + llvm::SmallPtrSet ProcessedBaseTypes; + Lookup.shouldCheckForDuplicates(Results.size() > 1); + for (auto &Result : Results) { Lookup.setCanCurrDeclContextHandleAsync(Result.IsInAsyncContext); Lookup.setClosureActorIsolations(Result.ClosureActorIsolations); Lookup.setIsStaticMetatype(Result.BaseIsStaticMetaType); - Lookup.getPostfixKeywordCompletions(Result.BaseTy, BaseExpr); + if (!ProcessedBaseTypes.contains(Result.BaseTy)) { + Lookup.getPostfixKeywordCompletions(Result.BaseTy, BaseExpr); + } Lookup.setExpectedTypes(Result.ExpectedTypes, Result.IsImplicitSingleExpressionReturn, Result.ExpectsNonVoid); @@ -441,10 +453,21 @@ void PostfixCompletionCallback::deliverResults( Lookup.getValueExprCompletions(Result.BaseTy, Result.BaseDecl, Result.IsBaseDeclUnapplied); - if (IncludeOperators && !Result.BaseIsStaticMetaType) { + // `==`, `<=` etc can be used on `Void` because `Void` is just an empty + // tuple. But that doesn’t really make sense so we shouldn't be suggesting + // any operators based on `Void`. + if (IncludeOperators && !Result.BaseIsStaticMetaType && + !Result.BaseTy->isVoid() && + !ProcessedBaseTypes.contains(Result.BaseTy)) { addOperatorResults(Result.BaseTy, Operators, DC, Lookup); } + + UnifiedTypeContext.merge(*Lookup.getExpectedTypeContext()); + UnifiedCanHandleAsync |= Result.IsInAsyncContext; + + ProcessedBaseTypes.insert(Result.BaseTy); } - deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer); + collectCompletionResults(CompletionCtx, Lookup, DC, UnifiedTypeContext, + UnifiedCanHandleAsync); } diff --git a/lib/IDE/REPLCodeCompletion.cpp b/lib/IDE/REPLCodeCompletion.cpp index 4e79117039190..b134bcfcea99f 100644 --- a/lib/IDE/REPLCodeCompletion.cpp +++ b/lib/IDE/REPLCodeCompletion.cpp @@ -174,7 +174,7 @@ static void toDisplayString(CodeCompletionResult *Result, } namespace swift { -class REPLCodeCompletionConsumer : public SimpleCachingCodeCompletionConsumer { +class REPLCodeCompletionConsumer : public CodeCompletionConsumer { REPLCompletions &Completions; public: diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp index dd9656aba68fc..8d3e606e43c3e 100644 --- a/lib/IDE/SyntaxModel.cpp +++ b/lib/IDE/SyntaxModel.cpp @@ -917,7 +917,7 @@ ASTWalker::PreWalkAction ModelASTWalker::walkToDeclPre(Decl *D) { SourceLoc NREnd = NRStart.getAdvancedLoc(NTD->getName().getLength()); SN.NameRange = CharSourceRange(SM, NRStart, NREnd); - for (const TypeLoc &TL : NTD->getInherited()) { + for (const TypeLoc &TL : NTD->getInherited().getEntries()) { CharSourceRange TR = charSourceRangeFromSourceRange(SM, TL.getSourceRange()); SN.InheritedTypeRanges.push_back(TR); @@ -937,7 +937,7 @@ ASTWalker::PreWalkAction ModelASTWalker::walkToDeclPre(Decl *D) { NSR = repr->getSourceRange(); SN.NameRange = charSourceRangeFromSourceRange(SM, NSR); - for (const TypeLoc &TL : ED->getInherited()) { + for (const TypeLoc &TL : ED->getInherited().getEntries()) { CharSourceRange TR = charSourceRangeFromSourceRange(SM, TL.getSourceRange()); SN.InheritedTypeRanges.push_back(TR); @@ -1116,7 +1116,7 @@ ASTWalker::PreWalkAction ModelASTWalker::walkToDeclPre(Decl *D) { GenericParamD->getSourceRange()); SN.NameRange = CharSourceRange(GenericParamD->getNameLoc(), GenericParamD->getName().getLength()); - for (const TypeLoc &TL : GenericParamD->getInherited()) { + for (const TypeLoc &TL : GenericParamD->getInherited().getEntries()) { CharSourceRange TR = charSourceRangeFromSourceRange(SM, TL.getSourceRange()); SN.InheritedTypeRanges.push_back(TR); diff --git a/lib/IDE/UnresolvedMemberCompletion.cpp b/lib/IDE/UnresolvedMemberCompletion.cpp index 2006ec7d63e73..3c35d9da55054 100644 --- a/lib/IDE/UnresolvedMemberCompletion.cpp +++ b/lib/IDE/UnresolvedMemberCompletion.cpp @@ -88,10 +88,9 @@ void UnresolvedMemberTypeCheckCompletionCallback::sawSolutionImpl( } } -void UnresolvedMemberTypeCheckCompletionCallback::deliverResults( +void UnresolvedMemberTypeCheckCompletionCallback::collectResults( DeclContext *DC, SourceLoc DotLoc, - ide::CodeCompletionContext &CompletionCtx, - CodeCompletionConsumer &Consumer) { + ide::CodeCompletionContext &CompletionCtx) { ASTContext &Ctx = DC->getASTContext(); CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC, &CompletionCtx); @@ -125,6 +124,11 @@ void UnresolvedMemberTypeCheckCompletionCallback::deliverResults( Lookup.getUnresolvedMemberCompletions(Result.ExpectedTy); } + // The type context that is being used for global results. + ExpectedTypeContext UnifiedTypeContext; + UnifiedTypeContext.setPreferNonVoid(true); + bool UnifiedCanHandleAsync = false; + // Offer completions when interpreting the pattern match as an // EnumElementPattern. for (auto &Result : EnumPatternTypes) { @@ -141,7 +145,11 @@ void UnresolvedMemberTypeCheckCompletionCallback::deliverResults( } Lookup.getEnumElementPatternCompletions(Ty); + + UnifiedTypeContext.merge(*Lookup.getExpectedTypeContext()); + UnifiedCanHandleAsync |= Result.IsInAsyncContext; } - deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer); + collectCompletionResults(CompletionCtx, Lookup, DC, UnifiedTypeContext, + UnifiedCanHandleAsync); } diff --git a/lib/IDETool/IDEInspectionInstance.cpp b/lib/IDETool/IDEInspectionInstance.cpp index 2bf86fea6450f..1785fc6b43d90 100644 --- a/lib/IDETool/IDEInspectionInstance.cpp +++ b/lib/IDETool/IDEInspectionInstance.cpp @@ -594,8 +594,7 @@ void swift::ide::IDEInspectionInstance::codeComplete( llvm::function_ref)> Callback) { using ResultType = CancellableResult; - struct ConsumerToCallbackAdapter - : public SimpleCachingCodeCompletionConsumer { + struct ConsumerToCallbackAdapter : public CodeCompletionConsumer { SwiftCompletionInfo SwiftContext; ImportDepth ImportDep; std::shared_ptr> CancellationFlag; diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp index d3d0d40e64e80..618e027c64520 100644 --- a/lib/IRGen/GenClass.cpp +++ b/lib/IRGen/GenClass.cpp @@ -1075,8 +1075,10 @@ void IRGenModule::emitClassDecl(ClassDecl *D) { assert(!IRGen.hasLazyMetadata(D)); // Emit the class metadata. - emitClassMetadata(*this, D, fragileLayout, resilientLayout); - emitFieldDescriptor(D); + if (!D->getASTContext().LangOpts.hasFeature(Feature::Embedded)) { + emitClassMetadata(*this, D, fragileLayout, resilientLayout); + emitFieldDescriptor(D); + } IRGen.addClassForEagerInitialization(D); IRGen.addBackDeployedObjCActorInitialization(D); diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index bfbaf62f14b53..12a8561e46015 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -536,7 +536,7 @@ void IRGenModule::emitSourceFile(SourceFile &SF) { // libraries. This may however cause the library to get pulled in in // situations where it isn't useful, such as for dylibs, though this is // harmless aside from code size. - if (!IRGen.Opts.UseJIT) { + if (!IRGen.Opts.UseJIT && !Context.LangOpts.hasFeature(Feature::Embedded)) { auto addBackDeployLib = [&](llvm::VersionTuple version, StringRef libraryName, bool forceLoad) { llvm::Optional compatibilityVersion; @@ -1239,6 +1239,13 @@ void IRGenModule::emitGlobalLists() { // Eagerly emit functions that are externally visible. Functions that are // dynamic replacements must also be eagerly emitted. static bool isLazilyEmittedFunction(SILFunction &f, SILModule &m) { + // Embedded Swift only emits specialized function, so don't emit genreic + // functions, even if they're externally visible. + if (f.getASTContext().LangOpts.hasFeature(Feature::Embedded) && + f.getLoweredFunctionType()->getSubstGenericSignature()) { + return true; + } + if (f.isPossiblyUsedExternally()) return false; @@ -1403,6 +1410,17 @@ deleteAndReenqueueForEmissionValuesDependentOnCanonicalPrespecializedMetadataRec /// Emit any lazy definitions (of globals or functions or whatever /// else) that we require. void IRGenerator::emitLazyDefinitions() { + if (SIL.getASTContext().LangOpts.hasFeature(Feature::Embedded)) { + // In embedded Swift, the compiler cannot emit any metadata, etc. + LazyTypeMetadata.clear(); + LazySpecializedTypeMetadataRecords.clear(); + LazyTypeContextDescriptors.clear(); + LazyOpaqueTypeDescriptors.clear(); + LazyCanonicalSpecializedMetadataAccessors.clear(); + LazyMetadataAccessors.clear(); + LazyWitnessTables.clear(); + } + while (!LazyTypeMetadata.empty() || !LazySpecializedTypeMetadataRecords.empty() || !LazyTypeContextDescriptors.empty() || diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp index b271e81e87b71..fed0dafd993cd 100644 --- a/lib/IRGen/GenEnum.cpp +++ b/lib/IRGen/GenEnum.cpp @@ -7158,7 +7158,8 @@ const TypeInfo *TypeConverter::convertEnumType(TypeBase *key, CanType type, } void IRGenModule::emitEnumDecl(EnumDecl *theEnum) { - if (!IRGen.hasLazyMetadata(theEnum)) { + if (!IRGen.hasLazyMetadata(theEnum) && + !theEnum->getASTContext().LangOpts.hasFeature(Feature::Embedded)) { emitEnumMetadata(*this, theEnum); emitFieldDescriptor(theEnum); } diff --git a/lib/IRGen/GenExistential.cpp b/lib/IRGen/GenExistential.cpp index decd069a2b5f9..9b3d633bdddab 100644 --- a/lib/IRGen/GenExistential.cpp +++ b/lib/IRGen/GenExistential.cpp @@ -1780,6 +1780,11 @@ static void forEachProtocolWitnessTable( assert(protocols.size() == witnessConformances.size() && "mismatched protocol conformances"); + // Don't emit witness tables in embedded Swift. + if (srcType->getASTContext().LangOpts.hasFeature(Feature::Embedded)) { + return; + } + for (unsigned i = 0, e = protocols.size(); i < e; ++i) { assert(protocols[i] == witnessConformances[i].getRequirement()); auto table = emitWitnessTableRef(IGF, srcType, srcMetadataCache, diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index bda693170b7de..6efb2e6496dc4 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -2568,6 +2568,10 @@ static void eraseExistingTypeContextDescriptor(IRGenModule &IGM, void irgen::emitLazyTypeContextDescriptor(IRGenModule &IGM, NominalTypeDecl *type, RequireMetadata_t requireMetadata) { + if (type->getASTContext().LangOpts.hasFeature(Feature::Embedded)) { + return; + } + eraseExistingTypeContextDescriptor(IGM, type); bool hasLayoutString = false; @@ -6466,6 +6470,10 @@ SpecialProtocol irgen::getSpecialProtocolID(ProtocolDecl *P) { void IRGenModule::emitProtocolDecl(ProtocolDecl *protocol) { PrettyStackTraceDecl stackTraceRAII("emitting metadata for", protocol); + if (protocol->getASTContext().LangOpts.hasFeature(Feature::Embedded)) { + return; + } + // Marker protocols are never emitted. if (protocol->isMarkerProtocol()) return; diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index f02ec5abde6d0..96d7ae25b8402 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -2394,6 +2394,10 @@ static void addWTableTypeMetadata(IRGenModule &IGM, } void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) { + if (Context.LangOpts.hasFeature(Feature::Embedded)) { + return; + } + // Don't emit a witness table if it is a declaration. if (wt->isDeclaration()) return; @@ -3353,6 +3357,8 @@ llvm::Value *irgen::emitWitnessTableRef(IRGenFunction &IGF, CanType srcType, llvm::Value **srcMetadataCache, ProtocolConformanceRef conformance) { + assert(!srcType->getASTContext().LangOpts.hasFeature(Feature::Embedded)); + auto proto = conformance.getRequirement(); assert(Lowering::TypeConverter::protocolRequiresWitnessTable(proto) && "protocol does not have witness tables?!"); diff --git a/lib/IRGen/GenStruct.cpp b/lib/IRGen/GenStruct.cpp index cc2828d841a3a..a5f8cf070c1c0 100644 --- a/lib/IRGen/GenStruct.cpp +++ b/lib/IRGen/GenStruct.cpp @@ -1597,7 +1597,8 @@ const TypeInfo *irgen::getPhysicalStructFieldTypeInfo(IRGenModule &IGM, } void IRGenModule::emitStructDecl(StructDecl *st) { - if (!IRGen.hasLazyMetadata(st)) { + if (!IRGen.hasLazyMetadata(st) && + !st->getASTContext().LangOpts.hasFeature(Feature::Embedded)) { emitStructMetadata(*this, st); emitFieldDescriptor(st); } diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index af24749ba30b2..7e3961b28986a 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -2469,6 +2469,19 @@ IRGenDebugInfoImpl::emitFunction(const SILDebugScope *DS, llvm::Function *Fn, /*IsLocalToUnit=*/Fn ? Fn->hasInternalLinkage() : true, /*IsDefinition=*/true, /*IsOptimized=*/Opts.shouldOptimize()); + // When the function is a method, we want a DW_AT_declaration there. + // Because there's no good way to cross the CU boundary to insert a nested + // DISubprogram definition in one CU into a type defined in another CU when + // doing LTO builds. + if (Rep == SILFunctionTypeRepresentation::Method) { + llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::toSPFlags( + /*IsLocalToUnit=*/Fn ? Fn->hasInternalLinkage() : true, + /*IsDefinition=*/false, /*IsOptimized=*/Opts.shouldOptimize()); + Decl = DBuilder.createMethod(Scope, Name, LinkageName, File, Line, DIFnTy, + 0, 0, nullptr, Flags, SPFlags, + TemplateParameters, Error); + } + // Construct the DISubprogram. llvm::DISubprogram *SP = DBuilder.createFunction( Scope, Name, LinkageName, File, Line, DIFnTy, ScopeLine, Flags, SPFlags, diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index b4baad8635b1d..19a462eb89f5e 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -2017,7 +2017,7 @@ const llvm::StringRef IRGenerator::getClangDataLayoutString() { } TypeExpansionContext IRGenModule::getMaximalTypeExpansionContext() const { - return TypeExpansionContext::maximal(getSwiftModule(), + return TypeExpansionContext::maximal(getSILModule().getAssociatedContext(), getSILModule().isWholeModule()); } diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index 805a1399b1d99..addf23a14ee24 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -3303,6 +3303,12 @@ llvm::Value *IRGenFunction::emitTypeMetadataRef(CanType type) { MetadataResponse IRGenFunction::emitTypeMetadataRef(CanType type, DynamicMetadataRequest request) { + if (type->getASTContext().LangOpts.hasFeature(Feature::Embedded)) { + llvm::errs() << "Metadata pointer requested in embedded Swift for type " + << type << "\n"; + assert(0 && "metadata used in embedded mode"); + } + type = IGM.getRuntimeReifiedType(type); // Look through any opaque types we're allowed to. type = IGM.substOpaqueTypesWithUnderlyingTypes(type); diff --git a/lib/Index/Index.cpp b/lib/Index/Index.cpp index e07abe3b6f891..dd37e3acb27ee 100644 --- a/lib/Index/Index.cpp +++ b/lib/Index/Index.cpp @@ -974,8 +974,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker { /// \param Loc The location of the reference, otherwise the location of the TypeLoc is used. bool reportRelatedTypeRef(const TypeLoc &Ty, SymbolRoleSet Relations, Decl *Related, bool isImplicit=false, SourceLoc Loc={}); - bool reportInheritedTypeRefs( - ArrayRef Inherited, Decl *Inheritee); + bool reportInheritedTypeRefs(InheritedTypes Inherited, Decl *Inheritee); bool reportPseudoGetterDecl(VarDecl *D) { return reportPseudoAccessor(D, AccessorKind::Get, /*IsRef=*/false, @@ -1073,7 +1072,7 @@ class IndexSwiftASTWalker : public SourceEntityWalker { if (shouldIndex(VD, /*IsRef=*/false)) return true; - for (auto Inherit : D->getInherited()) + for (auto Inherit : D->getInherited().getEntries()) if (auto T = Inherit.getType()) if (T->getAnyNominal() && shouldIndex(T->getAnyNominal(), /*IsRef=*/false)) @@ -1384,8 +1383,9 @@ bool IndexSwiftASTWalker::reportRelatedRef(ValueDecl *D, SourceLoc Loc, bool isI return !Cancelled; } -bool IndexSwiftASTWalker::reportInheritedTypeRefs(ArrayRef Inherited, Decl *Inheritee) { - for (auto Base : Inherited) { +bool IndexSwiftASTWalker::reportInheritedTypeRefs(InheritedTypes Inherited, + Decl *Inheritee) { + for (auto Base : Inherited.getEntries()) { if (!reportRelatedTypeRef(Base, (SymbolRoleSet) SymbolRole::RelationBaseOf, Inheritee)) return false; } diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 62985a9c44aa0..3d8f52957ebe7 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -3336,38 +3336,8 @@ Parser::parseTrailingClosures(bool isExprBasic, SourceRange calleeRange, // Parse labeled trailing closures. while (true) { if (!isStartOfLabelledTrailingClosure(*this)) { - if (!Tok.is(tok::code_complete)) - break; - - // FIXME: Additional trailing closure completion on newline positions. - // let foo = SomeThing { - // ... - // } - // - // This was previously enabled, but it failed to suggest 'foo' because - // the token was considered a part of the initializer. - if (Tok.isAtStartOfLine()) - break; - - // If the current completion mode doesn't support trailing closure - // completion, leave the token here and let "postfix completion" to - // handle it. - if (CodeCompletionCallbacks && - !CodeCompletionCallbacks->canPerformCompleteLabeledTrailingClosure()) - break; - - // foo() {} - auto CCExpr = new (Context) CodeCompletionExpr(Tok.getLoc()); - if (CodeCompletionCallbacks) { - CodeCompletionCallbacks->completeLabeledTrailingClosure( - CCExpr, Tok.isAtStartOfLine()); - } - consumeToken(tok::code_complete); - result.setHasCodeCompletionAndIsError(); - closures.emplace_back(SourceLoc(), Identifier(), CCExpr); - continue; + break; } - Identifier label; auto labelLoc = consumeArgumentLabel(label, /*diagnoseDollarPrefix=*/false); consumeToken(tok::colon); diff --git a/lib/Refactoring/Refactoring.cpp b/lib/Refactoring/Refactoring.cpp index bcf4d4f7c16f5..5b471cdaa4305 100644 --- a/lib/Refactoring/Refactoring.cpp +++ b/lib/Refactoring/Refactoring.cpp @@ -3539,7 +3539,7 @@ class AddEquatableContext { AddEquatableContext(NominalTypeDecl *Decl) : DC(Decl), Adopter(Decl->getDeclaredType()), StartLoc(Decl->getBraces().Start), - ProtocolsLocations(Decl->getInherited()), + ProtocolsLocations(Decl->getInherited().getEntries()), Protocols(getAllProtocols(Decl)), ProtInsertStartLoc(Decl->getNameLoc()), StoredProperties(Decl->getStoredProperties()), @@ -3548,7 +3548,7 @@ class AddEquatableContext { AddEquatableContext(ExtensionDecl *Decl) : DC(Decl), Adopter(Decl->getExtendedType()), StartLoc(Decl->getBraces().Start), - ProtocolsLocations(Decl->getInherited()), + ProtocolsLocations(Decl->getInherited().getEntries()), Protocols(getAllProtocols(Decl->getExtendedNominal())), ProtInsertStartLoc(Decl->getExtendedTypeRepr()->getEndLoc()), StoredProperties(Decl->getExtendedNominal()->getStoredProperties()), diff --git a/lib/SIL/IR/Linker.cpp b/lib/SIL/IR/Linker.cpp index c5b1b3e20d19f..8337dce56183e 100644 --- a/lib/SIL/IR/Linker.cpp +++ b/lib/SIL/IR/Linker.cpp @@ -120,7 +120,8 @@ void SILLinkerVisitor::maybeAddFunctionToWorklist(SILFunction *F, return; } - // In the performance pipeline, we deserialize all reachable functions. + // In the performance pipeline or embedded mode, we deserialize all reachable + // functions. if (isLinkAll()) return deserializeAndPushToWorklist(F); @@ -435,6 +436,11 @@ void SILLinkerVisitor::process() { Fn->setSerialized(IsSerialized_t::IsNotSerialized); } + // TODO: This should probably be done as a separate SIL pass ("internalize") + if (Fn->getModule().getASTContext().LangOpts.hasFeature(Feature::Embedded)) { + Fn->setLinkage(stripExternalFromLinkage(Fn->getLinkage())); + } + LLVM_DEBUG(llvm::dbgs() << "Process imports in function: " << Fn->getName() << "\n"); diff --git a/lib/SIL/IR/Linker.h b/lib/SIL/IR/Linker.h index 8e9b12af3888b..31265f79fbe77 100644 --- a/lib/SIL/IR/Linker.h +++ b/lib/SIL/IR/Linker.h @@ -142,7 +142,10 @@ class SILLinkerVisitor : public SILInstructionVisitor { /// Is the current mode link all? Link all implies we should try and link /// everything, not just transparent/shared functions. - bool isLinkAll() const { return Mode == LinkingMode::LinkAll; } + bool isLinkAll() const { + return Mode == LinkingMode::LinkAll || + Mod.getASTContext().LangOpts.hasFeature(Feature::Embedded); + } void linkInVTable(ClassDecl *D); diff --git a/lib/SIL/IR/SILModule.cpp b/lib/SIL/IR/SILModule.cpp index d3c107917bdf6..34ed2ae3d308b 100644 --- a/lib/SIL/IR/SILModule.cpp +++ b/lib/SIL/IR/SILModule.cpp @@ -898,6 +898,10 @@ void SILModule::performOnceForPrespecializedImportedExtensions( if (prespecializedFunctionDeclsImported) return; + // No prespecitalizations in embedded Swift + if (getASTContext().LangOpts.hasFeature(Feature::Embedded)) + return; + SmallVector importedModules; // Add the Swift module. if (!isStdlibModule()) { diff --git a/lib/SIL/IR/SILSymbolVisitor.cpp b/lib/SIL/IR/SILSymbolVisitor.cpp index b913316b9cd63..1c25ca91edb64 100644 --- a/lib/SIL/IR/SILSymbolVisitor.cpp +++ b/lib/SIL/IR/SILSymbolVisitor.cpp @@ -601,6 +601,9 @@ class SILSymbolVisitorImpl : public ASTVisitor { if (canSkipNominal(NTD)) return; + if (NTD->getASTContext().LangOpts.hasFeature(Feature::Embedded)) + return; + auto declaredType = NTD->getDeclaredType()->getCanonicalType(); if (!NTD->getObjCImplementationDecl()) { diff --git a/lib/SIL/Utils/InstWrappers.cpp b/lib/SIL/Utils/InstWrappers.cpp index e2bc8b4db5ebc..f638361f33985 100644 --- a/lib/SIL/Utils/InstWrappers.cpp +++ b/lib/SIL/Utils/InstWrappers.cpp @@ -59,14 +59,39 @@ bool ForwardingOperation::hasSameRepresentation() const { } bool ForwardingOperation::isAddressOnly() const { - if (canForwardAllOperands()) { - // All ForwardingInstructions that forward all operands are currently a - // single value instruction. - auto *aggregate = - cast(forwardingInst); - // If any of the operands are address-only, then the aggregate must be. - return aggregate->getType().isAddressOnly(*forwardingInst->getFunction()); + if (auto *singleForwardingOp = getSingleForwardingOperand()) { + return singleForwardingOp->get()->getType().isAddressOnly( + *forwardingInst->getFunction()); } - return forwardingInst->getOperand(0)->getType().isAddressOnly( - *forwardingInst->getFunction()); + // All ForwardingInstructions that forward all operands are currently a + // single value instruction. + auto *aggregate = + cast(forwardingInst); + // If any of the operands are address-only, then the aggregate must be. + return aggregate->getType().isAddressOnly(*forwardingInst->getFunction()); } + +bool ForwardingOperation::visitForwardedValues( + function_ref visitor) { + if (auto *svi = dyn_cast(forwardingInst)) { + return visitor(svi); + } + if (auto *mvri = dyn_cast(forwardingInst)) { + return llvm::all_of(mvri->getResults(), [&](SILValue value) { + if (value->getOwnershipKind() == OwnershipKind::None) + return true; + return visitor(value); + }); + } + auto *ti = cast(forwardingInst); + assert(ti->mayHaveTerminatorResult()); + return llvm::all_of(ti->getSuccessorBlocks(), [&](SILBasicBlock *succBlock) { + // If we do not have any arguments, then continue. + if (succBlock->args_empty()) + return true; + + auto args = succBlock->getSILPhiArguments(); + assert(args.size() == 1 && "Transforming terminator with multiple args?!"); + return visitor(args[0]); + }); +} \ No newline at end of file diff --git a/lib/SIL/Utils/InstructionUtils.cpp b/lib/SIL/Utils/InstructionUtils.cpp index 990cbe0dfb96a..c566bc276dff0 100644 --- a/lib/SIL/Utils/InstructionUtils.cpp +++ b/lib/SIL/Utils/InstructionUtils.cpp @@ -518,10 +518,6 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType) case SILInstructionKind::UncheckedTakeEnumDataAddrInst: case SILInstructionKind::SelectEnumInst: case SILInstructionKind::SelectEnumAddrInst: - case SILInstructionKind::OpenExistentialMetatypeInst: - case SILInstructionKind::OpenExistentialBoxInst: - case SILInstructionKind::OpenExistentialValueInst: - case SILInstructionKind::OpenExistentialBoxValueInst: case SILInstructionKind::ProjectBlockStorageInst: case SILInstructionKind::UnreachableInst: case SILInstructionKind::ReturnInst: @@ -569,6 +565,12 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType) case SILInstructionKind::PackLengthInst: case SILInstructionKind::DebugStepInst: return RuntimeEffect::NoEffect; + + case SILInstructionKind::OpenExistentialMetatypeInst: + case SILInstructionKind::OpenExistentialBoxInst: + case SILInstructionKind::OpenExistentialValueInst: + case SILInstructionKind::OpenExistentialBoxValueInst: + return RuntimeEffect::Existential; case SILInstructionKind::DebugValueInst: // Ignore runtime calls of debug_value @@ -636,10 +638,12 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType) case SILInstructionKind::InitExistentialValueInst: impactType = inst->getOperand(0)->getType(); return RuntimeEffect::Allocating | RuntimeEffect::Releasing | - RuntimeEffect::MetaData; + RuntimeEffect::MetaData | RuntimeEffect::Existential; case SILInstructionKind::InitExistentialRefInst: case SILInstructionKind::InitExistentialMetatypeInst: + impactType = inst->getOperand(0)->getType(); + return RuntimeEffect::MetaData | RuntimeEffect::Existential; case SILInstructionKind::ObjCToThickMetatypeInst: impactType = inst->getOperand(0)->getType(); return RuntimeEffect::MetaData; @@ -655,18 +659,18 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType) case SILInstructionKind::OpenExistentialAddrInst: if (cast(inst)->getAccessKind() == OpenedExistentialAccess::Mutable) - return RuntimeEffect::Allocating; - return RuntimeEffect::NoEffect; + return RuntimeEffect::Allocating | RuntimeEffect::Existential; + return RuntimeEffect::Existential; case SILInstructionKind::OpenExistentialRefInst: { SILType opType = cast(inst)->getOperand()->getType(); impactType = opType; if (opType.getASTType()->isObjCExistentialType()) { - return RuntimeEffect::MetaData; + return RuntimeEffect::MetaData | RuntimeEffect::Existential; } - return RuntimeEffect::MetaData; - // TODO: should be NoEffect - //return RuntimeEffect::NoEffect; + return RuntimeEffect::MetaData | RuntimeEffect::Existential; + // TODO: should be Existential + //return RuntimeEffect::Existential; } case SILInstructionKind::UnconditionalCheckedCastInst: @@ -712,8 +716,11 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType) } return RuntimeEffect::Allocating; } - case SILInstructionKind::AllocBoxInst: case SILInstructionKind::AllocExistentialBoxInst: + impactType = cast(inst)->getType(); + return RuntimeEffect::Allocating | RuntimeEffect::MetaData | + RuntimeEffect::Releasing | RuntimeEffect::Existential; + case SILInstructionKind::AllocBoxInst: case SILInstructionKind::AllocRefInst: case SILInstructionKind::AllocRefDynamicInst: impactType = cast(inst)->getType(); @@ -890,7 +897,7 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType) rt |= RuntimeEffect::ObjectiveC | RuntimeEffect::MetaData; break; case SILFunctionTypeRepresentation::WitnessMethod: - rt |= RuntimeEffect::MetaData; + rt |= RuntimeEffect::MetaData | RuntimeEffect::Existential; break; case SILFunctionTypeRepresentation::CFunctionPointer: case SILFunctionTypeRepresentation::CXXMethod: diff --git a/lib/SIL/Utils/MemAccessUtils.cpp b/lib/SIL/Utils/MemAccessUtils.cpp index b9e4b7300dd39..1f6888c3fc8a4 100644 --- a/lib/SIL/Utils/MemAccessUtils.cpp +++ b/lib/SIL/Utils/MemAccessUtils.cpp @@ -902,12 +902,8 @@ SILValue swift::findOwnershipReferenceAggregate(SILValue ref) { if (auto *inst = root->getDefiningInstruction()) { if (auto fwdOp = ForwardingOperation(inst)) { - if (fwdOp.canForwardFirstOperandOnly()) { - // The `enum` instruction can have no operand. - if (inst->getNumOperands() == 0) - return root; - - root = inst->getOperand(0); + if (auto *singleForwardingOp = fwdOp.getSingleForwardingOperand()) { + root = singleForwardingOp->get(); continue; } } diff --git a/lib/SILOptimizer/IPO/CrossModuleOptimization.cpp b/lib/SILOptimizer/IPO/CrossModuleOptimization.cpp index 41ec5ab3bcabf..5cdd6ea23d5b3 100644 --- a/lib/SILOptimizer/IPO/CrossModuleOptimization.cpp +++ b/lib/SILOptimizer/IPO/CrossModuleOptimization.cpp @@ -442,7 +442,9 @@ bool CrossModuleOptimization::shouldSerialize(SILFunction *function) { if (function->hasSemanticsAttr("optimize.no.crossmodule")) return false; - if (SerializeEverything) + // In embedded Swift we serialize everything. + if (SerializeEverything || + function->getASTContext().LangOpts.hasFeature(Feature::Embedded)) return true; if (!conservative) { @@ -652,15 +654,18 @@ class CrossModuleOptimizationPass: public SILModuleTransform { return; bool conservative = false; - switch (M.getOptions().CMOMode) { - case swift::CrossModuleOptimizationMode::Off: - return; - case swift::CrossModuleOptimizationMode::Default: - conservative = true; - break; - case swift::CrossModuleOptimizationMode::Aggressive: - conservative = false; - break; + // In embedded Swift we serialize everything. + if (!M.getASTContext().LangOpts.hasFeature(Feature::Embedded)) { + switch (M.getOptions().CMOMode) { + case swift::CrossModuleOptimizationMode::Off: + return; + case swift::CrossModuleOptimizationMode::Default: + conservative = true; + break; + case swift::CrossModuleOptimizationMode::Aggressive: + conservative = false; + break; + } } CrossModuleOptimization CMO(M, conservative); diff --git a/lib/SILOptimizer/Mandatory/MoveOnlyChecker.cpp b/lib/SILOptimizer/Mandatory/MoveOnlyChecker.cpp index db2286682428e..0f0d9ff882d8e 100644 --- a/lib/SILOptimizer/Mandatory/MoveOnlyChecker.cpp +++ b/lib/SILOptimizer/Mandatory/MoveOnlyChecker.cpp @@ -30,6 +30,7 @@ #include "swift/SIL/FieldSensitivePrunedLiveness.h" #include "swift/SIL/InstructionUtils.h" #include "swift/SIL/MemAccessUtils.h" +#include "swift/SIL/OSSALifetimeCompletion.h" #include "swift/SIL/OwnershipUtils.h" #include "swift/SIL/PrunedLiveness.h" #include "swift/SIL/SILArgument.h" @@ -86,6 +87,7 @@ struct MoveOnlyChecker { } void checkObjects(); + void completeObjectLifetimes(ArrayRef); void checkAddresses(); }; @@ -110,10 +112,75 @@ void MoveOnlyChecker::checkObjects() { return; } + completeObjectLifetimes(moveIntroducersToProcess.getArrayRef()); + MoveOnlyObjectChecker checker{diagnosticEmitter, domTree, poa, allocator}; madeChange |= checker.check(moveIntroducersToProcess); } +void MoveOnlyChecker::completeObjectLifetimes( + ArrayRef insts) { +// TODO: Delete once OSSALifetimeCompletion is run as part of SILGenCleanup. + OSSALifetimeCompletion completion(fn, domTree); + + // Collect all values derived from each mark_unresolved_non_copyable_value + // instruction via ownership instructions and phis. + ValueWorklist transitiveValues(fn); + for (auto *inst : insts) { + transitiveValues.push(inst); + } + while (auto value = transitiveValues.pop()) { + for (auto *use : value->getUses()) { + auto *user = use->getUser(); + switch (user->getKind()) { + case SILInstructionKind::BeginBorrowInst: + case SILInstructionKind::CopyValueInst: + case SILInstructionKind::MoveValueInst: + transitiveValues.pushIfNotVisited(cast(user)); + break; + case SILInstructionKind::BranchInst: { + PhiOperand po(use); + transitiveValues.pushIfNotVisited(po.getValue()); + break; + } + default: { + auto forward = ForwardingOperation(user); + if (!forward) + continue; + forward.visitForwardedValues([&transitiveValues](auto forwarded) { + transitiveValues.pushIfNotVisited(forwarded); + return true; + }); + break; + } + } + } + } + // Complete the lifetime of each collected value. This is a subset of the + // work that SILGenCleanup will do. + for (auto *block : poa->get(fn)->getPostOrder()) { + for (SILInstruction &inst : reverse(*block)) { + for (auto result : inst.getResults()) { + if (!transitiveValues.isVisited(result)) + continue; + if (completion.completeOSSALifetime(result) == + LifetimeCompletion::WasCompleted) { + madeChange = true; + } + } + } + for (SILArgument *arg : block->getArguments()) { + assert(!arg->isReborrow() && "reborrows not legal at this SIL stage"); + if (!transitiveValues.isVisited(arg)) + continue; + if (completion.completeOSSALifetime(arg) == + LifetimeCompletion::WasCompleted) { + madeChange = true; + } + } + } +} + void MoveOnlyChecker::checkAddresses() { unsigned diagCount = diagnosticEmitter.getDiagnosticCount(); SmallSetVector diff --git a/lib/SILOptimizer/Mandatory/PerformanceDiagnostics.cpp b/lib/SILOptimizer/Mandatory/PerformanceDiagnostics.cpp index 70a1a40628a98..c2bff004888b8 100644 --- a/lib/SILOptimizer/Mandatory/PerformanceDiagnostics.cpp +++ b/lib/SILOptimizer/Mandatory/PerformanceDiagnostics.cpp @@ -353,7 +353,17 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst, SILType impactType; RuntimeEffect impact = getRuntimeEffect(inst, impactType); LocWithParent loc(inst->getLoc().getSourceLoc(), parentLoc); - + + if (module.getASTContext().LangOpts.hasFeature(Feature::Embedded) && + impact & RuntimeEffect::Existential) { + PrettyStackTracePerformanceDiagnostics stackTrace("existential", inst); + diagnose(loc, diag::performance_metadata, "existential"); + return true; + } + + if (perfConstr == PerformanceConstraints::None) + return false; + if (impact & RuntimeEffect::Casting) { // TODO: be more specific on casting. // E.g. distinguish locking and allocating dynamic casts, etc. @@ -497,6 +507,11 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst, void PerformanceDiagnostics::checkNonAnnotatedFunction(SILFunction *function) { for (SILBasicBlock &block : *function) { for (SILInstruction &inst : block) { + if (function->getASTContext().LangOpts.hasFeature(Feature::Embedded)) { + auto loc = LocWithParent(inst.getLoc().getSourceLoc(), nullptr); + visitInst(&inst, PerformanceConstraints::None, &loc); + } + auto as = FullApplySite::isa(&inst); if (!as) continue; @@ -592,7 +607,8 @@ class PerformanceDiagnosticsPass : public SILModuleTransform { } } - if (!annotatedFunctionsFound) + if (!annotatedFunctionsFound && + !getModule()->getASTContext().LangOpts.hasFeature(Feature::Embedded)) return; for (SILFunction &function : *module) { @@ -600,6 +616,11 @@ class PerformanceDiagnosticsPass : public SILModuleTransform { if (function.wasDeserializedCanonical()) continue; + // Don't check generic functions, they're about to be removed anyway. + if (getModule()->getASTContext().LangOpts.hasFeature(Feature::Embedded) && + function.getLoweredFunctionType()->getSubstGenericSignature()) + continue; + if (function.getPerfConstraints() == PerformanceConstraints::None) { diagnoser.checkNonAnnotatedFunction(&function); } diff --git a/lib/SILOptimizer/Mandatory/SILGenCleanup.cpp b/lib/SILOptimizer/Mandatory/SILGenCleanup.cpp index 8e4f33b64f437..fa5b880f00211 100644 --- a/lib/SILOptimizer/Mandatory/SILGenCleanup.cpp +++ b/lib/SILOptimizer/Mandatory/SILGenCleanup.cpp @@ -124,6 +124,7 @@ bool SILGenCleanup::completeOSSALifetimes(SILFunction *function) { } } for (SILArgument *arg : block->getArguments()) { + assert(!arg->isReborrow() && "reborrows not legal at this SIL stage"); if (completion.completeOSSALifetime(arg) == LifetimeCompletion::WasCompleted) { changed = true; diff --git a/lib/SILOptimizer/PassManager/PassPipeline.cpp b/lib/SILOptimizer/PassManager/PassPipeline.cpp index e7eadab6bf61d..2501f48ffc284 100644 --- a/lib/SILOptimizer/PassManager/PassPipeline.cpp +++ b/lib/SILOptimizer/PassManager/PassPipeline.cpp @@ -1004,6 +1004,9 @@ SILPassPipelinePlan::getOnonePassPipeline(const SILOptions &Options) { // inlinable functions from imported ones. P.addOnonePrespecializations(); + // For embedded Swift: CMO is used to serialize libraries. + P.addCrossModuleOptimization(); + // First serialize the SIL if we are asked to. P.startPipeline("Serialization"); P.addSerializeSILPass(); diff --git a/lib/SILOptimizer/SILCombiner/SILCombine.cpp b/lib/SILOptimizer/SILCombiner/SILCombine.cpp index 9ebdeddbfa6a9..599855125c9f8 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombine.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombine.cpp @@ -441,7 +441,7 @@ bool SILCombiner::doOneIteration(SILFunction &F, unsigned Iteration) { // block. if (auto *svi = dyn_cast(I)) { if (auto fwdOp = ForwardingOperation(svi)) { - if (fwdOp.canForwardFirstOperandOnly() && + if (fwdOp.getSingleForwardingOperand() && SILValue(svi)->getOwnershipKind() == OwnershipKind::Owned) { // Try to sink the value. If we sank the value and deleted it, // continue. If we didn't optimize or sank but we are still able to diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp index e7f44ba1f3a8c..23134192c9a1a 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp @@ -1500,6 +1500,13 @@ SILInstruction *SILCombiner::visitApplyInst(ApplyInst *AI) { } } + // (apply (differentiable_function f)) to (apply f) + if (auto *DFI = dyn_cast(AI->getCallee())) { + return cloneFullApplySiteReplacingCallee(AI, DFI->getOperand(0), + Builder.getBuilderContext()) + .getInstruction(); + } + // (apply (thin_to_thick_function f)) to (apply f) if (auto *TTTFI = dyn_cast(AI->getCallee())) { // We currently don't remove any possible retain associated with the thick diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp index 8b853d30b260f..c7fac705fdc0f 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp @@ -1110,39 +1110,42 @@ SILInstruction *SILCombiner::visitConvertEscapeToNoEscapeInst( // %vjp' = convert_escape_to_noescape %vjp // %y = differentiable_function(%orig', %jvp', %vjp') if (auto *DFI = dyn_cast(Cvt->getOperand())) { - auto createConvertEscapeToNoEscape = [&](NormalDifferentiableFunctionTypeComponent extractee) { - if (!DFI->hasExtractee(extractee)) - return SILValue(); + if (DFI->hasOneUse()) { + auto createConvertEscapeToNoEscape = + [&](NormalDifferentiableFunctionTypeComponent extractee) { + if (!DFI->hasExtractee(extractee)) + return SILValue(); - auto operand = DFI->getExtractee(extractee); - auto fnType = operand->getType().castTo(); - auto noEscapeFnType = - fnType->getWithExtInfo(fnType->getExtInfo().withNoEscape()); - auto noEscapeType = SILType::getPrimitiveObjectType(noEscapeFnType); - return Builder.createConvertEscapeToNoEscape( - operand.getLoc(), operand, noEscapeType, Cvt->isLifetimeGuaranteed())->getResult(0); - }; + auto operand = DFI->getExtractee(extractee); + auto fnType = operand->getType().castTo(); + auto noEscapeFnType = + fnType->getWithExtInfo(fnType->getExtInfo().withNoEscape()); + auto noEscapeType = SILType::getPrimitiveObjectType(noEscapeFnType); + return Builder.createConvertEscapeToNoEscape( + operand.getLoc(), operand, noEscapeType, Cvt->isLifetimeGuaranteed())->getResult(0); + }; - SILValue originalNoEscape = - createConvertEscapeToNoEscape(NormalDifferentiableFunctionTypeComponent::Original); - SILValue convertedJVP = createConvertEscapeToNoEscape( - NormalDifferentiableFunctionTypeComponent::JVP); - SILValue convertedVJP = createConvertEscapeToNoEscape( - NormalDifferentiableFunctionTypeComponent::VJP); - - llvm::Optional> derivativeFunctions; - if (convertedJVP && convertedVJP) - derivativeFunctions = std::make_pair(convertedJVP, convertedVJP); - - auto *newDFI = Builder.createDifferentiableFunction( - DFI->getLoc(), DFI->getParameterIndices(), DFI->getResultIndices(), - originalNoEscape, derivativeFunctions); - assert(newDFI->getType() == Cvt->getType() && - "New `@differentiable` function instruction should have same type " - "as the old `convert_escape_to_no_escape` instruction"); - return newDFI; - } + SILValue originalNoEscape = + createConvertEscapeToNoEscape(NormalDifferentiableFunctionTypeComponent::Original); + SILValue convertedJVP = createConvertEscapeToNoEscape( + NormalDifferentiableFunctionTypeComponent::JVP); + SILValue convertedVJP = createConvertEscapeToNoEscape( + NormalDifferentiableFunctionTypeComponent::VJP); + + llvm::Optional> derivativeFunctions; + if (convertedJVP && convertedVJP) + derivativeFunctions = std::make_pair(convertedJVP, convertedVJP); + auto *newDFI = Builder.createDifferentiableFunction( + DFI->getLoc(), DFI->getParameterIndices(), DFI->getResultIndices(), + originalNoEscape, derivativeFunctions); + assert(newDFI->getType() == Cvt->getType() && + "New `@differentiable` function instruction should have same type " + "as the old `convert_escape_to_no_escape` instruction"); + return newDFI; + } + } + return nullptr; } diff --git a/lib/SILOptimizer/Utils/InstOptUtils.cpp b/lib/SILOptimizer/Utils/InstOptUtils.cpp index 1966620eeb39c..bbed442427fff 100644 --- a/lib/SILOptimizer/Utils/InstOptUtils.cpp +++ b/lib/SILOptimizer/Utils/InstOptUtils.cpp @@ -1806,7 +1806,11 @@ SILValue swift::makeValueAvailable(SILValue value, SILBasicBlock *inBlock) { bool swift::tryEliminateOnlyOwnershipUsedForwardingInst( SingleValueInstruction *forwardingInst, InstModCallbacks &callbacks) { auto fwdOp = ForwardingOperation(forwardingInst); - if (!fwdOp || !fwdOp.canForwardFirstOperandOnly()) { + if (!fwdOp) { + return false; + } + auto *singleFwdOp = fwdOp.getSingleForwardingOperand(); + if (!singleFwdOp) { return false; } @@ -1831,7 +1835,7 @@ bool swift::tryEliminateOnlyOwnershipUsedForwardingInst( // Now that we know we can perform our transform, set all uses of // forwardingInst to be used of its operand and then delete \p forwardingInst. - auto newValue = forwardingInst->getOperand(0); + auto newValue = singleFwdOp->get(); while (!forwardingInst->use_empty()) { auto *use = *(forwardingInst->use_begin()); use->set(newValue); diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index e2eb5e9eecc18..cfaecc9be7188 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -2052,7 +2052,7 @@ bool TypeVarBindingProducer::computeNext() { } } - if (NumTries == 0) { + if (newBindings.empty()) { // Add defaultable constraints (if any). for (auto *constraint : DelayedDefaults) { if (constraint->getKind() == ConstraintKind::FallbackType) { @@ -2065,6 +2065,9 @@ bool TypeVarBindingProducer::computeNext() { addNewBinding(getDefaultBinding(constraint)); } + + // Drop all of the default since we have converted them into bindings. + DelayedDefaults.clear(); } if (newBindings.empty()) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 843dc1e522639..3953f6120ede3 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -2761,6 +2761,17 @@ bool ContextualFailure::diagnoseAsNote() { } } + // Note that mentions candidate type number of parameters diff. + auto fromFnType = getFromType()->getAs(); + auto toFnType = getToType()->getAs(); + if (fromFnType && toFnType && + fromFnType->getNumParams() > toFnType->getNumParams()) { + emitDiagnosticAt(decl, diag::candidate_with_extraneous_args, fromFnType, + fromFnType->getNumParams(), toFnType, + toFnType->getNumParams()); + return true; + } + emitDiagnosticAt(decl, diag::found_candidate_type, getFromType()); return true; } @@ -3388,11 +3399,9 @@ bool ContextualFailure::tryProtocolConformanceFixIt( auto conformanceDiag = emitDiagnostic(diag::assign_protocol_conformance_fix_it, constraint, nominal->getDescriptiveKind(), fromType); - if (nominal->getInherited().size() > 0) { - auto lastInherited = nominal->getInherited().back().getLoc(); - auto lastInheritedEndLoc = - Lexer::getLocForEndOfToken(getASTContext().SourceMgr, lastInherited); - conformanceDiag.fixItInsert(lastInheritedEndLoc, ", " + protoString); + if (!nominal->getInherited().empty()) { + auto lastInheritedEndLoc = nominal->getInherited().getEndLoc(); + conformanceDiag.fixItInsertAfter(lastInheritedEndLoc, ", " + protoString); } else { auto nameEndLoc = Lexer::getLocForEndOfToken(getASTContext().SourceMgr, nominal->getNameLoc()); diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 8a69fcf4c1398..882349e9acf49 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -866,7 +866,7 @@ namespace { }; } // end anonymous namespace -void VarRefCollector::inferTypeVars(Decl *D) { +void TypeVarRefCollector::inferTypeVars(Decl *D) { // We're only interested in VarDecls. if (!isa_and_nonnull(D)) return; @@ -881,7 +881,10 @@ void VarRefCollector::inferTypeVars(Decl *D) { } ASTWalker::PreWalkResult -VarRefCollector::walkToExprPre(Expr *expr) { +TypeVarRefCollector::walkToExprPre(Expr *expr) { + if (isa(expr)) + DCDepth += 1; + if (auto *DRE = dyn_cast(expr)) inferTypeVars(DRE->getDecl()); @@ -901,6 +904,34 @@ VarRefCollector::walkToExprPre(Expr *expr) { return Action::Continue(expr); } +ASTWalker::PostWalkResult +TypeVarRefCollector::walkToExprPost(Expr *expr) { + if (isa(expr)) + DCDepth -= 1; + + return Action::Continue(expr); +} + +ASTWalker::PreWalkResult +TypeVarRefCollector::walkToStmtPre(Stmt *stmt) { + // If we have a return without any intermediate DeclContexts in a ClosureExpr, + // we need to include any type variables in the closure's result type, since + // the conjunction will generate constraints using that type. We don't need to + // connect to returns in e.g nested closures since we'll connect those when we + // generate constraints for those closures. We also don't need to bother if + // we're generating constraints for the closure itself, since we'll connect + // the conjunction to the closure type variable itself. + if (auto *CE = dyn_cast(DC)) { + if (isa(stmt) && DCDepth == 0 && + !Locator->directlyAt()) { + SmallPtrSet typeVars; + CS.getClosureType(CE)->getResult()->getTypeVariables(typeVars); + TypeVars.insert(typeVars.begin(), typeVars.end()); + } + } + return Action::Continue(stmt); +} + namespace { class ConstraintGenerator : public ExprVisitor { ConstraintSystem &CS; @@ -1304,7 +1335,8 @@ namespace { // in the tap body, otherwise tap expression is going // to get disconnected from the context. if (auto *body = tap->getBody()) { - VarRefCollector refCollector(CS); + TypeVarRefCollector refCollector( + CS, tap->getVar()->getDeclContext(), locator); body->walk(refCollector); @@ -2938,7 +2970,7 @@ namespace { auto *locator = CS.getConstraintLocator(closure); auto closureType = CS.createTypeVariable(locator, TVO_CanBindToNoEscape); - VarRefCollector refCollector(CS); + TypeVarRefCollector refCollector(CS, /*DC*/ closure, locator); // Walk the capture list if this closure has one, because it could // reference declarations from the outer closure. if (auto *captureList = diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 3e7da8595614a..f6375a4430c84 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -3425,18 +3425,36 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, if (!anchor) return getTypeMatchFailure(argumentLocator); - // If there are missing arguments, let's add them - // using parameter as a template. - if (diff < 0) { - if (fixMissingArguments(*this, anchor, func1Params, func2Params, - abs(diff), loc)) + // The param diff is in a function type coercion context + // + // func fn(_: Int) {} + // let i: Int = 0 + // (fn as (Int, Int) -> Void)(i, i) + // + // Since we are not in a function argument application, simply record + // a function type mismatch instead of an argument fix. + // Except for when a closure is a subexpr because closure expr parameters + // syntax can be added or removed by missing/extraneous arguments fix. + if (loc->isForCoercion() && !isExpr(anchor)) { + auto *fix = ContextualMismatch::create(*this, func1, func2, loc); + if (recordFix(fix)) return getTypeMatchFailure(argumentLocator); } else { - // If there are extraneous arguments, let's remove - // them from the list. - if (fixExtraneousArguments(*this, func2, func1Params, diff, loc)) - return getTypeMatchFailure(argumentLocator); + // If there are missing arguments, let's add them + // using parameter as a template. + if (diff < 0) { + if (fixMissingArguments(*this, anchor, func1Params, func2Params, + abs(diff), loc)) + return getTypeMatchFailure(argumentLocator); + } else { + // If there are extraneous arguments, let's remove + // them from the list. + if (fixExtraneousArguments(*this, func2, func1Params, diff, loc)) + return getTypeMatchFailure(argumentLocator); + } + } + if (diff > 0) { // Drop all of the extraneous arguments. auto numParams = func2Params.size(); func1Params.erase(func1Params.begin() + numParams, func1Params.end()); diff --git a/lib/Sema/CSSyntacticElement.cpp b/lib/Sema/CSSyntacticElement.cpp index ebd616057b343..36c9aa279379e 100644 --- a/lib/Sema/CSSyntacticElement.cpp +++ b/lib/Sema/CSSyntacticElement.cpp @@ -281,11 +281,10 @@ static bool isViableElement(ASTNode element, using ElementInfo = std::tuple; -static void createConjunction(ConstraintSystem &cs, +static void createConjunction(ConstraintSystem &cs, DeclContext *dc, ArrayRef elements, - ConstraintLocator *locator, - bool isIsolated = false, - ArrayRef extraTypeVars = {}) { + ConstraintLocator *locator, bool isIsolated, + ArrayRef extraTypeVars) { SmallVector constraints; SmallVector referencedVars; referencedVars.append(extraTypeVars.begin(), extraTypeVars.end()); @@ -335,7 +334,7 @@ static void createConjunction(ConstraintSystem &cs, isIsolated = true; } - VarRefCollector paramCollector(cs); + TypeVarRefCollector paramCollector(cs, dc, locator); // Whether we're doing completion, and the conjunction is for a // SingleValueStmtExpr, or one of its braces. @@ -517,6 +516,13 @@ class SyntacticElementConstraintGenerator ConstraintLocator *locator) : cs(cs), context(context), locator(locator) {} + void createConjunction(ArrayRef elements, + ConstraintLocator *locator, bool isIsolated = false, + ArrayRef extraTypeVars = {}) { + ::createConjunction(cs, context.getAsDeclContext(), elements, locator, + isIsolated, extraTypeVars); + } + void visitExprPattern(ExprPattern *EP) { auto target = SyntacticElementTarget::forExprPattern(EP); @@ -859,7 +865,7 @@ class SyntacticElementConstraintGenerator if (auto *join = context.ElementJoin.getPtrOrNull()) elements.push_back(makeJoinElement(cs, join, locator)); - createConjunction(cs, elements, locator); + createConjunction(elements, locator); } void visitGuardStmt(GuardStmt *guardStmt) { @@ -868,7 +874,7 @@ class SyntacticElementConstraintGenerator visitStmtCondition(guardStmt, elements, locator); elements.push_back(makeElement(guardStmt->getBody(), locator)); - createConjunction(cs, elements, locator); + createConjunction(elements, locator); } void visitWhileStmt(WhileStmt *whileStmt) { @@ -877,7 +883,7 @@ class SyntacticElementConstraintGenerator visitStmtCondition(whileStmt, elements, locator); elements.push_back(makeElement(whileStmt->getBody(), locator)); - createConjunction(cs, elements, locator); + createConjunction(elements, locator); } void visitDoStmt(DoStmt *doStmt) { @@ -885,8 +891,7 @@ class SyntacticElementConstraintGenerator } void visitRepeatWhileStmt(RepeatWhileStmt *repeatWhileStmt) { - createConjunction(cs, - {makeElement(repeatWhileStmt->getCond(), + createConjunction({makeElement(repeatWhileStmt->getCond(), cs.getConstraintLocator( locator, ConstraintLocator::Condition), getContextForCondition()), @@ -895,8 +900,7 @@ class SyntacticElementConstraintGenerator } void visitPoundAssertStmt(PoundAssertStmt *poundAssertStmt) { - createConjunction(cs, - {makeElement(poundAssertStmt->getCondition(), + createConjunction({makeElement(poundAssertStmt->getCondition(), cs.getConstraintLocator( locator, ConstraintLocator::Condition), getContextForCondition())}, @@ -913,12 +917,10 @@ class SyntacticElementConstraintGenerator auto *errorExpr = throwStmt->getSubExpr(); createConjunction( - cs, - {makeElement( - errorExpr, - cs.getConstraintLocator( - locator, LocatorPathElt::SyntacticElement(errorExpr)), - {errType, CTP_ThrowStmt})}, + {makeElement(errorExpr, + cs.getConstraintLocator( + locator, LocatorPathElt::SyntacticElement(errorExpr)), + {errType, CTP_ThrowStmt})}, locator); } @@ -939,12 +941,10 @@ class SyntacticElementConstraintGenerator auto *selfExpr = discardStmt->getSubExpr(); createConjunction( - cs, - {makeElement( - selfExpr, - cs.getConstraintLocator( - locator, LocatorPathElt::SyntacticElement(selfExpr)), - {nominalType, CTP_DiscardStmt})}, + {makeElement(selfExpr, + cs.getConstraintLocator( + locator, LocatorPathElt::SyntacticElement(selfExpr)), + {nominalType, CTP_DiscardStmt})}, locator); } @@ -962,7 +962,7 @@ class SyntacticElementConstraintGenerator // Body of the `for-in` loop. elements.push_back(makeElement(forEachStmt->getBody(), stmtLoc)); - createConjunction(cs, elements, locator); + createConjunction(elements, locator); } void visitSwitchStmt(SwitchStmt *switchStmt) { @@ -990,7 +990,7 @@ class SyntacticElementConstraintGenerator if (auto *join = context.ElementJoin.getPtrOrNull()) elements.push_back(makeJoinElement(cs, join, switchLoc)); - createConjunction(cs, elements, switchLoc); + createConjunction(elements, switchLoc); } void visitDoCatchStmt(DoCatchStmt *doStmt) { @@ -1007,7 +1007,7 @@ class SyntacticElementConstraintGenerator for (auto *catchStmt : doStmt->getCatches()) elements.push_back(makeElement(catchStmt, doLoc)); - createConjunction(cs, elements, doLoc); + createConjunction(elements, doLoc); } void visitCaseStmt(CaseStmt *caseStmt) { @@ -1040,7 +1040,7 @@ class SyntacticElementConstraintGenerator elements.push_back(makeElement(caseStmt->getBody(), caseLoc)); - createConjunction(cs, elements, caseLoc); + createConjunction(elements, caseLoc); } void visitBraceStmt(BraceStmt *braceStmt) { @@ -1127,7 +1127,7 @@ class SyntacticElementConstraintGenerator // want to type-check captures to make sure that the context // is valid. if (captureList) - createConjunction(cs, elements, locator); + createConjunction(elements, locator); return; } @@ -1195,7 +1195,7 @@ class SyntacticElementConstraintGenerator contextInfo.value_or(ContextualTypeInfo()), isDiscarded)); } - createConjunction(cs, elements, locator); + createConjunction(elements, locator); } void visitReturnStmt(ReturnStmt *returnStmt) { @@ -1282,7 +1282,7 @@ class SyntacticElementConstraintGenerator auto resultElt = makeElement(resultExpr, locator, contextInfo.value_or(ContextualTypeInfo()), /*isDiscarded=*/false); - createConjunction(cs, {resultElt}, locator); + createConjunction({resultElt}, locator); } ContextualTypeInfo getContextualResultInfo() const { @@ -1520,6 +1520,9 @@ bool ConstraintSystem::generateConstraints(SingleValueStmtExpr *E) { void ConstraintSystem::generateConstraints(ArrayRef exprPatterns, ConstraintLocatorBuilder locator) { + assert(!exprPatterns.empty()); + auto *DC = exprPatterns.front()->getDeclContext(); + // Form a conjunction of ExprPattern elements, isolated from the rest of the // pattern. SmallVector elements; @@ -1532,7 +1535,7 @@ void ConstraintSystem::generateConstraints(ArrayRef exprPatterns, elements.push_back(makeElement(EP, getConstraintLocator(EP), context)); } auto *loc = getConstraintLocator(locator); - createConjunction(*this, elements, loc, /*isIsolated*/ true, + createConjunction(*this, DC, elements, loc, /*isIsolated*/ true, referencedTypeVars); } diff --git a/lib/Sema/DerivedConformanceCodingKey.cpp b/lib/Sema/DerivedConformanceCodingKey.cpp index d548dce426705..635e152e421af 100644 --- a/lib/Sema/DerivedConformanceCodingKey.cpp +++ b/lib/Sema/DerivedConformanceCodingKey.cpp @@ -338,7 +338,7 @@ static bool canSynthesizeCodingKey(DerivedConformance &derived) { } } - auto inherited = enumDecl->getInherited(); + auto inherited = enumDecl->getInherited().getEntries(); if (!inherited.empty() && inherited.front().wasValidated() && inherited.front().isError()) return false; diff --git a/lib/Sema/DerivedConformanceComparable.cpp b/lib/Sema/DerivedConformanceComparable.cpp index a98050fcd3d3f..22f9367f74263 100644 --- a/lib/Sema/DerivedConformanceComparable.cpp +++ b/lib/Sema/DerivedConformanceComparable.cpp @@ -336,7 +336,7 @@ void DerivedConformance::tryDiagnoseFailedComparableDerivation( if (auto enumDecl = dyn_cast(nominal)) { if (enumDecl->hasRawType() && !enumDecl->getRawType()->is()) { auto rawType = enumDecl->getRawType(); - auto rawTypeLoc = enumDecl->getInherited()[0].getSourceRange().Start; + auto rawTypeLoc = enumDecl->getInherited().getStartLoc(); ctx.Diags.diagnose(rawTypeLoc, diag::comparable_synthesis_raw_value_not_allowed, rawType, nominal->getDeclaredInterfaceType(), diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp index b166aee64b830..68d36ea043093 100644 --- a/lib/Sema/DerivedConformanceRawRepresentable.cpp +++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp @@ -460,7 +460,7 @@ bool DerivedConformance::canDeriveRawRepresentable(DeclContext *DC, rawType = DC->mapTypeIntoContext(rawType); - auto inherited = enumDecl->getInherited(); + auto inherited = enumDecl->getInherited().getEntries(); if (!inherited.empty() && inherited.front().wasValidated() && inherited.front().isError()) return false; diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index 5d90d6ff95989..91694557dcfb5 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -411,13 +411,13 @@ void AccessControlCheckerBase::checkGenericParamAccess( if (auto params = ownerCtx->getGenericParams()) { for (auto param : *params) { - if (param->getInherited().empty()) + auto inheritedEntries = param->getInherited().getEntries(); + if (inheritedEntries.empty()) continue; - assert(param->getInherited().size() == 1); - checkTypeAccessImpl(param->getInherited().front().getType(), - param->getInherited().front().getTypeRepr(), - accessScope, DC, /*mayBeInferred*/false, - callback); + assert(inheritedEntries.size() == 1); + checkTypeAccessImpl(inheritedEntries.front().getType(), + inheritedEntries.front().getTypeRepr(), accessScope, + DC, /*mayBeInferred*/ false, callback); } } @@ -725,9 +725,7 @@ class AccessControlChecker : public AccessControlCheckerBase, auto minDiagAccessLevel = AccessLevel::Public; ImportAccessLevel minImportLimit = llvm::None; - std::for_each(assocType->getInherited().begin(), - assocType->getInherited().end(), - [&](TypeLoc requirement) { + for (TypeLoc requirement : assocType->getInherited().getEntries()) { checkTypeAccess(requirement, assocType, /*mayBeInferred*/false, [&](AccessScope typeAccessScope, const TypeRepr *thisComplainRepr, @@ -745,7 +743,7 @@ class AccessControlChecker : public AccessControlCheckerBase, minImportLimit = importLimit; } }); - }); + } checkTypeAccess(assocType->getDefaultDefinitionType(), assocType->getDefaultDefinitionTypeRepr(), assocType, /*mayBeInferred*/false, @@ -809,14 +807,15 @@ class AccessControlChecker : public AccessControlCheckerBase, if (ED->hasRawType()) { Type rawType = ED->getRawType(); - auto rawTypeLocIter = std::find_if(ED->getInherited().begin(), - ED->getInherited().end(), + auto inheritedEntries = ED->getInherited().getEntries(); + auto rawTypeLocIter = std::find_if(inheritedEntries.begin(), + inheritedEntries.end(), [&](TypeLoc inherited) { if (!inherited.wasValidated()) return false; return inherited.getType().getPointer() == rawType.getPointer(); }); - if (rawTypeLocIter == ED->getInherited().end()) + if (rawTypeLocIter == inheritedEntries.end()) return; checkTypeAccess(rawType, rawTypeLocIter->getTypeRepr(), ED, /*mayBeInferred*/false, @@ -851,8 +850,9 @@ class AccessControlChecker : public AccessControlCheckerBase, if (const NominalTypeDecl *superclassDecl = CD->getSuperclassDecl()) { // Be slightly defensive here in the presence of badly-ordered // inheritance clauses. - auto superclassLocIter = std::find_if(CD->getInherited().begin(), - CD->getInherited().end(), + auto inheritedEntries = CD->getInherited().getEntries(); + auto superclassLocIter = std::find_if(inheritedEntries.begin(), + inheritedEntries.end(), [&](TypeLoc inherited) { if (!inherited.wasValidated()) return false; @@ -865,7 +865,7 @@ class AccessControlChecker : public AccessControlCheckerBase, // Sanity check: we couldn't find the superclass for whatever reason // (possibly because it's synthetic or something), so don't bother // checking it. - if (superclassLocIter == CD->getInherited().end()) + if (superclassLocIter == inheritedEntries.end()) return; auto outerDowngradeToWarning = DowngradeToWarning::No; @@ -918,12 +918,9 @@ class AccessControlChecker : public AccessControlCheckerBase, DescriptiveDeclKind declKind = DescriptiveDeclKind::Protocol; // FIXME: Hack to ensure that we've computed the types involved here. - ASTContext &ctx = proto->getASTContext(); - for (unsigned i : indices(proto->getInherited())) { - (void)evaluateOrDefault(ctx.evaluator, - InheritedTypeRequest{ - proto, i, TypeResolutionStage::Interface}, - Type()); + auto inheritedTypes = proto->getInherited(); + for (auto i : inheritedTypes.getIndices()) { + (void)inheritedTypes.getResolvedType(i); } auto declKindForType = [](Type type) -> DescriptiveDeclKind { @@ -940,9 +937,7 @@ class AccessControlChecker : public AccessControlCheckerBase, return DescriptiveDeclKind::Type; }; - std::for_each(proto->getInherited().begin(), - proto->getInherited().end(), - [&](TypeLoc requirement) { + for (TypeLoc requirement : proto->getInherited().getEntries()) { checkTypeAccess(requirement, proto, /*mayBeInferred*/false, [&](AccessScope typeAccessScope, const TypeRepr *thisComplainRepr, @@ -961,7 +956,7 @@ class AccessControlChecker : public AccessControlCheckerBase, declKind = declKindForType(requirement.getType()); } }); - }); + } forAllRequirementTypes(proto, [&](Type type, TypeRepr *typeRepr) { checkTypeAccess( @@ -1488,9 +1483,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, ACEK_Requirement }; - std::for_each(assocType->getInherited().begin(), - assocType->getInherited().end(), - [&](TypeLoc requirement) { + for (TypeLoc requirement : assocType->getInherited().getEntries()) { checkTypeAccess(requirement, assocType, /*mayBeInferred*/false, [&](AccessScope typeAccessScope, const TypeRepr *complainRepr, @@ -1504,7 +1497,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, noteLimitingImport(assocType->getASTContext(), importLimit, complainRepr); }); - }); + } checkTypeAccess(assocType->getDefaultDefinitionType(), assocType->getDefaultDefinitionTypeRepr(), assocType, /*mayBeInferred*/false, @@ -1549,14 +1542,15 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, if (ED->hasRawType()) { Type rawType = ED->getRawType(); - auto rawTypeLocIter = std::find_if(ED->getInherited().begin(), - ED->getInherited().end(), + auto inheritedEntries = ED->getInherited().getEntries(); + auto rawTypeLocIter = std::find_if(inheritedEntries.begin(), + inheritedEntries.end(), [&](TypeLoc inherited) { if (!inherited.wasValidated()) return false; return inherited.getType().getPointer() == rawType.getPointer(); }); - if (rawTypeLocIter == ED->getInherited().end()) + if (rawTypeLocIter == inheritedEntries.end()) return; checkTypeAccess(rawType, rawTypeLocIter->getTypeRepr(), ED, /*mayBeInferred*/false, @@ -1584,10 +1578,11 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, if (CD->hasSuperclass()) { const NominalTypeDecl *superclassDecl = CD->getSuperclassDecl(); + auto inheritedEntries = CD->getInherited().getEntries(); // Be slightly defensive here in the presence of badly-ordered // inheritance clauses. - auto superclassLocIter = std::find_if(CD->getInherited().begin(), - CD->getInherited().end(), + auto superclassLocIter = std::find_if(inheritedEntries.begin(), + inheritedEntries.end(), [&](TypeLoc inherited) { if (!inherited.wasValidated()) return false; @@ -1600,7 +1595,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, // Sanity check: we couldn't find the superclass for whatever reason // (possibly because it's synthetic or something), so don't bother // checking it. - if (superclassLocIter == CD->getInherited().end()) + if (superclassLocIter == inheritedEntries.end()) return; checkTypeAccess(CD->getSuperclass(), superclassLocIter->getTypeRepr(), CD, @@ -1628,9 +1623,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, PCEK_Requirement }; - std::for_each(proto->getInherited().begin(), - proto->getInherited().end(), - [&](TypeLoc requirement) { + for (TypeLoc requirement : proto->getInherited().getEntries()) { checkTypeAccess(requirement, proto, /*mayBeInferred*/false, [&](AccessScope typeAccessScope, const TypeRepr *complainRepr, @@ -1644,7 +1637,7 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, highlightOffendingType(diag, complainRepr); noteLimitingImport(proto->getASTContext(), importLimit, complainRepr); }); - }); + } if (proto->getTrailingWhereClause()) { auto accessScope = proto->getFormalAccessScope(nullptr, @@ -2008,10 +2001,11 @@ class DeclAvailabilityChecker : public DeclVisitor { if (auto params = ownerCtx->getGenericParams()) { for (auto param : *params) { - if (param->getInherited().empty()) + auto inheritedEntries = param->getInherited().getEntries(); + if (inheritedEntries.empty()) continue; - assert(param->getInherited().size() == 1); - auto inherited = param->getInherited().front(); + assert(inheritedEntries.size() == 1); + auto inherited = inheritedEntries.front(); checkType(inherited.getType(), inherited.getTypeRepr(), ownerDecl); } } @@ -2158,11 +2152,10 @@ class DeclAvailabilityChecker : public DeclVisitor { } void visitAssociatedTypeDecl(AssociatedTypeDecl *assocType) { - llvm::for_each(assocType->getInherited(), - [&](TypeLoc requirement) { + for (TypeLoc requirement : assocType->getInherited().getEntries()) { checkType(requirement.getType(), requirement.getTypeRepr(), assocType); - }); + } checkType(assocType->getDefaultDefinitionType(), assocType->getDefaultDefinitionTypeRepr(), assocType); @@ -2192,17 +2185,17 @@ class DeclAvailabilityChecker : public DeclVisitor { flags |= DeclAvailabilityFlag:: AllowPotentiallyUnavailableAtOrBelowDeploymentTarget; - llvm::for_each(nominal->getInherited(), [&](TypeLoc inherited) { + for (TypeLoc inherited : nominal->getInherited().getEntries()) { checkType(inherited.getType(), inherited.getTypeRepr(), nominal, ExportabilityReason::General, flags); - }); + } } void visitProtocolDecl(ProtocolDecl *proto) { - llvm::for_each(proto->getInherited(), [&](TypeLoc requirement) { + for (TypeLoc requirement : proto->getInherited().getEntries()) { checkType(requirement.getType(), requirement.getTypeRepr(), proto, ExportabilityReason::General); - }); + } if (proto->getTrailingWhereClause()) { forAllRequirementTypes(proto, [&](Type type, TypeRepr *typeRepr) { @@ -2290,11 +2283,11 @@ class DeclAvailabilityChecker : public DeclVisitor { // // 1) If the extension defines conformances, the conformed-to protocols // must be exported. - llvm::for_each(ED->getInherited(), [&](TypeLoc inherited) { + for (TypeLoc inherited : ED->getInherited().getEntries()) { checkType(inherited.getType(), inherited.getTypeRepr(), ED, ExportabilityReason::General, DeclAvailabilityFlag::AllowPotentiallyUnavailableProtocol); - }); + } auto wasWhere = Where; diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index a3043d8595d8a..c49cdd347458b 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -6948,7 +6948,7 @@ void AttributeChecker::visitMacroRoleAttr(MacroRoleAttr *attr) { (void)evaluateOrDefault( Ctx.evaluator, - ResolveExtensionMacroConformances{attr, D}, + ResolveMacroConformances{attr, D}, {}); } diff --git a/lib/Sema/TypeCheckCodeCompletion.cpp b/lib/Sema/TypeCheckCodeCompletion.cpp index ad16602c65fc2..5254450ff495f 100644 --- a/lib/Sema/TypeCheckCodeCompletion.cpp +++ b/lib/Sema/TypeCheckCodeCompletion.cpp @@ -102,201 +102,6 @@ static Expr *extractKeyPathFromCurryThunkCall(Expr *E) { return cast(E)->getArgs()->getUnlabeledUnaryExpr(); } -namespace { - -/// AST walker that "sanitizes" an expression for re-typechecking during -/// code completion. -/// -/// FIXME: Remove this. -class SanitizeExpr : public ASTWalker { - ASTContext &C; - llvm::SmallDenseMap OpenExistentials; - -public: - SanitizeExpr(ASTContext &C) - : C(C) { } - - MacroWalking getMacroWalkingBehavior() const override { - return MacroWalking::Arguments; - } - - PreWalkResult - walkToArgumentListPre(ArgumentList *argList) override { - // Return the argument list to the state prior to being rewritten. This will - // strip default arguments and expand variadic args. - return Action::Continue(argList->getOriginalArgs()); - } - - PreWalkResult walkToExprPre(Expr *expr) override { - while (true) { - // OpenExistentialExpr contains OpaqueValueExpr in its sub expression. - if (auto OOE = dyn_cast(expr)) { - auto archetypeVal = OOE->getOpaqueValue(); - auto base = OOE->getExistentialValue(); - - bool inserted = OpenExistentials.insert({archetypeVal, base}).second; - assert(inserted && "OpaqueValue appears multiple times?"); - (void)inserted; - SWIFT_DEFER { OpenExistentials.erase(archetypeVal); }; - - // Walk to and return the base expression to erase any existentials - // within it. - return Action::SkipChildren(OOE->getSubExpr()->walk(*this)); - } - - // Hacky, this behaves just like an OpenedExistential in that it changes - // the expr tree. - if (auto ISLE = dyn_cast(expr)) { - if (auto subExpr = ISLE->getAppendingExpr()->getSubExpr()) { - if (auto opaqueValue = dyn_cast(subExpr)) { - ISLE->getAppendingExpr()->setSubExpr(nullptr); - } - } - } - - // Substitute OpaqueValue with its representing existential. - if (auto OVE = dyn_cast(expr)) { - auto value = OpenExistentials.find(OVE); - - if (value != OpenExistentials.end()) { - expr = value->second; - continue; - } else { - assert(OVE->isPlaceholder() && - "Didn't see this OVE in a containing OpenExistentialExpr?"); - } - } - - // Skip any implicit conversions applied to this expression. - if (auto ICE = dyn_cast(expr)) { - expr = ICE->getSubExpr(); - continue; - } - - // MakeTemporarilyEscapableExpr is typechecked expression. - if (auto MTEE = dyn_cast(expr)) { - expr = MTEE->getOriginalExpr(); - continue; - } - - // Extract keypath from '{ `$kp$` in { $0[keyPath: $kp$] } }(keypath)' - if (isKeyPathCurriedThunkCallExpr(expr)) { - expr = extractKeyPathFromCurryThunkCall(expr); - continue; - } - - if (auto ACE = dyn_cast(expr)) { - // Restore '@autoclosure'd value. - // This is only valid if the closure doesn't have parameters. - if (ACE->getParameters()->size() == 0) { - expr = ACE->getSingleExpressionBody(); - continue; - } - // Restore autoclosure'd function reference. - if (auto *unwrapped = ACE->getUnwrappedCurryThunkExpr()) { - expr = unwrapped; - continue; - } - - llvm_unreachable("other AutoClosureExpr must be handled specially"); - } - - // Remove any semantic expression injected by typechecking. - if (auto EPE = dyn_cast(expr)) { - EPE->setSemanticExpr(nullptr); - } - - // If this is a closure, only walk into its children if they - // are type-checked in the context of the enclosing expression. - if (auto closure = dyn_cast(expr)) { - for (auto &Param : *closure->getParameters()) { - Param->setSpecifier(swift::ParamSpecifier::Default); - } - } - - // Now, we're ready to walk into sub expressions. - return Action::Continue(expr); - } - } - - PostWalkResult walkToExprPost(Expr *expr) override { - assert(!isa(expr) && - "ImplicitConversionExpr should be eliminated in walkToExprPre"); - - auto buildMemberRef = [&](Type memberType, Expr *base, SourceLoc dotLoc, - ConcreteDeclRef member, DeclNameLoc memberLoc, - bool implicit) -> Expr * { - auto *memberRef = new (C) - MemberRefExpr(base, dotLoc, member, memberLoc, implicit); - - if (memberType) { - memberRef->setType(memberType); - return memberRef; - } - - return memberRef; - }; - - // A DotSyntaxCallExpr is a member reference that has already been - // type-checked down to a call; turn it back into an overloaded - // member reference expression. - if (auto dotCall = dyn_cast(expr)) { - DeclNameLoc memberLoc; - auto memberAndFunctionRef = findReferencedDecl(dotCall->getFn(), - memberLoc); - if (memberAndFunctionRef.first) { - assert(!isa(dotCall->getBase())); - auto *ref = buildMemberRef(dotCall->getType(), - dotCall->getBase(), - dotCall->getDotLoc(), - memberAndFunctionRef.first, - memberLoc, expr->isImplicit()); - return Action::Continue(ref); - } - } - - if (auto *dynamicMember = dyn_cast(expr)) { - if (auto memberRef = dynamicMember->getMember()) { - assert(!isa(dynamicMember->getBase())); - auto *ref = buildMemberRef(dynamicMember->getType(), - dynamicMember->getBase(), - dynamicMember->getDotLoc(), - memberRef, - dynamicMember->getNameLoc(), - expr->isImplicit()); - return Action::Continue(ref); - } - } - - // A DotSyntaxBaseIgnoredExpr is a static member reference that has - // already been type-checked down to a call where the argument doesn't - // actually matter; turn it back into an overloaded member reference - // expression. - if (auto dotIgnored = dyn_cast(expr)) { - DeclNameLoc memberLoc; - auto memberAndFunctionRef = findReferencedDecl(dotIgnored->getRHS(), - memberLoc); - if (memberAndFunctionRef.first) { - assert(!isa(dotIgnored->getLHS())); - auto *ref = buildMemberRef(dotIgnored->getType(), - dotIgnored->getLHS(), - dotIgnored->getDotLoc(), - memberAndFunctionRef.first, - memberLoc, expr->isImplicit()); - return Action::Continue(ref); - } - } - return Action::Continue(expr); - } - - /// Ignore declarations. - PreWalkAction walkToDeclPre(Decl *decl) override { - return Action::SkipChildren(); - } -}; - -} // end namespace - static Type getTypeOfExpressionWithoutApplying(Expr *&expr, DeclContext *dc, ConcreteDeclRef &referencedDecl, @@ -310,8 +115,6 @@ getTypeOfExpressionWithoutApplying(Expr *&expr, DeclContext *dc, } auto &Context = dc->getASTContext(); - expr = expr->walk(SanitizeExpr(Context)); - FrontendStatsTracer StatsTracer(Context.Stats, "typecheck-expr-no-apply", expr); PrettyStackTraceExpr stackTrace(Context, "type-checking", expr); @@ -401,134 +204,6 @@ getTypeOfExpressionWithoutApplying(Expr *&expr, DeclContext *dc, return exprType; } -static FunctionType * -getTypeOfCompletionOperatorImpl(DeclContext *DC, Expr *expr, - ConcreteDeclRef &referencedDecl) { - auto &Context = DC->getASTContext(); - - FrontendStatsTracer StatsTracer(Context.Stats, - "typecheck-completion-operator", expr); - PrettyStackTraceExpr stackTrace(Context, "type-checking", expr); - - expr = expr->walk(SanitizeExpr(Context)); - - ConstraintSystemOptions options; - options |= ConstraintSystemFlags::SuppressDiagnostics; - - // Construct a constraint system from this expression. - ConstraintSystem CS(DC, options); - expr = CS.generateConstraints(expr, DC); - if (!expr) - return nullptr; - - if (CS.isDebugMode()) { - auto &log = llvm::errs(); - auto indent = CS.solverState ? CS.solverState->getCurrentIndent() : 0; - log.indent(indent) - << "---Initial constraints for the given expression---\n"; - expr->dump(log, indent); - log << "\n"; - CS.print(log); - } - - // Attempt to solve the constraint system. - SmallVector viable; - if (CS.solve(viable, FreeTypeVariableBinding::Disallow)) - return nullptr; - - auto &solution = viable[0]; - if (CS.isDebugMode()) { - auto &log = llvm::errs(); - auto indent = CS.solverState ? CS.solverState->getCurrentIndent() : 0; - log.indent(indent) << "---Solution---\n"; - solution.dump(log, indent); - } - - // Fill the results. - Expr *opExpr = cast(expr)->getFn(); - referencedDecl = - solution.resolveLocatorToDecl(CS.getConstraintLocator(opExpr)); - - // Return '(ArgType[, ArgType]) -> ResultType' as a function type. - // We don't use the type of the operator expression because we want the types - // of the *arguments* instead of the types of the parameters. - auto *args = cast(expr)->getArgs(); - SmallVector argTypes; - for (auto arg : *args) - argTypes.emplace_back(solution.simplifyType(CS.getType(arg.getExpr()))); - - // FIXME: Verify ExtInfo state is correct, not working by accident. - FunctionType::ExtInfo info; - return FunctionType::get(argTypes, solution.simplifyType(CS.getType(expr)), - info); -} - -/// Return the type of operator function for specified LHS, or a null -/// \c Type on error. -FunctionType * -TypeChecker::getTypeOfCompletionOperator(DeclContext *DC, Expr *LHS, - Identifier opName, DeclRefKind refKind, - ConcreteDeclRef &referencedDecl) { - - // For the infix operator, find the actual LHS from pre-folded LHS. - if (refKind == DeclRefKind::BinaryOperator) - LHS = TypeChecker::findLHS(DC, LHS, opName); - - if (!LHS) - return nullptr; - - auto LHSTy = LHS->getType(); - - // FIXME: 'UnresolvedType' still might be typechecked by an operator. - if (!LHSTy || LHSTy->is()) - return nullptr; - - // Meta types and function types cannot be a operand of operator expressions. - if (LHSTy->is() || LHSTy->is()) - return nullptr; - - auto Loc = LHS->getEndLoc(); - - // Build temporary expression to typecheck. - // We allocate these expressions on the stack because we know they can't - // escape and there isn't a better way to allocate scratch Expr nodes. - - // Use a placeholder expr for the LHS argument to avoid sending - // a pre-type-checked AST through the constraint system. - OpaqueValueExpr argExpr(LHS->getSourceRange(), LHSTy, - /*isPlaceholder=*/true); - UnresolvedDeclRefExpr UDRE(DeclNameRef(opName), refKind, DeclNameLoc(Loc)); - auto *opExpr = TypeChecker::resolveDeclRefExpr( - &UDRE, DC, /*replaceInvalidRefsWithErrors=*/true); - - auto &ctx = DC->getASTContext(); - switch (refKind) { - case DeclRefKind::PostfixOperator: { - // (postfix_unary_expr - // (declref_expr name=) - // (argument_list - // ())) - auto *postfixExpr = PostfixUnaryExpr::create(ctx, opExpr, &argExpr); - return getTypeOfCompletionOperatorImpl(DC, postfixExpr, referencedDecl); - } - - case DeclRefKind::BinaryOperator: { - // (binary_expr - // (declref_expr name=) - // (argument_list - // () - // (code_completion_expr))) - CodeCompletionExpr dummyRHS(Loc); - auto *binaryExpr = BinaryExpr::create(ctx, &argExpr, opExpr, &dummyRHS, - /*implicit*/ true); - return getTypeOfCompletionOperatorImpl(DC, binaryExpr, referencedDecl); - } - - default: - llvm_unreachable("Invalid DeclRefKind for operator completion"); - } -} - static bool hasTypeForCompletion(Solution &solution, CompletionContextFinder &contextAnalyzer) { if (contextAnalyzer.hasCompletionExpr()) { @@ -581,11 +256,6 @@ bool TypeChecker::typeCheckForCodeCompletion( return false; } - if (getAsExpr(target.getAsASTNode())) { - SanitizeExpr sanitizer(Context); - target = *target.walk(sanitizer); - } - CompletionContextFinder contextAnalyzer(target, DC); // If there was no completion expr (e.g. if the code completion location was @@ -744,30 +414,6 @@ llvm::Optional swift::getTypeOfCompletionContextExpr( referencedDecl); } -/// Return the type of operator function for specified LHS, or a null -/// \c Type on error. -FunctionType * -swift::getTypeOfCompletionOperator(DeclContext *DC, Expr *LHS, - Identifier opName, DeclRefKind refKind, - ConcreteDeclRef &referencedDecl) { - auto &ctx = DC->getASTContext(); - DiagnosticSuppression suppression(ctx.Diags); - return TypeChecker::getTypeOfCompletionOperator(DC, LHS, opName, refKind, - referencedDecl); -} - -bool swift::typeCheckExpression(DeclContext *DC, Expr *&parsedExpr) { - auto &ctx = DC->getASTContext(); - - parsedExpr = parsedExpr->walk(SanitizeExpr(ctx)); - - DiagnosticSuppression suppression(ctx.Diags); - auto resultTy = TypeChecker::typeCheckExpression( - parsedExpr, DC, - /*contextualInfo=*/{}, TypeCheckExprFlags::LeaveClosureBodyUnchecked); - return !resultTy; -} - LookupResult swift::lookupSemanticMember(DeclContext *DC, Type ty, DeclName name) { return TypeChecker::lookupMember(DC, ty, DeclNameRef(name), SourceLoc(), diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index 971e4d3e6a738..8562119e8c239 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -629,7 +629,7 @@ static void addSendableFixIt( diag.fixItInsert(fixItLoc, unchecked ? ": @unchecked Sendable" : ": Sendable"); } else { - auto fixItLoc = nominal->getInherited().back().getLoc(); + auto fixItLoc = nominal->getInherited().getEndLoc(); diag.fixItInsertAfter(fixItLoc, unchecked ? ", @unchecked Sendable" : ", Sendable"); } @@ -644,7 +644,7 @@ static void addSendableFixIt(const GenericTypeParamDecl *genericArgument, diag.fixItInsertAfter(fixItLoc, unchecked ? ": @unchecked Sendable" : ": Sendable"); } else { - auto fixItLoc = genericArgument->getInherited().back().getLoc(); + auto fixItLoc = genericArgument->getInherited().getEndLoc(); diag.fixItInsertAfter(fixItLoc, unchecked ? ", @unchecked Sendable" : ", Sendable"); } diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 2e66abcef855e..9768feabea97d 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -2938,22 +2938,12 @@ bool TypeChecker::isPassThroughTypealias(TypeAliasDecl *typealias, // If neither is generic at this level, we have a pass-through typealias. if (!typealias->isGeneric()) return true; - auto boundGenericType = typealias->getUnderlyingType() - ->getAs(); - if (!boundGenericType) return false; - - // If our arguments line up with our innermost generic parameters, it's - // a passthrough typealias. - auto innermostGenericParams = typealiasSig.getInnermostGenericParams(); - auto boundArgs = boundGenericType->getGenericArgs(); - if (boundArgs.size() != innermostGenericParams.size()) - return false; + if (typealias->getUnderlyingType()->isEqual( + nominal->getSelfInterfaceType())) { + return true; + } - return std::equal(boundArgs.begin(), boundArgs.end(), - innermostGenericParams.begin(), - [](Type arg, GenericTypeParamType *gp) { - return arg->isEqual(gp); - }); + return false; } Type @@ -2979,7 +2969,7 @@ ExtendedTypeRequest::evaluate(Evaluator &eval, ExtensionDecl *ext) const { PlaceholderType::get, /*packElementOpener*/ nullptr); - const auto extendedType = resolution.resolveType(extendedRepr); + auto extendedType = resolution.resolveType(extendedRepr); if (extendedType->hasError()) return error(); @@ -2987,13 +2977,17 @@ ExtendedTypeRequest::evaluate(Evaluator &eval, ExtensionDecl *ext) const { // Hack to allow extending a generic typealias. if (auto *unboundGeneric = extendedType->getAs()) { if (auto *aliasDecl = dyn_cast(unboundGeneric->getDecl())) { - auto extendedNominal = - aliasDecl->getUnderlyingType()->getAnyNominal(); - if (extendedNominal) + auto underlyingType = aliasDecl->getUnderlyingType(); + if (auto extendedNominal = underlyingType->getAnyNominal()) { return TypeChecker::isPassThroughTypealias( aliasDecl, extendedNominal) ? extendedType : extendedNominal->getDeclaredType(); + } + + if (underlyingType->is()) { + return extendedType; + } } } @@ -3006,8 +3000,9 @@ ExtendedTypeRequest::evaluate(Evaluator &eval, ExtensionDecl *ext) const { return error(); } - // Cannot extend function types, tuple types, etc. - if (!extendedType->getAnyNominal() && + // Cannot extend function types, metatypes, existentials, etc. + if (!extendedType->is() && + !extendedType->getAnyNominal() && !extendedType->is()) { diags.diagnose(ext->getLoc(), diag::non_nominal_extension, extendedType) .highlight(extendedRepr->getSourceRange()); diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp index 6a090189fe40a..2006f0ffd3aaa 100644 --- a/lib/Sema/TypeCheckDeclObjC.cpp +++ b/lib/Sema/TypeCheckDeclObjC.cpp @@ -1319,8 +1319,9 @@ static llvm::Optional shouldMarkClassAsObjC(const ClassDecl *CD) { .limitBehavior(behavior); } else if (CD->getSuperclass().isNull()) { CD->diagnose(diag::invalid_objc_swift_root_class_insert_nsobject) - .fixItInsert(CD->getInherited().front().getLoc(), "NSObject, ") - .limitBehavior(behavior); + .fixItInsert(CD->getInherited().getEntry(0).getLoc(), + "NSObject, ") + .limitBehavior(behavior); } } @@ -1594,7 +1595,7 @@ static bool isEnumObjC(EnumDecl *enumDecl) { if (!isCIntegerType(rawType)) { SourceRange errorRange; if (!enumDecl->getInherited().empty()) - errorRange = enumDecl->getInherited().front().getSourceRange(); + errorRange = enumDecl->getInherited().getEntry(0).getSourceRange(); enumDecl->diagnose(diag::objc_enum_raw_type_not_integer, rawType) .highlight(errorRange); return false; @@ -2892,7 +2893,7 @@ class ObjCImplementationChecker { // Conformances are declared exclusively in the interface, so diagnose any // in the implementation right away. - for (auto &inherited : ext->getInherited()) { + for (auto &inherited : ext->getInherited().getEntries()) { bool isImportedProtocol = false; if (auto protoNominal = inherited.getType()->getAnyNominal()) isImportedProtocol = protoNominal->hasClangNode(); diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index e37ee3b20d588..15d302d7bc40d 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -92,15 +92,13 @@ static Type containsParameterizedProtocolType(Type inheritedTy) { /// file. static void checkInheritanceClause( llvm::PointerUnion declUnion) { - ArrayRef inheritedClause; + auto inheritedClause = InheritedTypes(declUnion).getEntries(); const ExtensionDecl *ext = nullptr; const TypeDecl *typeDecl = nullptr; const Decl *decl; if ((ext = declUnion.dyn_cast())) { decl = ext; - inheritedClause = ext->getInherited(); - // Protocol extensions cannot have inheritance clauses. if (auto proto = ext->getExtendedProtocolDecl()) { if (!inheritedClause.empty()) { @@ -114,7 +112,6 @@ static void checkInheritanceClause( } else { typeDecl = declUnion.get(); decl = typeDecl; - inheritedClause = typeDecl->getInherited(); } // Can this declaration's inheritance clause contain a class or @@ -1968,6 +1965,14 @@ class DeclChecker : public DeclVisitor { target->getModuleFilename()); } + // Report use of package import when no package name is set. + if (ID->getAccessLevel() == AccessLevel::Package && + getASTContext().LangOpts.PackageName.empty()) { + auto &diags = ID->getASTContext().Diags; + diags.diagnose(ID->getLoc(), + diag::access_control_requires_package_name_import); + } + // Report the public import of a private module. if (ID->getASTContext().LangOpts.LibraryLevel == LibraryLevel::API) { auto importer = ID->getModuleContext(); @@ -2655,27 +2660,37 @@ class DeclChecker : public DeclVisitor { void checkUnsupportedNestedType(NominalTypeDecl *NTD) { auto *DC = NTD->getDeclContext(); + + // We don't allow nested types inside inlinable contexts. auto kind = DC->getFragileFunctionKind(); if (kind.kind != FragileFunctionKind::None) { NTD->diagnose(diag::local_type_in_inlinable_function, NTD->getName(), kind.getSelector()); } - // We don't support protocols outside the top level of a file. - if (isa(NTD) && - !NTD->getParent()->isModuleScopeContext()) { - NTD->diagnose(diag::unsupported_nested_protocol, NTD); - NTD->setInvalid(); - return; - } + if (auto *parentDecl = DC->getSelfNominalTypeDecl()) { + // We don't allow types to be nested within a tuple extension. + if (isa(parentDecl)) { + NTD->diagnose(diag::tuple_extension_nested_type, NTD); + return; + } - // We don't support nested types in protocols. - if (auto proto = DC->getSelfProtocolDecl()) { - if (DC->getExtendedProtocolDecl()) { - NTD->diagnose(diag::unsupported_type_nested_in_protocol_extension, NTD, - proto); - } else { - NTD->diagnose(diag::unsupported_type_nested_in_protocol, NTD, proto); + // We don't support protocols outside the top level of a file. + if (isa(NTD) && + !DC->isModuleScopeContext()) { + NTD->diagnose(diag::unsupported_nested_protocol, NTD); + NTD->setInvalid(); + return; + } + + // We don't support nested types in protocols. + if (auto proto = dyn_cast(parentDecl)) { + if (DC->getExtendedProtocolDecl()) { + NTD->diagnose(diag::unsupported_type_nested_in_protocol_extension, NTD, + proto); + } else { + NTD->diagnose(diag::unsupported_type_nested_in_protocol, NTD, proto); + } } } @@ -2731,14 +2746,14 @@ class DeclChecker : public DeclVisitor { // The raw type must be one of the blessed literal convertible types. if (!computeAutomaticEnumValueKind(ED)) { if (!rawTy->is()) { - DE.diagnose(ED->getInherited().front().getSourceRange().Start, + DE.diagnose(ED->getInherited().getStartLoc(), diag::raw_type_not_literal_convertible, rawTy); } } // We need at least one case to have a raw value. if (ED->getAllElements().empty()) { - DE.diagnose(ED->getInherited().front().getSourceRange().Start, + DE.diagnose(ED->getInherited().getStartLoc(), diag::empty_enum_raw_type); } } @@ -2968,7 +2983,7 @@ class DeclChecker : public DeclVisitor { return; // go over the all types directly conformed-to by the extension - for (auto entry : extension->getInherited()) { + for (auto entry : extension->getInherited().getEntries()) { diagnoseIncompatibleWithMoveOnlyType(extension->getLoc(), nomDecl, entry.getType()); } @@ -3470,7 +3485,7 @@ class DeclChecker : public DeclVisitor { if (EED->hasAssociatedValues()) { if (auto rawTy = ED->getRawType()) { EED->diagnose(diag::enum_with_raw_type_case_with_argument); - DE.diagnose(ED->getInherited().front().getSourceRange().Start, + DE.diagnose(ED->getInherited().getStartLoc(), diag::enum_raw_type_here, rawTy); EED->setInvalid(); } @@ -3486,18 +3501,99 @@ class DeclChecker : public DeclVisitor { checkAccessControl(EED); } - void visitExtensionDecl(ExtensionDecl *ED) { - // Produce any diagnostics for the extended type. + /// The extended type must be '(repeat each Element)' or a generic + /// typealias with that underlying type. + static bool isValidExtendedTypeForTupleExtension(ExtensionDecl *ED) { auto extType = ED->getExtendedType(); + auto selfType = ED->getSelfInterfaceType(); + + // The extended type must be '(repeat each Element)'. + if (extType->is()) { + auto *extDecl = extType->getAnyGeneric(); + if (!extDecl->getDeclaredInterfaceType()->isEqual(selfType)) + return false; + } else if (extType->is()) { + if (!extType->isEqual(selfType)) + return false; + } else { + assert(false && "Huh?"); + } + return true; + } + + static void checkTupleExtension(ExtensionDecl *ED) { auto *nominal = ED->getExtendedNominal(); + if (!nominal || !isa(nominal)) + return; + + auto &ctx = ED->getASTContext(); - // Diagnose experimental tuple extensions. - if (nominal && isa(nominal) && - !getASTContext().LangOpts.hasFeature(Feature::TupleConformances)) { + if (!ctx.LangOpts.hasFeature(Feature::TupleConformances)) { ED->diagnose(diag::experimental_tuple_extension); } + if (!isValidExtendedTypeForTupleExtension(ED)) { + ED->diagnose(diag::tuple_extension_wrong_type, + ED->getSelfInterfaceType()); + } + + // Make sure we declare conformance to exactly one protocol. + auto protocols = ED->getLocalProtocols(); + if (protocols.size() != 1) { + ED->diagnose(diag::tuple_extension_one_conformance); + return; + } + + auto *protocol = protocols[0]; + + // Validate the generic signature. + auto genericSig = ED->getGenericSignature(); + + // We have a single parameter pack by construction, if we + // get this far. + auto params = genericSig.getGenericParams(); + assert(params.size() == 1); + assert(params[0]->isParameterPack()); + + // Make sure we have a single conditional requirement, + // 'repeat each Element: P', where 'Element' is our pack + // and 'P' is the protocol above, and nothing else. + bool foundRequirement = false; + auto reqs = genericSig.getRequirements(); + for (auto req : reqs) { + if (req.getKind() == RequirementKind::Conformance && + req.getFirstType()->isEqual(params[0]) && + req.getProtocolDecl() == protocol) { + assert(!foundRequirement); + foundRequirement = true; + } else { + if (req.getKind() == RequirementKind::Layout) { + ED->diagnose(diag::tuple_extension_extra_requirement, + req.getFirstType(), + unsigned(RequirementKind::Conformance), + ctx.getAnyObjectType()); + } else { + ED->diagnose(diag::tuple_extension_extra_requirement, + req.getFirstType(), + unsigned(req.getKind()), + req.getSecondType()); + } + } + } + + if (!foundRequirement) { + ED->diagnose(diag::tuple_extension_missing_requirement, + params[0], protocol->getDeclaredInterfaceType()); + } + } + + void visitExtensionDecl(ExtensionDecl *ED) { + // Produce any diagnostics for the extended type. + auto extType = ED->getExtendedType(); + + auto *nominal = ED->getExtendedNominal(); + if (nominal == nullptr) { const bool wasAlreadyInvalid = ED->isInvalid(); ED->setInvalid(); @@ -3625,6 +3721,8 @@ class DeclChecker : public DeclVisitor { TypeChecker::checkDistributedActor(SF, nominal); diagnoseIncompatibleProtocolsForMoveOnlyType(ED); + + checkTupleExtension(ED); } void visitTopLevelCodeDecl(TopLevelCodeDecl *TLCD) { diff --git a/lib/Sema/TypeCheckDistributed.cpp b/lib/Sema/TypeCheckDistributed.cpp index 24c4d8769c39c..2ee97ec36dbf3 100644 --- a/lib/Sema/TypeCheckDistributed.cpp +++ b/lib/Sema/TypeCheckDistributed.cpp @@ -155,10 +155,8 @@ void swift::diagnoseDistributedFunctionInNonDistributedActorProtocol( } else { // Similar to how Sendable FitIts do this, we insert at the end of // the inherited types. - ASTContext &ctx = proto->getASTContext(); - SourceLoc fixItLoc = proto->getInherited().back().getSourceRange().End; - fixItLoc = Lexer::getLocForEndOfToken(ctx.SourceMgr, fixItLoc); - diag.fixItInsert(fixItLoc, ", DistributedActor"); + SourceLoc fixItLoc = proto->getInherited().getEndLoc(); + diag.fixItInsertAfter(fixItLoc, ", DistributedActor"); } } @@ -173,10 +171,8 @@ void swift::addCodableFixIt( SourceLoc fixItLoc = nominal->getBraces().Start; diag.fixItInsert(fixItLoc, ": Codable"); } else { - ASTContext &ctx = nominal->getASTContext(); - SourceLoc fixItLoc = nominal->getInherited().back().getSourceRange().End; - fixItLoc = Lexer::getLocForEndOfToken(ctx.SourceMgr, fixItLoc); - diag.fixItInsert(fixItLoc, ", Codable"); + SourceLoc fixItLoc = nominal->getInherited().getEndLoc(); + diag.fixItInsertAfter(fixItLoc, ", Codable"); } } diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index b24dad65f368f..1a65cb3fe9ba4 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -565,12 +565,15 @@ void TypeChecker::checkShadowedGenericParams(GenericContext *dc) { /// Generic types /// -/// Collect additional requirements into \p sameTypeReqs. +/// Collect additional requirements into \p extraReqs. static void collectAdditionalExtensionRequirements( - Type type, SmallVectorImpl &sameTypeReqs) { + Type type, SmallVectorImpl &extraReqs) { if (type->is()) return; + if (type->is()) + return; + // Find the nominal type declaration and its parent type. if (type->is()) type = type->getCanonicalType(); @@ -584,7 +587,7 @@ static void collectAdditionalExtensionRequirements( paramProtoTy->getRequirements( protoTy->getDecl()->getSelfInterfaceType(), - sameTypeReqs); + extraReqs); } Type parentType = type->getNominalParent(); @@ -592,7 +595,7 @@ static void collectAdditionalExtensionRequirements( // Visit the parent type, if there is one. if (parentType) { - collectAdditionalExtensionRequirements(parentType, sameTypeReqs); + collectAdditionalExtensionRequirements(parentType, extraReqs); } // Find the nominal type. @@ -601,6 +604,8 @@ static void collectAdditionalExtensionRequirements( if (!nominal) { type = typealias->getUnderlyingType(); nominal = type->getNominalOrBoundGenericNominal(); + if (!nominal && type->is()) + nominal = type->getASTContext().getBuiltinTupleDecl(); } // If we have a bound generic type, add same-type requirements for each of @@ -611,8 +616,8 @@ static void collectAdditionalExtensionRequirements( auto *gp = genericParams->getParams()[gpIndex]; auto gpType = gp->getDeclaredInterfaceType(); - sameTypeReqs.emplace_back(RequirementKind::SameType, gpType, - currentBoundType->getGenericArgs()[gpIndex]); + extraReqs.emplace_back(RequirementKind::SameType, gpType, + currentBoundType->getGenericArgs()[gpIndex]); } } @@ -620,7 +625,7 @@ static void collectAdditionalExtensionRequirements( // generic signature. if (typealias && TypeChecker::isPassThroughTypealias(typealias, nominal)) { for (auto req : typealias->getGenericSignature().getRequirements()) - sameTypeReqs.push_back(req); + extraReqs.push_back(req); } } @@ -695,7 +700,7 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator, GenericSignature parentSig; SmallVector inferenceSources; - SmallVector sameTypeReqs; + SmallVector extraReqs; if (auto VD = dyn_cast(GC->getAsDecl())) { parentSig = GC->getParentForLookup()->getGenericSignatureOfContext(); @@ -769,13 +774,23 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator, } } } else if (auto *ext = dyn_cast(GC)) { - parentSig = ext->getExtendedNominal()->getGenericSignatureOfContext(); - genericParams = nullptr; + collectAdditionalExtensionRequirements(ext->getExtendedType(), extraReqs); + + auto *extendedNominal = ext->getExtendedNominal(); - collectAdditionalExtensionRequirements(ext->getExtendedType(), sameTypeReqs); + if (isa(extendedNominal)) { + genericParams = ext->getGenericParams(); + } else { + parentSig = extendedNominal->getGenericSignatureOfContext(); + genericParams = nullptr; + } // Re-use the signature of the type being extended by default. - if (sameTypeReqs.empty() && !ext->getTrailingWhereClause()) { + // For tuple extensions, always build a new signature to get + // the right sugared types, since we don't want to expose the + // name of the generic parameter of BuiltinTupleDecl itself. + if (extraReqs.empty() && !ext->getTrailingWhereClause() && + !isa(extendedNominal)) { return parentSig; } @@ -788,7 +803,7 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator, auto request = InferredGenericSignatureRequest{ parentSig.getPointer(), genericParams, WhereClauseOwner(GC), - sameTypeReqs, inferenceSources, + extraReqs, inferenceSources, allowConcreteGenericParams}; auto sig = evaluateOrDefault(ctx.evaluator, request, GenericSignatureWithError()).getPointer(); diff --git a/lib/Sema/TypeCheckMacros.cpp b/lib/Sema/TypeCheckMacros.cpp index c73a6b5c6a374..5313ab221e60e 100644 --- a/lib/Sema/TypeCheckMacros.cpp +++ b/lib/Sema/TypeCheckMacros.cpp @@ -1548,12 +1548,56 @@ swift::expandAttributes(CustomAttr *attr, MacroDecl *macro, Decl *member) { return macroSourceFile->getBufferID(); } +// Collect the protocol conformances that the macro asked about but were +// not already present on the declaration. +static TinyPtrVector getIntroducedConformances( + NominalTypeDecl *nominal, MacroRole role, MacroDecl *macro, + SmallVectorImpl *potentialConformances = nullptr) { + SmallVector potentialConformancesBuffer; + if (!potentialConformances) + potentialConformances = &potentialConformancesBuffer; + macro->getIntroducedConformances(nominal, role, *potentialConformances); + + TinyPtrVector introducedConformances; + for (auto protocol : *potentialConformances) { + SmallVector existingConformances; + nominal->lookupConformance(protocol, existingConformances); + + bool hasExistingConformance = llvm::any_of( + existingConformances, + [&](ProtocolConformance *conformance) { + return conformance->getSourceKind() != + ConformanceEntryKind::PreMacroExpansion; + }); + + if (!hasExistingConformance) { + introducedConformances.push_back(protocol); + } + } + + return introducedConformances; +} + llvm::Optional swift::expandMembers(CustomAttr *attr, MacroDecl *macro, Decl *decl) { + auto nominal = dyn_cast(decl); + if (!nominal) { + auto ext = dyn_cast(decl); + if (!ext) + return llvm::None; + + nominal = ext->getExtendedNominal(); + if (!nominal) + return llvm::None; + } + auto introducedConformances = getIntroducedConformances( + nominal, MacroRole::Member, macro); + // Evaluate the macro. auto macroSourceFile = ::evaluateAttachedMacro(macro, decl, attr, - /*passParentContext=*/false, MacroRole::Member); + /*passParentContext=*/false, MacroRole::Member, + introducedConformances); if (!macroSourceFile) return llvm::None; @@ -1625,22 +1669,9 @@ swift::expandExtensions(CustomAttr *attr, MacroDecl *macro, return llvm::None; } - // Collect the protocol conformances that the macro can add. The - // macro should not add conformances that are already stated in - // the original source. - SmallVector potentialConformances; - macro->getIntroducedConformances(nominal, potentialConformances); - - SmallVector introducedConformances; - for (auto protocol : potentialConformances) { - SmallVector existingConformances; - nominal->lookupConformance(protocol, existingConformances); - if (existingConformances.empty()) { - introducedConformances.push_back(protocol); - } - } - + auto introducedConformances = getIntroducedConformances( + nominal, MacroRole::Extension, macro, &potentialConformances); auto macroSourceFile = ::evaluateAttachedMacro(macro, nominal, attr, /*passParentContext=*/false, role, introducedConformances); @@ -1678,7 +1709,8 @@ swift::expandExtensions(CustomAttr *attr, MacroDecl *macro, // Extension macros can only add conformances that are documented by // the `@attached(extension)` attribute. - for (auto inherited : extension->getInherited()) { + auto inheritedTypes = extension->getInherited(); + for (auto i : inheritedTypes.getIndices()) { auto constraint = TypeResolution::forInterface( extension->getDeclContext(), @@ -1686,7 +1718,7 @@ swift::expandExtensions(CustomAttr *attr, MacroDecl *macro, /*unboundTyOpener*/ nullptr, /*placeholderHandler*/ nullptr, /*packElementOpener*/ nullptr) - .resolveType(inherited.getTypeRepr()); + .resolveType(inheritedTypes.getTypeRepr(i)); // Already diagnosed or will be diagnosed later. if (constraint->is() || !constraint->isConstraintType()) @@ -1829,9 +1861,9 @@ ConcreteDeclRef ResolveMacroRequest::evaluate(Evaluator &evaluator, } ArrayRef -ResolveExtensionMacroConformances::evaluate(Evaluator &evaluator, - const MacroRoleAttr *attr, - const Decl *decl) const { +ResolveMacroConformances::evaluate(Evaluator &evaluator, + const MacroRoleAttr *attr, + const Decl *decl) const { auto *dc = decl->getDeclContext(); auto &ctx = dc->getASTContext(); diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 8cf2cbc2431b3..839a7be26fddf 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1901,13 +1901,12 @@ void MultiConformanceChecker::checkAllConformances() { static void diagnoseConformanceImpliedByConditionalConformance( DiagnosticEngine &Diags, NormalProtocolConformance *conformance, NormalProtocolConformance *implyingConf, bool issueFixit) { - Type T = conformance->getType(); auto proto = conformance->getProtocol(); Type protoType = proto->getDeclaredInterfaceType(); auto implyingProto = implyingConf->getProtocol()->getDeclaredInterfaceType(); auto loc = implyingConf->getLoc(); Diags.diagnose(loc, diag::conditional_conformances_cannot_imply_conformances, - T, implyingProto, protoType); + conformance->getType(), implyingProto, protoType); if (!issueFixit) return; @@ -1949,11 +1948,7 @@ static void diagnoseConformanceImpliedByConditionalConformance( llvm::raw_svector_ostream prefixStream(prefix); llvm::raw_svector_ostream suffixStream(suffix); - ValueDecl *decl = T->getAnyNominal(); - if (!decl) - decl = T->getAnyGeneric(); - - prefixStream << "extension " << decl->getName() << ": " << protoType << " "; + prefixStream << "extension " << ext->getExtendedType() << ": " << protoType << " "; suffixStream << " {\n" << indent << extraIndent << "<#witnesses#>\n" << indent << "}\n\n" @@ -3548,6 +3543,18 @@ static bool isNSObjectProtocol(ProtocolDecl *proto) { return proto->hasClangNode(); } +static Type getTupleConformanceTypeWitness(DeclContext *dc, + AssociatedTypeDecl *assocType) { + auto genericSig = dc->getGenericSignatureOfContext(); + assert(genericSig.getGenericParams().size() == 1); + + auto paramTy = genericSig.getGenericParams()[0]; + auto elementTy = DependentMemberType::get(paramTy, assocType); + auto expansionTy = PackExpansionType::get(elementTy, paramTy); + + return TupleType::get(TupleTypeElt(expansionTy), dc->getASTContext()); +} + bool swift:: printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter, Type AdopterTy, SourceLoc TypeLoc, raw_ostream &OS) { @@ -3588,7 +3595,15 @@ printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter, Printer << "public "; if (auto MissingTypeWitness = dyn_cast(Requirement)) { - Printer << "typealias " << MissingTypeWitness->getName() << " = <#type#>"; + Printer << "typealias " << MissingTypeWitness->getName() << " = "; + + if (isa(Adopter->getSelfNominalTypeDecl())) { + auto expectedTy = getTupleConformanceTypeWitness(Adopter, MissingTypeWitness); + Printer << expectedTy.getString(); + } else { + Printer << "<#type#>"; + } + Printer << "\n"; } else { if (isa(Requirement)) { @@ -3899,17 +3914,25 @@ diagnoseMissingWitnesses(MissingWitnessDiagnosisKind Kind) { // Issue diagnostics for witness types. if (auto MissingTypeWitness = dyn_cast(VD)) { + llvm::Optional diag; + if (isa(DC->getSelfNominalTypeDecl())) { + auto expectedTy = getTupleConformanceTypeWitness(DC, MissingTypeWitness); + diag.emplace(Diags.diagnose(MissingTypeWitness, diag::no_witnesses_type_tuple, + MissingTypeWitness, expectedTy)); + } else { + diag.emplace(Diags.diagnose(MissingTypeWitness, diag::no_witnesses_type, + MissingTypeWitness)); + } if (SameFile) { // If the protocol member decl is in the same file of the stub, // we can directly associate the fixit with the note issued to the // requirement. - Diags.diagnose(MissingTypeWitness, diag::no_witnesses_type, - MissingTypeWitness).fixItInsertAfter(FixitLocation, FixIt); + diag->fixItInsertAfter(FixitLocation, FixIt); } else { + diag.value().flush(); + // Otherwise, we have to issue another note to carry the fixit, // because editor may assume the fixit is in the same file with the note. - Diags.diagnose(MissingTypeWitness, diag::no_witnesses_type, - MissingTypeWitness); if (EditorMode) { Diags.diagnose(ComplainLoc, diag::missing_witnesses_general) .fixItInsertAfter(FixitLocation, FixIt); @@ -4618,7 +4641,7 @@ swift::checkTypeWitness(Type type, AssociatedTypeDecl *assocType, auto &ctx = assocType->getASTContext(); if (type->hasError()) - return ErrorType::get(ctx); + return CheckTypeWitnessResult::forError(); const auto proto = Conf->getProtocol(); const auto dc = Conf->getDeclContext(); @@ -4629,14 +4652,14 @@ swift::checkTypeWitness(Type type, AssociatedTypeDecl *assocType, if (ctx.isRecursivelyConstructingRequirementMachine(sig.getCanonicalSignature()) || ctx.isRecursivelyConstructingRequirementMachine(proto) || proto->isComputingRequirementSignature()) - return ErrorType::get(ctx); + return CheckTypeWitnessResult::forError(); // No move-only type can witness an associatedtype requirement. if (type->isPureMoveOnly()) { // describe the failure reason as it not conforming to Copyable auto *copyable = ctx.getProtocol(KnownProtocolKind::Copyable); assert(copyable && "missing _Copyable protocol!"); - return CheckTypeWitnessResult(copyable->getDeclaredInterfaceType()); + return CheckTypeWitnessResult::forConformance(copyable); } const auto depTy = DependentMemberType::get(proto->getSelfInterfaceType(), @@ -4661,7 +4684,7 @@ swift::checkTypeWitness(Type type, AssociatedTypeDecl *assocType, superclass = dc->mapTypeIntoContext(superclass); } if (!superclass->isExactSuperclassOf(contextType)) - return superclass; + return CheckTypeWitnessResult::forSuperclass(superclass); } auto *module = dc->getParentModule(); @@ -4673,7 +4696,7 @@ swift::checkTypeWitness(Type type, AssociatedTypeDecl *assocType, /*allowMissing=*/reqProto->isSpecificProtocol( KnownProtocolKind::Sendable)) .isInvalid()) - return CheckTypeWitnessResult(reqProto->getDeclaredInterfaceType()); + return CheckTypeWitnessResult::forConformance(reqProto); // FIXME: Why is conformsToProtocol() not enough? The stdlib doesn't // build unless we fail here while inferring an associated type @@ -4686,17 +4709,28 @@ swift::checkTypeWitness(Type type, AssociatedTypeDecl *assocType, decl->getGenericEnvironmentOfContext()); for (auto replacement : subMap.getReplacementTypes()) { if (replacement->hasError()) - return CheckTypeWitnessResult(reqProto->getDeclaredInterfaceType()); + return CheckTypeWitnessResult::forConformance(reqProto); } } } if (sig->requiresClass(depTy) && - !contextType->satisfiesClassConstraint()) - return CheckTypeWitnessResult(module->getASTContext().getAnyObjectType()); + !contextType->satisfiesClassConstraint()) { + return CheckTypeWitnessResult::forLayout( + module->getASTContext().getAnyObjectType()); + } + + // Tuple conformances can only witness associated types by projecting them + // element-wise. + if (isa(dc->getSelfNominalTypeDecl())) { + auto expectedTy = getTupleConformanceTypeWitness(dc, assocType); + if (!expectedTy->isEqual(type)) { + return CheckTypeWitnessResult::forTuple(expectedTy); + } + } // Success! - return CheckTypeWitnessResult(); + return CheckTypeWitnessResult::forSuccess(); } ResolveWitnessResult @@ -4883,15 +4917,39 @@ ResolveWitnessResult ConformanceChecker::resolveTypeWitnessViaLookup( auto &diags = conformance->getDeclContext()->getASTContext().Diags; for (auto candidate : nonViable) { if (candidate.first->getDeclaredInterfaceType()->hasError() || - candidate.second.isError()) + candidate.second.getKind() == CheckTypeWitnessResult::Error) continue; - diags.diagnose( - candidate.first, - diag::protocol_witness_nonconform_type, - candidate.first->getDeclaredInterfaceType(), - candidate.second.getRequirement(), - candidate.second.isConformanceRequirement()); + switch (candidate.second.getKind()) { + case CheckTypeWitnessResult::Success: + case CheckTypeWitnessResult::Error: + llvm_unreachable("Should not end up here"); + + case CheckTypeWitnessResult::Conformance: + case CheckTypeWitnessResult::Layout: + diags.diagnose( + candidate.first, + diag::protocol_type_witness_unsatisfied_conformance, + candidate.first->getDeclaredInterfaceType(), + candidate.second.getRequirement()); + break; + + case CheckTypeWitnessResult::Superclass: + diags.diagnose( + candidate.first, + diag::protocol_type_witness_unsatisfied_superclass, + candidate.first->getDeclaredInterfaceType(), + candidate.second.getRequirement()); + break; + + case CheckTypeWitnessResult::Tuple: + diags.diagnose( + candidate.first, + diag::protocol_type_witness_tuple, + candidate.first->getDeclaredInterfaceType(), + candidate.second.getRequirement()); + break; + } } }); @@ -5562,15 +5620,15 @@ void swift::diagnoseConformanceFailure(Type T, auto rawType = enumDecl->getRawType(); - diags.diagnose(enumDecl->getInherited()[0].getSourceRange().Start, - diag::enum_raw_type_nonconforming_and_nonsynthable, - T, rawType); + diags.diagnose(enumDecl->getInherited().getStartLoc(), + diag::enum_raw_type_nonconforming_and_nonsynthable, T, + rawType); // If the reason is that the raw type does not conform to // Equatable, say so. if (!TypeChecker::conformsToKnownProtocol( rawType, KnownProtocolKind::Equatable, DC->getParentModule())) { - SourceLoc loc = enumDecl->getInherited()[0].getSourceRange().Start; + SourceLoc loc = enumDecl->getInherited().getStartLoc(); diags.diagnose(loc, diag::enum_raw_type_not_equatable, rawType); return; } @@ -5592,13 +5650,9 @@ void swift::diagnoseConformanceFailure(Type T, if (!classDecl) return; - auto inheritedClause = classDecl->getInherited(); - for (unsigned i : indices(inheritedClause)) { - auto &inherited = inheritedClause[i]; - - // Find the inherited type. - InheritedTypeRequest request{classDecl, i, TypeResolutionStage::Interface}; - Type inheritedTy = evaluateOrDefault(ctx.evaluator, request, Type()); + auto inheritedTypes = classDecl->getInherited(); + for (auto i : inheritedTypes.getIndices()) { + Type inheritedTy = inheritedTypes.getResolvedType(i); // If it's a class, we cannot suggest a different class to inherit // from. @@ -5608,7 +5662,8 @@ void swift::diagnoseConformanceFailure(Type T, // Is it the NSObject protocol? if (auto protoTy = inheritedTy->getAs()) { if (isNSObjectProtocol(protoTy->getDecl())) { - diag.fixItReplace(inherited.getSourceRange(), "NSObject"); + diag.fixItReplace(inheritedTypes.getEntry(i).getSourceRange(), + "NSObject"); return; } } @@ -6638,8 +6693,8 @@ void TypeChecker::checkConformancesInContext(IterableDeclContext *idc) { DerivedConformance::derivesProtocolConformance(dc, enumDecl, diag.Protocol) && enumDecl->hasRawType() && - enumDecl->getInherited()[0].getSourceRange().isValid()) { - auto inheritedLoc = enumDecl->getInherited()[0].getSourceRange().Start; + enumDecl->getInherited().getStartLoc().isValid()) { + auto inheritedLoc = enumDecl->getInherited().getStartLoc(); Context.Diags.diagnose( inheritedLoc, diag::enum_declares_rawrep_with_raw_type, dc->getDeclaredInterfaceType(), enumDecl->getRawType()); diff --git a/lib/Sema/TypeCheckProtocol.h b/lib/Sema/TypeCheckProtocol.h index 3f2c016dd10f7..1ee910834a14e 100644 --- a/lib/Sema/TypeCheckProtocol.h +++ b/lib/Sema/TypeCheckProtocol.h @@ -72,23 +72,69 @@ struct TypeWitnessConflict { /// /// This class evaluates true if an error occurred. class CheckTypeWitnessResult { - Type Requirement; +public: + enum Kind { + Success, + + /// Type witness contains an error type. + Error, + + /// Type witness does not satisfy a conformance requirement on + /// the associated type. + Conformance, + + /// Type witness does not satisfy a superclass requirement on + /// the associated type. + Superclass, + + /// Type witness does not satisfy a layout requirement on + /// the associated type. + Layout, + + /// Type witness of a tuple conformance does not have the form + /// (repeat (each Element).A). + Tuple + } kind; + +private: + Type reqt; + + CheckTypeWitnessResult() : kind(Success) {} + + CheckTypeWitnessResult(Kind kind, Type reqt) + : kind(kind), reqt(reqt) {} public: - CheckTypeWitnessResult() { } - CheckTypeWitnessResult(Type reqt) : Requirement(reqt) {} + static CheckTypeWitnessResult forSuccess() { + return CheckTypeWitnessResult(Success, Type()); + } - Type getRequirement() const { return Requirement; } - bool isConformanceRequirement() const { - return Requirement->isExistentialType(); + static CheckTypeWitnessResult forError() { + return CheckTypeWitnessResult(Error, Type()); } - bool isSuperclassRequirement() const { - return !isConformanceRequirement(); + + static CheckTypeWitnessResult forConformance(ProtocolDecl *proto) { + auto reqt = proto->getDeclaredInterfaceType(); + return CheckTypeWitnessResult(Conformance, reqt); } - bool isError() const { - return Requirement->is(); + + static CheckTypeWitnessResult forSuperclass(Type reqt) { + assert(reqt->getClassOrBoundGenericClass()); + return CheckTypeWitnessResult(Superclass, reqt); + } + + static CheckTypeWitnessResult forLayout(Type reqt) { + return CheckTypeWitnessResult(Layout, reqt); + } + + static CheckTypeWitnessResult forTuple(Type reqt) { + return CheckTypeWitnessResult(Tuple, reqt); } - explicit operator bool() const { return !Requirement.isNull(); } + + Kind getKind() const { return kind; } + Type getRequirement() const { return reqt; } + + explicit operator bool() const { return kind != Success; } }; /// Check whether the given type witness can be used for the given @@ -1057,7 +1103,7 @@ class AssociatedTypeInference { /// Information about a failed, defaulted associated type. const AssociatedTypeDecl *failedDefaultedAssocType = nullptr; Type failedDefaultedWitness; - CheckTypeWitnessResult failedDefaultedResult; + CheckTypeWitnessResult failedDefaultedResult = CheckTypeWitnessResult::forSuccess(); /// Information about a failed, derived associated type. AssociatedTypeDecl *failedDerivedAssocType = nullptr; diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp index 33a95b63aafeb..d2169b5451f8e 100644 --- a/lib/Sema/TypeCheckProtocolInference.cpp +++ b/lib/Sema/TypeCheckProtocolInference.cpp @@ -593,8 +593,10 @@ AssociatedTypeInference::inferTypeWitnessesViaAssociatedType( // Look for types with the given default name that have appropriate // @_implements attributes. SmallVector lookupResults; - dc->lookupQualified(adoptee->getAnyNominal(), defaultName, - adoptee->getAnyNominal()->getStartLoc(), + dc->lookupQualified(dc->getSelfNominalTypeDecl(), defaultName, + isa(dc) + ? cast(dc)->getStartLoc() + : cast(dc)->getStartLoc(), subOptions, lookupResults); InferredAssociatedTypesByWitnesses result; @@ -819,7 +821,7 @@ Type AssociatedTypeInference::computeFixedTypeWitness( // Look at all of the inherited protocols to determine whether they // require a fixed type for this associated type. - for (auto conformedProto : adoptee->getAnyNominal()->getAllProtocols()) { + for (auto conformedProto : dc->getSelfNominalTypeDecl()->getAllProtocols()) { if (conformedProto != assocType->getProtocol() && !conformedProto->inheritsFrom(assocType->getProtocol())) continue; @@ -888,7 +890,7 @@ AssociatedTypeInference::computeDerivedTypeWitness( return std::make_pair(Type(), nullptr); // Can we derive conformances for this protocol and adoptee? - NominalTypeDecl *derivingTypeDecl = adoptee->getAnyNominal(); + NominalTypeDecl *derivingTypeDecl = dc->getSelfNominalTypeDecl(); if (!DerivedConformance::derivesProtocolConformance(dc, derivingTypeDecl, proto)) return std::make_pair(Type(), nullptr); @@ -942,7 +944,7 @@ void AssociatedTypeInference::collectAbstractTypeWitnesses( // First, look at all the protocols the adoptee conforms to and feed the // same-type constraints in their requirement signatures to the system. for (auto *const conformedProto : - adoptee->getAnyNominal()->getAllProtocols(/*sorted=*/true)) { + dc->getSelfNominalTypeDecl()->getAllProtocols(/*sorted=*/true)) { // FIXME: The RequirementMachine will assert on re-entrant construction. // We should find a more principled way of breaking this cycle. if (ctx.isRecursivelyConstructingRequirementMachine( @@ -1407,10 +1409,10 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses( // witness failure and we haven't seen one already, write it down. auto *defaultedAssocType = witness.getDefaultedAssocType(); if (defaultedAssocType && !failedDefaultedAssocType && - !failed.isError()) { + failed.getKind() != CheckTypeWitnessResult::Error) { failedDefaultedAssocType = defaultedAssocType; failedDefaultedWitness = type; - failedDefaultedResult = std::move(failed); + failedDefaultedResult = failed; } return assocType; @@ -1936,13 +1938,43 @@ bool AssociatedTypeInference::diagnoseNoSolutions( failedDefaultedResult](NormalProtocolConformance *conformance) { auto proto = conformance->getProtocol(); auto &diags = proto->getASTContext().Diags; - diags.diagnose(failedDefaultedAssocType, - diag::default_associated_type_req_fail, - failedDefaultedWitness, - failedDefaultedAssocType, - proto->getDeclaredInterfaceType(), - failedDefaultedResult.getRequirement(), - failedDefaultedResult.isConformanceRequirement()); + + switch (failedDefaultedResult.getKind()) { + case CheckTypeWitnessResult::Success: + case CheckTypeWitnessResult::Error: + llvm_unreachable("Should not end up here"); + + case CheckTypeWitnessResult::Conformance: + case CheckTypeWitnessResult::Layout: + diags.diagnose( + failedDefaultedAssocType, + diag::default_associated_type_unsatisfied_conformance, + failedDefaultedWitness, + failedDefaultedAssocType, + proto->getDeclaredInterfaceType(), + failedDefaultedResult.getRequirement()); + break; + + case CheckTypeWitnessResult::Superclass: + diags.diagnose( + failedDefaultedAssocType, + diag::default_associated_type_unsatisfied_superclass, + failedDefaultedWitness, + failedDefaultedAssocType, + proto->getDeclaredInterfaceType(), + failedDefaultedResult.getRequirement()); + break; + + case CheckTypeWitnessResult::Tuple: + diags.diagnose( + failedDefaultedAssocType, + diag::default_associated_type_tuple, + failedDefaultedWitness, + failedDefaultedAssocType, + proto->getDeclaredInterfaceType(), + failedDefaultedResult.getRequirement()); + break; + } }); return true; @@ -1977,12 +2009,12 @@ bool AssociatedTypeInference::diagnoseNoSolutions( diags.diagnose(assocType, diag::bad_associated_type_deduction, assocType, proto); for (const auto &failed : failedSet) { - if (failed.Result.isError()) + if (failed.Result.getKind() == CheckTypeWitnessResult::Error) continue; if ((!failed.TypeWitness->getAnyNominal() || failed.TypeWitness->isExistentialType()) && - failed.Result.isConformanceRequirement()) { + failed.Result.getKind() != CheckTypeWitnessResult::Superclass) { Type resultType; SourceRange typeRange; if (auto *var = dyn_cast(failed.Witness)) { @@ -2018,7 +2050,7 @@ bool AssociatedTypeInference::diagnoseNoSolutions( continue; } if (!failed.TypeWitness->getClassOrBoundGenericClass() && - failed.Result.isSuperclassRequirement()) { + failed.Result.getKind() == CheckTypeWitnessResult::Superclass) { diags.diagnose(failed.Witness, diag::associated_type_witness_inherit_impossible, assocType, failed.TypeWitness, @@ -2026,11 +2058,36 @@ bool AssociatedTypeInference::diagnoseNoSolutions( continue; } - diags.diagnose(failed.Witness, - diag::associated_type_deduction_witness_failed, - assocType, failed.TypeWitness, - failed.Result.getRequirement(), - failed.Result.isConformanceRequirement()); + switch (failed.Result.getKind()) { + case CheckTypeWitnessResult::Success: + case CheckTypeWitnessResult::Error: + llvm_unreachable("Should not end up here"); + + case CheckTypeWitnessResult::Conformance: + case CheckTypeWitnessResult::Layout: + diags.diagnose( + failed.Witness, + diag::associated_type_deduction_unsatisfied_conformance, + assocType, failed.TypeWitness, + failed.Result.getRequirement()); + break; + + case CheckTypeWitnessResult::Superclass: + diags.diagnose( + failed.Witness, + diag::associated_type_deduction_unsatisfied_superclass, + assocType, failed.TypeWitness, + failed.Result.getRequirement()); + break; + + case CheckTypeWitnessResult::Tuple: + diags.diagnose( + failed.Witness, + diag::associated_type_deduction_tuple, + assocType, failed.TypeWitness, + failed.Result.getRequirement()); + break; + } } }); diff --git a/lib/Sema/TypeCheckRequestFunctions.cpp b/lib/Sema/TypeCheckRequestFunctions.cpp index 8a6c0f7c438f2..b956c5d9ed949 100644 --- a/lib/Sema/TypeCheckRequestFunctions.cpp +++ b/lib/Sema/TypeCheckRequestFunctions.cpp @@ -71,7 +71,7 @@ Type InheritedTypeRequest::evaluate( break; } - const TypeLoc &typeLoc = getInheritedTypeLocAtIndex(decl, index); + const TypeLoc &typeLoc = InheritedTypes(decl).getEntry(index); Type inheritedType; if (typeLoc.getTypeRepr()) @@ -103,7 +103,7 @@ SuperclassTypeRequest::evaluate(Evaluator &evaluator, return Type(); } - for (unsigned int idx : indices(nominalDecl->getInherited())) { + for (unsigned int idx : nominalDecl->getInherited().getIndices()) { auto result = evaluator(InheritedTypeRequest{nominalDecl, idx, stage}); if (auto err = result.takeError()) { @@ -140,7 +140,7 @@ SuperclassTypeRequest::evaluate(Evaluator &evaluator, Type EnumRawTypeRequest::evaluate(Evaluator &evaluator, EnumDecl *enumDecl) const { - for (unsigned int idx : indices(enumDecl->getInherited())) { + for (unsigned int idx : enumDecl->getInherited().getIndices()) { auto inheritedTypeResult = evaluator( InheritedTypeRequest{enumDecl, idx, TypeResolutionStage::Interface}); diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index ec7747da1dcce..fa77dae7e5967 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -622,13 +622,6 @@ llvm::Optional typeCheckTarget(constraints::SyntacticElementTarget &target, TypeCheckExprOptions options = TypeCheckExprOptions()); -/// Return the type of operator function for specified LHS, or a null -/// \c Type on error. -FunctionType *getTypeOfCompletionOperator(DeclContext *DC, Expr *LHS, - Identifier opName, - DeclRefKind refKind, - ConcreteDeclRef &refdDecl); - /// Remove any solutions from the provided vector that require more fixes than /// the best score or don't contain a type for the code completion token. void filterSolutionsForCodeCompletion( diff --git a/lib/Serialization/ModuleFile.h b/lib/Serialization/ModuleFile.h index e589d12e05500..9029b718ccdbc 100644 --- a/lib/Serialization/ModuleFile.h +++ b/lib/Serialization/ModuleFile.h @@ -621,6 +621,11 @@ class ModuleFile return Core->Bits.HasHermeticSealAtLink; } + /// Whether this module was built using embedded Swift. + bool isEmbeddedSwiftModule() const { + return Core->Bits.IsEmbeddedSwiftModule; + } + /// Whether this module was built with C++ interoperability enabled. bool hasCxxInteroperability() const { return Core->Bits.HasCxxInteroperability; diff --git a/lib/Serialization/ModuleFileSharedCore.cpp b/lib/Serialization/ModuleFileSharedCore.cpp index a6481adf40bf1..88005f7941fda 100644 --- a/lib/Serialization/ModuleFileSharedCore.cpp +++ b/lib/Serialization/ModuleFileSharedCore.cpp @@ -158,6 +158,9 @@ static bool readOptionsBlock(llvm::BitstreamCursor &cursor, case options_block::HAS_HERMETIC_SEAL_AT_LINK: extendedInfo.setHasHermeticSealAtLink(true); break; + case options_block::IS_EMBEDDED_SWIFT_MODULE: + extendedInfo.setIsEmbeddedSwiftModule(true); + break; case options_block::IS_TESTABLE: extendedInfo.setIsTestable(true); break; @@ -1405,6 +1408,7 @@ ModuleFileSharedCore::ModuleFileSharedCore( Bits.IsSIB = extInfo.isSIB(); Bits.IsStaticLibrary = extInfo.isStaticLibrary(); Bits.HasHermeticSealAtLink = extInfo.hasHermeticSealAtLink(); + Bits.IsEmbeddedSwiftModule = extInfo.isEmbeddedSwiftModule(); Bits.IsTestable = extInfo.isTestable(); Bits.ResilienceStrategy = unsigned(extInfo.getResilienceStrategy()); Bits.IsImplicitDynamicEnabled = extInfo.isImplicitDynamicEnabled(); diff --git a/lib/Serialization/ModuleFileSharedCore.h b/lib/Serialization/ModuleFileSharedCore.h index 13824c66a3407..0ff7a930db529 100644 --- a/lib/Serialization/ModuleFileSharedCore.h +++ b/lib/Serialization/ModuleFileSharedCore.h @@ -367,6 +367,9 @@ class ModuleFileSharedCore { /// Whether this module was built with -experimental-hermetic-seal-at-link. unsigned HasHermeticSealAtLink : 1; + /// Whether this module was built with embedded Swift. + unsigned IsEmbeddedSwiftModule : 1; + /// Whether this module file is compiled with '-enable-testing'. unsigned IsTestable : 1; diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 61f3887798ea9..eec191d657a8e 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,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 = 803; // removed initializes and accesses attributes +const uint16_t SWIFTMODULE_VERSION_MINOR = 804; // embedded swift modules /// A standard hash seed used for all string hashes in a serialized module. /// @@ -885,6 +885,7 @@ namespace options_block { IS_SIB, IS_STATIC_LIBRARY, HAS_HERMETIC_SEAL_AT_LINK, + IS_EMBEDDED_SWIFT_MODULE, IS_TESTABLE, RESILIENCE_STRATEGY, ARE_PRIVATE_IMPORTS_ENABLED, @@ -928,6 +929,10 @@ namespace options_block { HAS_HERMETIC_SEAL_AT_LINK >; + using IsEmbeddedSwiftModuleLayout = BCRecordLayout< + IS_EMBEDDED_SWIFT_MODULE + >; + using IsTestableLayout = BCRecordLayout< IS_TESTABLE >; diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 6376f1942224c..551a7be34294f 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -1038,6 +1038,11 @@ void Serializer::writeHeader() { HasHermeticSealAtLink.emit(ScratchRecord); } + if (Options.EmbeddedSwiftModule) { + options_block::IsEmbeddedSwiftModuleLayout IsEmbeddedSwiftModule(Out); + IsEmbeddedSwiftModule.emit(ScratchRecord); + } + if (M->isTestingEnabled()) { options_block::IsTestableLayout IsTestable(Out); IsTestable.emit(ScratchRecord); @@ -3801,9 +3806,9 @@ class Serializer::DeclSerializer : public DeclVisitor { /// Add all of the inherited entries to the result vector. /// /// \returns the number of entries added. - size_t addInherited(ArrayRef inheritedEntries, + size_t addInherited(InheritedTypes inheritedEntries, SmallVectorImpl &result) { - for (const auto &inherited : inheritedEntries) { + for (const auto &inherited : inheritedEntries.getEntries()) { assert(!inherited.getType() || !inherited.getType()->hasArchetype()); TypeID typeRef = S.addTypeRef(inherited.getType()); @@ -4218,7 +4223,7 @@ class Serializer::DeclSerializer : public DeclVisitor { proto->getInherited(), inheritedAndDependencyTypes); // Separately collect inherited protocol types as dependencies. - for (auto element : proto->getInherited()) { + for (auto element : proto->getInherited().getEntries()) { auto elementType = element.getType(); assert(!elementType || !elementType->hasArchetype()); if (elementType && diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 8a6bebc374891..1412cce99fe54 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -826,6 +826,7 @@ LoadedFile *SerializedModuleLoaderBase::loadAST( fileUnit = new (Ctx) SerializedASTFile(M, *loadedModuleFile); M.setStaticLibrary(loadedModuleFile->isStaticLibrary()); M.setHasHermeticSealAtLink(loadedModuleFile->hasHermeticSealAtLink()); + M.setIsEmbeddedSwiftModule(loadedModuleFile->isEmbeddedSwiftModule()); if (loadedModuleFile->isTestable()) M.setTestingEnabled(); if (loadedModuleFile->arePrivateImportsEnabled()) @@ -916,6 +917,18 @@ LoadedFile *SerializedModuleLoaderBase::loadAST( diag::need_hermetic_seal_to_import_module, M.getName()); } + if (M.isEmbeddedSwiftModule() && + !Ctx.LangOpts.hasFeature(Feature::Embedded)) { + Ctx.Diags.diagnose(diagLoc.value_or(SourceLoc()), + diag::cannot_import_embedded_module, M.getName()); + } + + if (!M.isEmbeddedSwiftModule() && + Ctx.LangOpts.hasFeature(Feature::Embedded)) { + Ctx.Diags.diagnose(diagLoc.value_or(SourceLoc()), + diag::cannot_import_non_embedded_module, M.getName()); + } + // Non-resilient modules built with C++ interoperability enabled // are typically incompatible with clients that do not enable // C++ interoperability. diff --git a/lib/SymbolGraphGen/Symbol.cpp b/lib/SymbolGraphGen/Symbol.cpp index bc8c18403d7e2..3e9667e4a847b 100644 --- a/lib/SymbolGraphGen/Symbol.cpp +++ b/lib/SymbolGraphGen/Symbol.cpp @@ -861,7 +861,7 @@ AccessLevel Symbol::getEffectiveAccessLevel(const ExtensionDecl *ED) { } AccessLevel maxInheritedAL = AccessLevel::Private; - for (auto Inherited : ED->getInherited()) { + for (auto Inherited : ED->getInherited().getEntries()) { if (const auto Type = Inherited.getType()) { if (const auto *Proto = dyn_cast_or_null( Type->getAnyNominal())) { diff --git a/lib/SymbolGraphGen/SymbolGraph.cpp b/lib/SymbolGraphGen/SymbolGraph.cpp index e63371c740c43..e9e0b6dca0a3e 100644 --- a/lib/SymbolGraphGen/SymbolGraph.cpp +++ b/lib/SymbolGraphGen/SymbolGraph.cpp @@ -389,7 +389,7 @@ void SymbolGraph::recordInheritanceRelationships(Symbol S) { const auto VD = S.getLocalSymbolDecl(); if (const auto *NTD = dyn_cast(VD)) { - for (const auto &InheritanceLoc : NTD->getInherited()) { + for (const auto &InheritanceLoc : NTD->getInherited().getEntries()) { auto Ty = InheritanceLoc.getType(); if (!Ty) { continue; diff --git a/stdlib/public/Concurrency/TaskLocal.swift b/stdlib/public/Concurrency/TaskLocal.swift index 0226d0819e87f..92117c06d1e60 100644 --- a/stdlib/public/Concurrency/TaskLocal.swift +++ b/stdlib/public/Concurrency/TaskLocal.swift @@ -227,7 +227,6 @@ public final class TaskLocal: Sendable, CustomStringConvertible storage storageKeyPath: ReferenceWritableKeyPath> ) -> Value { get { - fatalError("Will never be executed, since enclosing instance is Never") } } diff --git a/stdlib/public/RemoteInspection/TypeRefBuilder.cpp b/stdlib/public/RemoteInspection/TypeRefBuilder.cpp index 77486c36bd9fe..fe36991d86f2c 100644 --- a/stdlib/public/RemoteInspection/TypeRefBuilder.cpp +++ b/stdlib/public/RemoteInspection/TypeRefBuilder.cpp @@ -93,6 +93,14 @@ RemoteRef TypeRefBuilder::readTypeRef(uint64_t remoteAddr) { /// Load and normalize a mangled name so it can be matched with string equality. llvm::Optional TypeRefBuilder::normalizeReflectionName(RemoteRef reflectionName) { + const auto reflectionNameRemoteAddress = reflectionName.getAddressData(); + + if (const auto found = + NormalizedReflectionNameCache.find(reflectionNameRemoteAddress); + found != NormalizedReflectionNameCache.end()) { + return found->second; + } + ScopedNodeFactoryCheckpoint checkpoint(this); // Remangle the reflection name to resolve symbolic references. if (auto node = demangleTypeRef(reflectionName, @@ -102,18 +110,27 @@ TypeRefBuilder::normalizeReflectionName(RemoteRef reflectionName) { case Node::Kind::ProtocolSymbolicReference: case Node::Kind::OpaqueTypeDescriptorSymbolicReference: // Symbolic references cannot be mangled, return a failure. + NormalizedReflectionNameCache.insert(std::make_pair( + reflectionNameRemoteAddress, llvm::Optional())); return {}; default: auto mangling = mangleNode(node); if (!mangling.isSuccess()) { + NormalizedReflectionNameCache.insert(std::make_pair( + reflectionNameRemoteAddress, llvm::Optional())); return {}; } + NormalizedReflectionNameCache.insert( + std::make_pair(reflectionNameRemoteAddress, mangling.result())); return std::move(mangling.result()); } } // Fall back to the raw string. - return getTypeRefString(reflectionName).str(); + const auto manglingResult = getTypeRefString(reflectionName).str(); + NormalizedReflectionNameCache.insert( + std::make_pair(reflectionNameRemoteAddress, manglingResult)); + return std::move(manglingResult); } /// Determine whether the given reflection protocol name matches. @@ -398,8 +415,12 @@ TypeRefBuilder::getBuiltinTypeInfo(const TypeRef *TR) { else return nullptr; - for (auto Info : ReflectionInfos) { - for (auto BuiltinTypeDescriptor : Info.Builtin) { + for (; NormalizedReflectionNameCacheLastReflectionInfoCache < + ReflectionInfos.size(); + NormalizedReflectionNameCacheLastReflectionInfoCache++) { + for (auto BuiltinTypeDescriptor : + ReflectionInfos[NormalizedReflectionNameCacheLastReflectionInfoCache] + .Builtin) { if (BuiltinTypeDescriptor->Stride <= 0) continue; if (!BuiltinTypeDescriptor->hasMangledTypeName()) @@ -413,13 +434,21 @@ TypeRefBuilder::getBuiltinTypeInfo(const TypeRef *TR) { continue; auto CandidateMangledName = - readTypeRef(BuiltinTypeDescriptor, BuiltinTypeDescriptor->TypeName); - if (!reflectionNameMatches(CandidateMangledName, MangledName)) - continue; - return BuiltinTypeDescriptor; + readTypeRef(BuiltinTypeDescriptor, BuiltinTypeDescriptor->TypeName); + auto CandidateNormalizedName = + normalizeReflectionName(CandidateMangledName); + if (CandidateNormalizedName) { + BuiltInTypeDescriptorCache.insert( + std::make_pair(*CandidateNormalizedName, BuiltinTypeDescriptor)); + } } } + if (const auto found = BuiltInTypeDescriptorCache.find(MangledName); + found != BuiltInTypeDescriptorCache.end()) { + return found->second; + } + return nullptr; } diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp index 6c63fccd8cd25..32232a3860207 100644 --- a/stdlib/public/runtime/MetadataLookup.cpp +++ b/stdlib/public/runtime/MetadataLookup.cpp @@ -2830,6 +2830,41 @@ swift_getOpaqueTypeConformance(const void * const *arguments, arguments, static_cast(descriptor), index); } +SWIFT_RUNTIME_STDLIB_SPI +SWIFT_CC(swift) +const Metadata *swift::_swift_instantiateCheckedGenericMetadata( + const TypeContextDescriptor *context, + const void * const *genericArgs, + size_t genericArgsSize) { + context = swift_auth_data_non_address( + context, SpecialPointerAuthDiscriminators::ContextDescriptor); + + if (!context->isGeneric()) { + return nullptr; + } + + DemanglerForRuntimeTypeResolution> demangler; + + llvm::ArrayRef genericArgsRef( + reinterpret_cast(genericArgs), genericArgsSize); + llvm::SmallVector genericParamCounts; + llvm::SmallVector allGenericArgs; + + auto result = _gatherGenericParameters(context, genericArgsRef, + /* parent */ nullptr, + genericParamCounts, allGenericArgs, + demangler); + + // _gatherGenericParameters returns llvm::None on success. + if (result.hasValue()) { + return nullptr; + } + + auto accessFunction = context->getAccessFunction(); + + return accessFunction(MetadataState::Complete, allGenericArgs).Value; +} + #if SWIFT_OBJC_INTEROP // Return the ObjC class for the given type name. diff --git a/stdlib/public/stubs/LibcShims.cpp b/stdlib/public/stubs/LibcShims.cpp index 0e13e2c85b71e..b5e39f5d05df5 100644 --- a/stdlib/public/stubs/LibcShims.cpp +++ b/stdlib/public/stubs/LibcShims.cpp @@ -23,6 +23,7 @@ #endif #include +#include #include "swift/shims/LibcShims.h" diff --git a/test/AutoDiff/SILOptimizer/differential_apply.swift b/test/AutoDiff/SILOptimizer/differential_apply.swift new file mode 100644 index 0000000000000..3474564ebb9f5 --- /dev/null +++ b/test/AutoDiff/SILOptimizer/differential_apply.swift @@ -0,0 +1,48 @@ +// RUN: %target-swift-frontend -emit-sil -O %s | %FileCheck %s +// REQUIRES: swift_in_compiler + +import _Differentiation + +@differentiable(reverse) +@_silgen_name("test_f") +// Check that (differentiable) closure apply is optimized out +// CHECK-LABEL: test_f : $@convention(thin) (@guaranteed Array) -> Double +// CHECK-NOT: differentiable_function [parameters 0] [results 0] +func f(array: [Double]) -> Double { + var array = array + array.update(at: 1, + byCalling: { + (element: inout Double) in + let initialElement = element; + element *= initialElement + } + ) + + return 0.0 +} + +public func valueWithPullback(at x: T, of f: @differentiable(reverse) (inout T) -> Void) -> (value: Void, pullback: (inout T.TangentVector) -> Void) {fatalError()} +public func pullback(at x: T, of f: @differentiable(reverse) (inout T) -> Void) -> (inout T.TangentVector) -> Void {return valueWithPullback(at: x, of: f).pullback} + +public extension Array { + @differentiable(reverse) + mutating func update(at index: Int, + byCalling closure: @differentiable(reverse) (inout Element) -> Void) where Element: Differentiable { + closure(&self[index]) + } +} + +public extension Array where Element: Differentiable { + @derivative(of: update(at:byCalling:)) + mutating func vjpUpdate(at index: Int, byCalling closure: @differentiable(reverse) (inout Element) -> Void) -> (value: Void, pullback: (inout Self.TangentVector) -> Void) { + let closurePullback = pullback(at: self[index], of: closure) + return (value: (), pullback: { closurePullback(&$0.base[index]) }) + } +} + +public struct D { + public subscript(_ index: I) -> D? { + get {fatalError()} + set {fatalError()} + } +} diff --git a/test/CAS/educational-notes.swift b/test/CAS/educational-notes.swift index f38a7133cb19b..e4e8c23625a22 100644 --- a/test/CAS/educational-notes.swift +++ b/test/CAS/educational-notes.swift @@ -13,10 +13,11 @@ let x = 1 + // NO-COLOR-NOT: {{-+$}} // A diagnostic with an educational note using supported markdown features -extension (Int, Int) {} -// CHECK:{{.*}}[0merror: non-nominal type '(Int, Int)' cannot be extended -// CHECK-NEXT:extension (Int, Int) {} -// CHECK-NEXT:^ ~~~~~~~~~~ +typealias Crap = () -> () +extension Crap {} +// CHECK:{{.*}}[0merror: non-nominal type 'Crap' (aka '() -> ()') cannot be extended +// CHECK-NEXT:extension Crap {} +// CHECK-NEXT:^ ~~~~ // CHECK-NEXT:Nominal Types // CHECK-NEXT:-------------- // CHECK-EMPTY: @@ -42,9 +43,9 @@ extension (Int, Int) {} // CHECK-NEXT:Header 1 // CHECK-NEXT:Header 3 -// NO-COLOR:{{.*}}error: non-nominal type '(Int, Int)' cannot be extended -// NO-COLOR-NEXT:extension (Int, Int) {} -// NO-COLOR-NEXT:^ ~~~~~~~~~~ +// NO-COLOR:{{.*}}error: non-nominal type 'Crap' (aka '() -> ()') cannot be extended +// NO-COLOR-NEXT:extension Crap {} +// NO-COLOR-NEXT:^ ~~~~ // NO-COLOR-NEXT:Nominal Types // NO-COLOR-NEXT:-------------- // NO-COLOR-EMPTY: @@ -72,15 +73,15 @@ extension (Int, Int) {} // CHECK-DESCRIPTIVE: educational-notes.swift // CHECK-DESCRIPTIVE-NEXT: | // A diagnostic with an educational note -// CHECK-DESCRIPTIVE-NEXT: | extension (Int, Int) {} +// CHECK-DESCRIPTIVE-NEXT: | extension Crap {} // CHECK-DESCRIPTIVE-NEXT: | ^ error: expected expression after operator // CHECK-DESCRIPTIVE-NEXT: | // CHECK-DESCRIPTIVE: educational-notes.swift // CHECK-DESCRIPTIVE-NEXT: | // A diagnostic with an educational note -// CHECK-DESCRIPTIVE-NEXT: | extension (Int, Int) {} -// CHECK-DESCRIPTIVE-NEXT: | ~~~~~~~~~~ -// CHECK-DESCRIPTIVE-NEXT: | ^ error: non-nominal type '(Int, Int)' cannot be extended +// CHECK-DESCRIPTIVE-NEXT: | extension Crap {} +// CHECK-DESCRIPTIVE-NEXT: | ~~~~ +// CHECK-DESCRIPTIVE-NEXT: | ^ error: non-nominal type 'Crap' (aka '() -> ()') cannot be extended // CHECK-DESCRIPTIVE-NEXT: | // CHECK-DESCRIPTIVE-NEXT: Nominal Types // CHECK-DESCRIPTIVE-NEXT: ------------- diff --git a/test/Concurrency/Runtime/async_task_priority_current.swift b/test/Concurrency/Runtime/async_task_priority_current.swift index b2638a4ad8689..626f52f4df9bc 100644 --- a/test/Concurrency/Runtime/async_task_priority_current.swift +++ b/test/Concurrency/Runtime/async_task_priority_current.swift @@ -10,17 +10,10 @@ import Dispatch -// Work around the inability of older Swift runtimes to print a task priority. -extension TaskPriority: CustomStringConvertible { - public var description: String { - "TaskPriority(rawValue: \(rawValue))" - } -} - @available(SwiftStdlib 5.1, *) @main struct Main { static func main() async { - print("main priority: \(Task.currentPriority)") // CHECK: main priority: TaskPriority(rawValue: [[#MAIN_PRIORITY:]]) + print("main priority: \(Task.currentPriority)") // CHECK: main priority: TaskPriority.medium await test_detach() await test_multiple_lo_indirectly_escalated() } @@ -29,18 +22,18 @@ extension TaskPriority: CustomStringConvertible { @available(SwiftStdlib 5.1, *) func test_detach() async { let a1 = Task.currentPriority - print("a1: \(a1)") // CHECK: a1: TaskPriority(rawValue: [[#MAIN_PRIORITY]]) + print("a1: \(a1)") // CHECK: a1: TaskPriority.medium // Note: remember to detach using a higher priority, otherwise a lower one // might be escalated by the get() and we could see `default` in the detached // task. await detach(priority: .userInitiated) { let a2 = Task.currentPriority - print("a2: \(a2)") // CHECK: a2: TaskPriority(rawValue: 25) + print("a2: \(a2)") // CHECK: a2: TaskPriority.high }.get() let a3 = Task.currentPriority - print("a3: \(a3)") // CHECK: a3: TaskPriority(rawValue: [[#MAIN_PRIORITY]]) + print("a3: \(a3)") // CHECK: a3: TaskPriority.medium } @available(SwiftStdlib 5.1, *) diff --git a/test/Concurrency/Runtime/custom_executors_complex_equality_crash.swift b/test/Concurrency/Runtime/custom_executors_complex_equality_crash.swift index de200253fecda..592aed0330235 100644 --- a/test/Concurrency/Runtime/custom_executors_complex_equality_crash.swift +++ b/test/Concurrency/Runtime/custom_executors_complex_equality_crash.swift @@ -1,4 +1,4 @@ -// RUN: %target-run-simple-swift( -Xfrontend -disable-availability-checking -parse-as-library) +// RUN: %target-run-simple-swift( -Xfrontend -disable-availability-checking %import-libdispatch -parse-as-library) // REQUIRES: concurrency // REQUIRES: executable_test diff --git a/test/Constraints/rdar114402042.swift b/test/Constraints/rdar114402042.swift new file mode 100644 index 0000000000000..ee366ddf3697d --- /dev/null +++ b/test/Constraints/rdar114402042.swift @@ -0,0 +1,32 @@ +// RUN: %target-typecheck-verify-swift + +// rdar://114402042 - Make sure we connect the SingleValueStmtExpr to the outer +// closure's return type. +func foo(_: () -> T) {} +func bar(_ x: T) {} +func test() { + foo { + bar(if true { return } else { return }) + // expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}} + // expected-error@-2 2{{cannot 'return' in 'if' when used as expression}} + } + foo { + bar(if true { { return } } else { { return } }) + // expected-error@-1 {{'if' may only be used as expression in return, throw, or as the source of an assignment}} + } +} + +func baz() -> String? { + nil +} + +var x: Int? = { + print( // expected-error {{cannot convert value of type '()' to closure result type 'Int?'}} + // expected-note@-1 {{to match this opening '('}} + switch baz() { + case ""?: + return nil + default: + return nil + } +}() // expected-error {{expected ')' in expression list}} diff --git a/test/DebugInfo/method-declaration.swift b/test/DebugInfo/method-declaration.swift new file mode 100644 index 0000000000000..b1fdb35d5dfa0 --- /dev/null +++ b/test/DebugInfo/method-declaration.swift @@ -0,0 +1,37 @@ +// RUN: %target-swift-frontend -primary-file %s -emit-ir -gdwarf-types -o - | %FileCheck %s + +// Verify that we added a declaration for a method. + +// CHECK: define{{.*}}foo_static_method{{.*}} !dbg ![[FOO_STATIC_METHOD_DEF_DBG:[0-9]+]] +// CHECK: define{{.*}}foo_method{{.*}} !dbg ![[FOO_METHOD_DEF_DBG:[0-9]+]] +// CHECK: define{{.*}}bar_static_method{{.*}} !dbg ![[BAR_STATIC_METHOD_DEF_DBG:[0-9]+]] +// CHECK: define{{.*}}bar_method{{.*}} !dbg ![[BAR_METHOD_DEF_DBG:[0-9]+]] +// CHECK: define{{.*}}a_function{{.*}} !dbg ![[FUNC_DEF_DBG:[0-9]+]] + +// CHECK-DAG: ![[FOO_DBG:[0-9]+]] = !DICompositeType(tag: {{.*}} name: "Foo", {{.*}} identifier: +public struct Foo { +// CHECK-DAG: ![[FOO_STATIC_METHOD_DEF_DBG]] = distinct !DISubprogram(name: "foo_static_method"{{.*}}, scope: ![[FOO_DBG]]{{.*}}DISPFlagDefinition{{.*}}, declaration: ![[FOO_STATIC_METHOD_DECL_DBG:[0-9]+]] +// CHECK-DAG: ![[FOO_STATIC_METHOD_DECL_DBG]] = !DISubprogram(name: "foo_static_method"{{.*}}, scope: ![[FOO_DBG]] + static func foo_static_method() {} +// CHECK-DAG: ![[FOO_METHOD_DEF_DBG]] = distinct !DISubprogram(name: "foo_method"{{.*}}, scope: ![[FOO_DBG]]{{.*}}DISPFlagDefinition{{.*}}, declaration: ![[FOO_METHOD_DECL_DBG:[0-9]+]] +// CHECK-DAG: ![[FOO_METHOD_DECL_DBG]] = !DISubprogram(name: "foo_method"{{.*}}, scope: ![[FOO_DBG]] + func foo_method() {} +} + +// CHECK-DAG: ![[BAR_DBG:[0-9]+]] = !DICompositeType(tag: {{.*}} name: "Bar", {{.*}} identifier: +public class Bar { +// CHECK-DAG: ![[BAR_STATIC_METHOD_DEF_DBG]] = distinct !DISubprogram(name: "bar_static_method"{{.*}}, scope: ![[BAR_DBG]]{{.*}}DISPFlagDefinition{{.*}}, declaration: ![[BAR_STATIC_METHOD_DECL_DBG:[0-9]+]] +// CHECK-DAG: ![[BAR_STATIC_METHOD_DECL_DBG]] = !DISubprogram(name: "bar_static_method"{{.*}}, scope: ![[BAR_DBG]] + static func bar_static_method() {} +// CHECK-DAG: ![[BAR_METHOD_DEF_DBG]] = distinct !DISubprogram(name: "bar_method"{{.*}}, scope: ![[BAR_DBG]]{{.*}}DISPFlagDefinition{{.*}}, declaration: ![[BAR_METHOD_DECL_DBG:[0-9]+]] +// CHECK-DAG: ![[BAR_METHOD_DECL_DBG]] = !DISubprogram(name: "bar_method"{{.*}}, scope: ![[BAR_DBG]] + func bar_method() {} +} + +// CHECK: ![[FUNC_DEF_DBG]] = distinct !DISubprogram(name: "a_function" +// CHECK-NOT: declaration +// CHECK-SAME: DISPFlagDefinition +// CHECK-NOT: declaration +// CHECK-SAME: ) +func a_function() {} + diff --git a/test/Generics/tuple-conformances.swift b/test/Generics/tuple-conformances.swift index 4977a57013483..cffc8a70aec15 100644 --- a/test/Generics/tuple-conformances.swift +++ b/test/Generics/tuple-conformances.swift @@ -1,8 +1,63 @@ -// RUN: %target-typecheck-verify-swift -enable-experimental-feature TupleConformances -parse-stdlib +// RUN: %target-typecheck-verify-swift -enable-experimental-feature TupleConformances +// Because of -enable-experimental-feature TupleConformances // REQUIRES: asserts -import Swift +extension () { + // expected-error@-1 {{tuple extension must be written as extension of '(repeat each Element)'}} + // expected-error@-2 {{tuple extension must declare conformance to exactly one protocol}} + + struct Nested {} + // expected-error@-1 {{type 'Nested' cannot be nested in tuple extension}} +} + +typealias BadTuple = (repeat each Horse, Int) +extension BadTuple {} +// expected-error@-1 {{tuple extension must be written as extension of '(repeat each Horse)'}} +// expected-error@-2 {{tuple extension must declare conformance to exactly one protocol}} + +typealias Tuple = (repeat each Element) + +protocol Q {} + +class C {} + +extension Tuple: Q where repeat each Element: Collection, repeat (each Element).Element == (each Element).Index, repeat (each Element).Indices: AnyObject, repeat (each Element).SubSequence: C {} +// expected-error@-1 {{tuple extension must require that 'each Element' conforms to 'Q'}} +// expected-error@-2 {{tuple extension cannot require that 'each Element' conforms to 'Collection'}} +// expected-error@-3 {{tuple extension cannot require that '(each Element).Element' is the same type as '(each Element).Index'}} +// expected-error@-4 {{tuple extension cannot require that '(each Element).Indices' conforms to 'AnyObject'}} +// expected-error@-5 {{tuple extension cannot require that '(each Element).SubSequence' subclasses 'C'}} + +protocol Base1 {} +protocol Derived1: Base1 {} + +extension Tuple: Derived1 where repeat each Element: Derived1 {} +// expected-error@-1 {{conditional conformance of type '(repeat each Element)' to protocol 'Derived1' does not imply conformance to inherited protocol 'Base1'}} +// expected-note@-2 {{did you mean to explicitly state the conformance like 'extension Tuple: Base1 where ...'?}} +// expected-error@-3 {{tuple extension must declare conformance to exactly one protocol}} + +protocol Base2 {} +protocol Derived2: Base2 {} + +extension Tuple: Derived2 {} +// expected-error@-1 {{tuple extension must declare conformance to exactly one protocol}} // FIXME: crappy error + +//// + +protocol P2 {} + +typealias FancyTuple1 = (repeat each Cat) +extension FancyTuple1: P2 {} + +protocol P3 {} + +typealias FancyTuple2 = (repeat each Cat) +extension FancyTuple2: P3 {} +// expected-error@-1 {{tuple extension cannot require that 'each Cat' subclasses 'C'}} +// expected-error@-2 {{tuple extension must require that 'each Cat' conforms to 'P3'}} + +//// protocol P { associatedtype A @@ -11,9 +66,9 @@ protocol P { func f() } -extension Builtin.TheTupleType: P where repeat each Elements: P { - typealias A = (repeat (each Elements).A) - typealias B = Float +extension Tuple: P where repeat each Element: P { + typealias A = (repeat (each Element).A) + typealias B = (repeat (each Element).B) func f() {} } @@ -30,14 +85,14 @@ func same(_: T, _: T) {} func useConformance() { same(returnsPA((1, 2, 3)), (Int, Int, Int).self) - same(returnsPB((1, 2, 3)), Float.self) + same(returnsPB((1, 2, 3)), (String, String, String).self) (1, 2, 3).f() } //// -extension Builtin.TheTupleType: Equatable where repeat each Elements: Equatable { +extension Tuple: Equatable where repeat each Element: Equatable { // FIXME: Hack @_disfavoredOverload public static func ==(lhs: Self, rhs: Self) -> Bool { @@ -51,7 +106,7 @@ extension Builtin.TheTupleType: Equatable where repeat each Elements: Equatable } } -extension Builtin.TheTupleType: Hashable where repeat each Elements: Hashable { +extension Tuple: Hashable where repeat each Element: Hashable { public func hash(into hasher: inout Hasher) { repeat (each self).hash(into: &hasher) } diff --git a/test/IDE/complete_multiple_trailingclosure.swift b/test/IDE/complete_multiple_trailingclosure.swift index 807ba2c4cf872..09b51538534d9 100644 --- a/test/IDE/complete_multiple_trailingclosure.swift +++ b/test/IDE/complete_multiple_trailingclosure.swift @@ -1,31 +1,13 @@ -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBALFUNC_SAMELINE | %FileCheck %s -check-prefix=GLOBALFUNC_SAMELINE -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBALFUNC_NEWLINE | %FileCheck %s -check-prefix=GLOBALFUNC_NEWLINE -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GLOBALFUNC_AFTERLABEL | %FileCheck %s -check-prefix=GLOBALFUNC_AFTERLABEL -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=METHOD_SAMELINE | %FileCheck %s -check-prefix=METHOD_SAMELINE -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=METHOD_NEWLINE | %FileCheck %s -check-prefix=METHOD_NEWLINE -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_OVERLOADED_SAMELINE | %FileCheck %s -check-prefix=INIT_OVERLOADED_SAMELINE -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_OVERLOADED_NEWLINE | %FileCheck %s -check-prefix=INIT_OVERLOADED_NEWLINE -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_OPTIONAL_SAMELINE | %FileCheck %s -check-prefix=INIT_OPTIONAL_SAMELINE -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_OPTIONAL_NEWLINE | %FileCheck %s -check-prefix=INIT_OPTIONAL_NEWLINE -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_REQUIRED_SAMELINE_1 | %FileCheck %s -check-prefix=INIT_REQUIRED_SAMELINE_1 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_REQUIRED_NEWLINE_1 | %FileCheck %s -check-prefix=INIT_REQUIRED_NEWLINE_1 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_REQUIRED_SAMELINE_2 | %FileCheck %s -check-prefix=INIT_REQUIRED_SAMELINE_2 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_REQUIRED_NEWLINE_2 | %FileCheck %s -check-prefix=INIT_REQUIRED_NEWLINE_2 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_REQUIRED_SAMELINE_3 | %FileCheck %s -check-prefix=INIT_REQUIRED_SAMELINE_3 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_REQUIRED_NEWLINE_3 | %FileCheck %s -check-prefix=INIT_REQUIRED_NEWLINE_3 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_FALLBACK_1 | %FileCheck %s -check-prefix=INIT_FALLBACK_1 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_FALLBACK_2 | %FileCheck %s -check-prefix=INIT_FALLBACK_2 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=MEMBERDECL_SAMELINE | %FileCheck %s -check-prefix=MEMBERDECL_SAMELINE -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=MEMBERDECL_NEWLINE | %FileCheck %s -check-prefix=MEMBERDECL_NEWLINE -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INITIALIZED_VARDECL_SAMELINE | %FileCheck %s -check-prefix=INITIALIZED_VARDECL_SAMELINE -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INITIALIZED_VARDECL_NEWLINE | %FileCheck %s -check-prefix=INITIALIZED_VARDECL_NEWLINE +// RUN: %empty-directory(%t) +// RUN: %target-swift-ide-test -batch-code-completion -source-filename %s -filecheck %raw-FileCheck -completion-output-dir %t func globalFunc1(fn1: () -> Int, fn2: () -> String) {} func testGlobalFunc() { globalFunc1() { 1 } #^GLOBALFUNC_SAMELINE^# #^GLOBALFUNC_NEWLINE^# -// GLOBALFUNC_SAMELINE: Begin completions, 1 items +// GLOBALFUNC_SAMELINE: Begin completions, 2 items +// GLOBALFUNC_SAMELINE-DAG: Keyword[self]/CurrNominal: .self[#Void#]; name=self // GLOBALFUNC_SAMELINE-DAG: Pattern/Local/Flair[ArgLabels]: {#fn2: () -> String {|}#}[#() -> String#]; // GLOBALFUNC_NEWLINE: Begin completions @@ -129,8 +111,11 @@ func testOptionalInit() { } #^INIT_REQUIRED_SAMELINE_1^# #^INIT_REQUIRED_NEWLINE_1^# -// INIT_REQUIRED_SAMELINE_1: Begin completions, 1 items -// INIT_REQUIRED_SAMELINE_1-DAG: Pattern/Local/Flair[ArgLabels]: {#fn2: () -> String {|}#}[#() -> String#]; +// INIT_REQUIRED_SAMELINE_1: Begin completions, 3 items +// INIT_REQUIRED_SAMELINE_1-DAG: Pattern/Local/Flair[ArgLabels]: {#fn2: () -> String {|}#}[#() -> String#]; +// INIT_REQUIRED_SAMELINE_1-DAG: Keyword[self]/CurrNominal: .self[#TestStruct3#]; name=self +// INIT_REQUIRED_SAMELINE_1-DAG: Decl[InstanceMethod]/CurrNominal: .testStructMethod()[#Void#]; name=testStructMethod() + // INIT_REQUIRED_NEWLINE_1: Begin completions // FIXME-INIT_REQUIRED_NEWLINE_1-DAG: Pattern/Local/Flair[ArgLabels]: {#fn2: () -> String {|}#}[#() -> String#]; @@ -144,8 +129,10 @@ func testOptionalInit() { } #^INIT_REQUIRED_SAMELINE_2^# #^INIT_REQUIRED_NEWLINE_2^# -// INIT_REQUIRED_SAMELINE_2: Begin completions, 1 items -// INIT_REQUIRED_SAMELINE_2-DAG: Pattern/Local/Flair[ArgLabels]: {#fn3: () -> String {|}#}[#() -> String#]; +// INIT_REQUIRED_SAMELINE_2: Begin completions, 3 items +// INIT_REQUIRED_SAMELINE_2-DAG: Keyword[self]/CurrNominal: .self[#TestStruct3#]; name=self +// INIT_REQUIRED_SAMELINE_2-DAG: Decl[InstanceMethod]/CurrNominal: .testStructMethod()[#Void#]; name=testStructMethod() +// INIT_REQUIRED_SAMELINE_2-DAG: Pattern/Local/Flair[ArgLabels]: {#fn3: () -> String {|}#}[#() -> String#]; // INIT_REQUIRED_NEWLINE_2: Begin completions // FIXME-INIT_REQUIRED_NEWLINE_2-DAG: Pattern/Local/Flair[ArgLabels]: {#fn3: () -> String {|}#}[#() -> String#]; @@ -161,7 +148,7 @@ func testOptionalInit() { } #^INIT_REQUIRED_SAMELINE_3^# #^INIT_REQUIRED_NEWLINE_3^# -// INIT_REQUIRED_SAMELINE_3: Begin completions, 2 items +// INIT_REQUIRED_SAMELINE_3: Begin completions // INIT_REQUIRED_SAMELINE_3-DAG: Decl[InstanceMethod]/CurrNominal: .testStructMethod()[#Void#]; // INIT_REQUIRED_SAMELINE_3-DAG: Keyword[self]/CurrNominal: .self[#TestStruct3#]; @@ -185,22 +172,17 @@ func testFallbackPostfix() { let _ = MyStruct4 { 1 } #^INIT_FALLBACK_1^# -// FIXME: We shouldn't be suggesting arg3 here because the second initializer -// doesn't match the already-provided parameters (missing `name` label argument -// and closure does not return `String`). However, we are not type-checking at -// the stage at which we complete argument labels, so we can't rule it out for -// now. (https://github.com/apple/swift/issues/56806) // INIT_FALLBACK_1: Begin completions, 3 items -// INIT_FALLBACK_1-DAG: Pattern/Local/Flair[ArgLabels]: {#arg3: () -> _ {|}#}[#() -> _#] -// INIT_FALLBACK_1-DAG: Decl[InstanceMethod]/CurrNominal: .testStructMethod()[#Void#]; -// INIT_FALLBACK_1-DAG: Keyword[self]/CurrNominal: .self[#MyStruct4#]; +// INIT_FALLBACK_1-DAG: Keyword[self]/CurrNominal: .self[#MyStruct4#]; name=self +// INIT_FALLBACK_1-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: .testStructMethod()[#Void#]; name=testStructMethod() +// INIT_FALLBACK_1-DAG: Pattern/Local/Flair[ArgLabels]: {#arg1: Int#}[#Int#]; name=arg1: let _ = MyStruct4(name: "test") { "" } arg3: { 1 } #^INIT_FALLBACK_2^# -// INIT_FALLBACK_2: Begin completions, 2 items -// INIT_FALLBACK_2-DAG: Decl[InstanceMethod]/CurrNominal: .testStructMethod()[#Void#]; +// INIT_FALLBACK_2: Begin completions +// INIT_FALLBACK_2-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: .testStructMethod()[#Void#]; // INIT_FALLBACK_2-DAG: Keyword[self]/CurrNominal: .self[#MyStruct4#]; } @@ -213,7 +195,7 @@ struct TestNominalMember: P { // MEMBERDECL_SAMELINE: Begin completions, 4 items // MEMBERDECL_SAMELINE-DAG: Pattern/Local/Flair[ArgLabels]: {#fn2: (() -> String)? {|}#}[#(() -> String)?#]; name=fn2: -// MEMBERDECL_SAMELINE-DAG: Decl[InstanceMethod]/CurrNominal: .enumFunc()[#Void#]; name=enumFunc() +// MEMBERDECL_SAMELINE-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: .enumFunc()[#Void#]; name=enumFunc() // MEMBERDECL_SAMELINE-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: [' ']+ {#SimpleEnum#}[#SimpleEnum#]; name=+ // MEMBERDECL_SAMELINE-DAG: Keyword[self]/CurrNominal: .self[#SimpleEnum#]; name=self @@ -235,7 +217,7 @@ func testInitializedVarDecl() { // INITIALIZED_VARDECL_SAMELINE-NOT: localVal // INITIALIZED_VARDECL_SAMELINE-DAG: Pattern/Local/Flair[ArgLabels]: {#fn2: () -> String {|}#}[#() -> String#]; // INITIALIZED_VARDECL_SAMELINE-DAG: Pattern/Local/Flair[ArgLabels]: {#fn3: () -> String {|}#}[#() -> String#]; -// INITIALIZED_VARDECL_SAMELINE-DAG: Decl[InstanceMethod]/CurrNominal: .testStructMethod()[#Void#]; +// INITIALIZED_VARDECL_SAMELINE-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: .testStructMethod()[#Void#]; // INITIALIZED_VARDECL_SAMELINE-DAG: Keyword[self]/CurrNominal: .self[#TestStruct#]; // INITIALIZED_VARDECL_SAMELINE-NOT: localVal diff --git a/test/IDE/complete_operators.swift b/test/IDE/complete_operators.swift index 4fa856575bba5..515f71babb035 100644 --- a/test/IDE/complete_operators.swift +++ b/test/IDE/complete_operators.swift @@ -225,12 +225,8 @@ func testInfix17(x: Void) { x#^INFIX_17?check=VOID_OPERATORS^# } -// VOID_OPERATORS-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: != {#()#}[#Bool#]; name=!= -// VOID_OPERATORS-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: == {#()#}[#Bool#]; name=== -// VOID_OPERATORS-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: <= {#()#}[#Bool#]; name=<= -// VOID_OPERATORS-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: >= {#()#}[#Bool#]; name=>= -// VOID_OPERATORS-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: < {#()#}[#Bool#]; name=< -// VOID_OPERATORS-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: > {#()#}[#Bool#]; name=> +// VOID_OPERATORS: Begin completions, 1 item +// VOID_OPERATORS-DAG: Keyword[self]/CurrNominal: .self[#Void#]; name=self func testInfix18(x: (S2, S2) { x#^INFIX_18?check=NO_OPERATORS^# diff --git a/test/IRGen/Inputs/opaque_result_type_private_2.swift b/test/IRGen/Inputs/opaque_result_type_private_2.swift new file mode 100644 index 0000000000000..494304fd48978 --- /dev/null +++ b/test/IRGen/Inputs/opaque_result_type_private_2.swift @@ -0,0 +1,11 @@ +public protocol P { + associatedtype A : P + func d() -> Self.A +} + +public struct B { + public var a: Content.A + init(_ v: Content) { + a = v.d() + } +} diff --git a/test/IRGen/opaque_result_type_private.swift b/test/IRGen/opaque_result_type_private.swift new file mode 100644 index 0000000000000..e58d64787b9c8 --- /dev/null +++ b/test/IRGen/opaque_result_type_private.swift @@ -0,0 +1,15 @@ +// RUN: %target-swift-frontend -disable-availability-checking -c -primary-file %s %S/Inputs/opaque_result_type_private_2.swift + +// This test used to crash during IRGen. + +private struct C : P { + var x = 1 + func d() -> some P { + return self + } +} + +public func test() { + var x = B(C()) + print(x) +} diff --git a/test/IRGen/tuple_conformances.swift b/test/IRGen/tuple_conformances.swift index 6e8d02ba9b2a2..f747b44aaa580 100644 --- a/test/IRGen/tuple_conformances.swift +++ b/test/IRGen/tuple_conformances.swift @@ -1,10 +1,8 @@ -// RUN: %target-swift-frontend -emit-ir -parse-stdlib -primary-file %s -enable-experimental-feature TupleConformances -parse-as-library | %FileCheck %s +// RUN: %target-swift-frontend -emit-ir -primary-file %s -enable-experimental-feature TupleConformances -parse-as-library | %FileCheck %s // -enable-experimental-feature requires an asserts build // REQUIRES: asserts -import Swift - protocol P { func defaultRequirement() static func staticRequirement() @@ -14,7 +12,9 @@ extension P { func defaultRequirement() {} } -extension Builtin.TheTupleType: P where repeat each Elements: P { +typealias Tuple = (repeat each Element) + +extension Tuple: P where repeat each Element: P { static func staticRequirement() {} } diff --git a/test/Macros/Inputs/syntax_macro_definitions.swift b/test/Macros/Inputs/syntax_macro_definitions.swift index a7f6252d450ea..1af18b331bd0c 100644 --- a/test/Macros/Inputs/syntax_macro_definitions.swift +++ b/test/Macros/Inputs/syntax_macro_definitions.swift @@ -2004,3 +2004,53 @@ public struct InitWithProjectedValueWrapperMacro: PeerMacro { ] } } + +public struct RequiredDefaultInitMacro: ExtensionMacro { + public static func expansion( + of node: AttributeSyntax, + attachedTo decl: some DeclGroupSyntax, + providingExtensionsOf type: some TypeSyntaxProtocol, + conformingTo protocols: [TypeSyntax], + in context: some MacroExpansionContext + ) throws -> [ExtensionDeclSyntax] { + if protocols.isEmpty { + return [] + } + + let decl: DeclSyntax = + """ + extension \(type.trimmed): DefaultInit { + } + + """ + + return [ + decl.cast(ExtensionDeclSyntax.self) + ] + } +} + +extension RequiredDefaultInitMacro: MemberMacro { + public static func expansion( + of node: AttributeSyntax, + providingMembersOf declaration: some DeclGroupSyntax, + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + fatalError("old swift-syntax") + } + + public static func expansion( + of node: AttributeSyntax, + providingMembersOf declaration: some DeclGroupSyntax, + conformingTo protocols: [TypeSyntax], + in context: some MacroExpansionContext + ) throws -> [DeclSyntax] { + let decl: DeclSyntax + if declaration.is(ClassDeclSyntax.self) && protocols.isEmpty { + decl = "required init() { }" + } else { + decl = "init() { }" + } + return [ decl ] + } +} diff --git a/test/Macros/macro_expand_member_with_conformances.swift b/test/Macros/macro_expand_member_with_conformances.swift new file mode 100644 index 0000000000000..a02e834464e79 --- /dev/null +++ b/test/Macros/macro_expand_member_with_conformances.swift @@ -0,0 +1,22 @@ +// REQUIRES: swift_swift_parser + +// RUN: %empty-directory(%t) +// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath + +// RUN: %target-typecheck-verify-swift -enable-experimental-feature ExtensionMacros -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -swift-version 5 -I %t +protocol DefaultInit { + init() +} + +@attached(extension, conformances: DefaultInit) +@attached(member, conformances: DefaultInit, names: named(init())) +macro DefaultInit() = #externalMacro(module: "MacroDefinition", type: "RequiredDefaultInitMacro") + +@DefaultInit +class C { } + +@DefaultInit +class D: C { } + +@DefaultInit +struct E { } diff --git a/test/Runtime/check_create_type.swift b/test/Runtime/check_create_type.swift new file mode 100644 index 0000000000000..147a36249de5a --- /dev/null +++ b/test/Runtime/check_create_type.swift @@ -0,0 +1,129 @@ +// RUN: %target-run-simple-swift(-Xfrontend -disable-availability-checking) +// REQUIRES: executable_test + +// UNSUPPORTED: CPU=arm64e +// UNSUPPORTED: use_os_stdlib +// UNSUPPORTED: back_deployment_runtime + +import StdlibUnittest + +let testSuite = TestSuite("CheckedCreateType") + +struct Variadic { + struct Nested {} +} + +@_silgen_name("swift_allocateMetadataPack") +func allocateMetadataPack( + _ packPointer: UnsafeRawPointer, + _ packCount: UInt +) -> UnsafeRawPointer + +@_silgen_name("_swift_instantiateCheckedGenericMetadata") +func _instantiateCheckedGenericMetadata( + _ descriptor: UnsafeRawPointer, + _ genericArgs: UnsafeRawPointer, + _ genericArgsSize: UInt +) -> Any.Type? + +func metaPointer(_ x: Any.Type) -> UnsafeRawPointer { + unsafeBitCast(x, to: UnsafeRawPointer.self) +} + +testSuite.test("_swift_checkedCreateType non-variadic") { + let dictMeta = unsafeBitCast( + [Int: Int].self as Any.Type, + to: UnsafeRawPointer.self + ) + let dictDesc = dictMeta.load( + fromByteOffset: MemoryLayout.size, + as: UnsafeRawPointer.self + ) + + let dictGenericArgs: [Any.Type] = [String.self, Double.self] + + dictGenericArgs.withUnsafeBufferPointer { + let newDict = _instantiateCheckedGenericMetadata( + dictDesc, + UnsafeRawPointer($0.baseAddress!), + UInt($0.count) + ) + + expectTrue(newDict == [String: Double].self) + } +} + +testSuite.test("_swift_checkedCreateType variadic") { + let variMeta = unsafeBitCast( + Variadic< >.self as Any.Type, + to: UnsafeRawPointer.self + ) + let variDesc = variMeta.load( + fromByteOffset: MemoryLayout.size, + as: UnsafeRawPointer.self + ) + + let variPack: [Any.Type] = [Int.self, Int8.self, UInt8.self] + + variPack.withUnsafeBufferPointer { pack in + let packPointer = allocateMetadataPack( + UnsafeRawPointer(pack.baseAddress!), + UInt(pack.count) + ) + let genericArgs = [packPointer] + + genericArgs.withUnsafeBufferPointer { genericArgs in + let newVari = _instantiateCheckedGenericMetadata( + variDesc, + UnsafeRawPointer(genericArgs.baseAddress!), + UInt(genericArgs.count) + ) + + expectTrue(newVari == Variadic.self) + } + } +} + +testSuite.test("_swift_checkedCreateType variadic nested with requirements") { + let nestedMeta = unsafeBitCast( + Variadic< >.Nested<()>.self as Any.Type, + to: UnsafeRawPointer.self + ) + let nestedDesc = nestedMeta.load( + fromByteOffset: MemoryLayout.size, + as: UnsafeRawPointer.self + ) + + let variPack: [Any.Type] = [String.self, [Int].self, UInt64.self] + + let nestedPack: [Any.Type] = [Int.self, Substring.self, Bool.self] + + nestedPack.withUnsafeBufferPointer { nestedPack in + variPack.withUnsafeBufferPointer { variPack in + let nestedGenericArgs = [ + allocateMetadataPack( + UnsafeRawPointer(variPack.baseAddress!), + UInt(variPack.count) + ), + metaPointer(Int16.self), + allocateMetadataPack( + UnsafeRawPointer(nestedPack.baseAddress!), + UInt(nestedPack.count) + ) + ] + + nestedGenericArgs.withUnsafeBufferPointer { nestedGenericArgs in + + let newNested = _instantiateCheckedGenericMetadata( + nestedDesc, + UnsafeRawPointer(nestedGenericArgs.baseAddress!), + UInt(nestedGenericArgs.count) + ) + + expectTrue(newNested == Variadic.Nested.self) + } + } + } +} + +runAllTests() diff --git a/test/Sema/access-level-and-non-resilient-import.swift b/test/Sema/access-level-and-non-resilient-import.swift index 9299e8f288aac..6e87186296f6d 100644 --- a/test/Sema/access-level-and-non-resilient-import.swift +++ b/test/Sema/access-level-and-non-resilient-import.swift @@ -17,18 +17,22 @@ /// A resilient client will error on public imports. // RUN: %target-swift-frontend -typecheck %t/Client_Swift5.swift -I %t \ // RUN: -enable-library-evolution -swift-version 5 \ -// RUN: -enable-experimental-feature AccessLevelOnImport -verify +// RUN: -enable-experimental-feature AccessLevelOnImport -verify \ +// RUN: -package-name pkg // RUN: %target-swift-frontend -typecheck %t/Client_Swift6.swift -I %t \ // RUN: -enable-library-evolution -swift-version 6 \ -// RUN: -enable-experimental-feature AccessLevelOnImport -verify +// RUN: -enable-experimental-feature AccessLevelOnImport -verify \ +// RUN: -package-name pkg /// A non-resilient client doesn't complain. // RUN: %target-swift-frontend -typecheck %t/Client_Swift5.swift -I %t \ // RUN: -swift-version 5 \ -// RUN: -enable-experimental-feature AccessLevelOnImport +// RUN: -enable-experimental-feature AccessLevelOnImport \ +// RUN: -package-name pkg // RUN: %target-swift-frontend -typecheck %t/Client_Swift6.swift -I %t \ // RUN: -swift-version 6 \ -// RUN: -enable-experimental-feature AccessLevelOnImport +// RUN: -enable-experimental-feature AccessLevelOnImport \ +// RUN: -package-name pkg //--- DefaultLib.swift //--- PublicLib.swift diff --git a/test/Sema/access-level-import-diag-priority.swift b/test/Sema/access-level-import-diag-priority.swift index e57a102d68006..2e39539db96b5 100644 --- a/test/Sema/access-level-import-diag-priority.swift +++ b/test/Sema/access-level-import-diag-priority.swift @@ -12,9 +12,11 @@ /// Check diagnostics. // RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t \ -// RUN: -enable-experimental-feature AccessLevelOnImport -verify +// RUN: -enable-experimental-feature AccessLevelOnImport -verify \ +// RUN: -package-name pkg // RUN: %target-swift-frontend -typecheck %t/LocalVsImportClient.swift -I %t \ -// RUN: -enable-experimental-feature AccessLevelOnImport -verify +// RUN: -enable-experimental-feature AccessLevelOnImport -verify \ +// RUN: -package-name pkg //--- PublicLib.swift public struct PublicImportType {} diff --git a/test/Sema/access-level-import-flag-check.swift b/test/Sema/access-level-import-flag-check.swift index bf2282c144db1..c93e8c966f5c6 100644 --- a/test/Sema/access-level-import-flag-check.swift +++ b/test/Sema/access-level-import-flag-check.swift @@ -9,9 +9,11 @@ // RUN: %target-swift-frontend -emit-module %t/PrivateLib.swift -o %t /// Check flag requirement, without and with the flag. -// RUN: %target-swift-frontend -typecheck %t/ClientWithoutTheFlag.swift -I %t -verify +// RUN: %target-swift-frontend -typecheck %t/ClientWithoutTheFlag.swift -I %t -verify \ +// RUN: -package-name package // RUN: %target-swift-frontend -typecheck %t/ClientWithoutTheFlag.swift -I %t \ -// RUN: -enable-experimental-feature AccessLevelOnImport +// RUN: -enable-experimental-feature AccessLevelOnImport \ +// RUN: -package-name package // REQUIRES: asserts //--- PublicLib.swift diff --git a/test/Sema/access-level-import-inconsistencies.swift b/test/Sema/access-level-import-inconsistencies.swift index cac2c4969b509..4f33f15a84862 100644 --- a/test/Sema/access-level-import-inconsistencies.swift +++ b/test/Sema/access-level-import-inconsistencies.swift @@ -21,7 +21,8 @@ public struct LibType {} // RUN: %target-swift-frontend -typecheck %t/OneFile_AllExplicit.swift -I %t \ -// RUN: -enable-experimental-feature AccessLevelOnImport -verify +// RUN: -enable-experimental-feature AccessLevelOnImport -verify \ +// RUN: -package-name package //--- OneFile_AllExplicit.swift public import Lib package import Lib @@ -30,7 +31,8 @@ fileprivate import Lib private import Lib // RUN: %target-swift-frontend -typecheck %t/ManyFiles_AllExplicit_File?.swift -I %t \ -// RUN: -enable-experimental-feature AccessLevelOnImport -verify +// RUN: -enable-experimental-feature AccessLevelOnImport -verify \ +// RUN: -package-name package //--- ManyFiles_AllExplicit_FileA.swift public import Lib //--- ManyFiles_AllExplicit_FileB.swift diff --git a/test/Sema/access-level-import-inlinable.swift b/test/Sema/access-level-import-inlinable.swift index 8c98a950e7f20..82af129542c0e 100644 --- a/test/Sema/access-level-import-inlinable.swift +++ b/test/Sema/access-level-import-inlinable.swift @@ -18,7 +18,8 @@ /// Check diagnostics. // RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t \ // RUN: -enable-library-evolution -swift-version 5 \ -// RUN: -enable-experimental-feature AccessLevelOnImport -verify +// RUN: -enable-experimental-feature AccessLevelOnImport -verify \ +// RUN: -package-name package //--- PublicLib.swift public protocol PublicImportProto { diff --git a/test/Sema/access-level-import-parsing.swift b/test/Sema/access-level-import-parsing.swift index 99c7a86a48aff..b6f8328a69af2 100644 --- a/test/Sema/access-level-import-parsing.swift +++ b/test/Sema/access-level-import-parsing.swift @@ -11,7 +11,8 @@ /// Check that all access levels are accepted, except for 'open'. // RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t \ -// RUN: -enable-experimental-feature AccessLevelOnImport -verify +// RUN: -enable-experimental-feature AccessLevelOnImport -verify \ +// RUN: -package-name package //--- PublicLib.swift //--- PackageLib.swift diff --git a/test/Sema/package-import-no-package-name.swift b/test/Sema/package-import-no-package-name.swift new file mode 100644 index 0000000000000..34395d7243eba --- /dev/null +++ b/test/Sema/package-import-no-package-name.swift @@ -0,0 +1,17 @@ +/// Report uses of package import without a package. + +// RUN: %empty-directory(%t) +// RUN: split-file --leading-lines %s %t + +// RUN: %target-swift-frontend -emit-module %t/PackageLib.swift -o %t +// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t \ +// RUN: -enable-experimental-feature AccessLevelOnImport -verify +// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t \ +// RUN: -enable-experimental-feature AccessLevelOnImport \ +// RUN: -package-name pkg + +//--- PackageLib.swift +public struct PackageImportType {} + +//--- Client.swift +package import PackageLib // expected-error {{package import can only be used from a module with a package name; set it with the compiler flag -package-name}} diff --git a/test/Serialization/access-level-import-dependencies.swift b/test/Serialization/access-level-import-dependencies.swift index a5a901fbf6c78..cf0298336ce99 100644 --- a/test/Serialization/access-level-import-dependencies.swift +++ b/test/Serialization/access-level-import-dependencies.swift @@ -49,6 +49,7 @@ private import HiddenDep import PublicDep // RUN: %target-swift-frontend -typecheck %t/ClientOfNonPublic.swift -I %t \ +// RUN: -package-name pkg \ // RUN: -Rmodule-loading 2>&1 | %FileCheck -check-prefix=HIDDEN-DEP %s // HIDDEN-DEP-NOT: loaded module 'HiddenDep' //--- ClientOfNonPublic.swift @@ -61,6 +62,7 @@ import PrivateDep // RUN: %target-swift-frontend -emit-module %t/PublicDep.swift -o %t -I %t \ // RUN: -enable-experimental-feature AccessLevelOnImport // RUN: %target-swift-frontend -emit-module %t/PackageDep.swift -o %t -I %t \ +// RUN: -package-name MyPackage \ // RUN: -enable-experimental-feature AccessLevelOnImport // RUN: %target-swift-frontend -emit-module %t/InternalDep.swift -o %t -I %t \ // RUN: -enable-experimental-feature AccessLevelOnImport @@ -110,6 +112,7 @@ import PrivateDep // RUN: %target-swift-frontend -typecheck %t/TestableClientOfPublic.swift -I %t \ // RUN: -Rmodule-loading 2>&1 | %FileCheck -check-prefix=VISIBLE-DEP %s // RUN: %target-swift-frontend -typecheck %t/TestableClientOfNonPublic.swift -I %t \ +// RUN: -package-name pkg \ // RUN: -Rmodule-loading 2>&1 | %FileCheck -check-prefix=VISIBLE-DEP %s /// In the case of a testable of a module reexporting another Swift module, @@ -132,6 +135,7 @@ import PrivateDep /// Fail if the transitive dependency is missing. // RUN: rm %t/HiddenDep.swiftmodule // RUN: %target-swift-frontend -typecheck %t/TestableClientOfNonPublic.swift -I %t \ +// RUN: -package-name pkg \ // RUN: -verify -show-diagnostics-after-fatal /// In a multi-file scenario, we try and fail to load the transitive dependency diff --git a/test/SourceKit/Sema/educational_note_diags.swift b/test/SourceKit/Sema/educational_note_diags.swift index efe0d09c108c9..baec66c00c2c9 100644 --- a/test/SourceKit/Sema/educational_note_diags.swift +++ b/test/SourceKit/Sema/educational_note_diags.swift @@ -1,4 +1,5 @@ -extension (Int, Int) {} +typealias Crap = () -> () +extension Crap {} // RUN: %sourcekitd-test -req=sema %s -- %s | %FileCheck %s -check-prefix=NO_OVERRIDE diff --git a/test/attr/ApplicationMain/attr_main_tuple_extension.swift b/test/attr/ApplicationMain/attr_main_tuple_extension.swift index b8a02493be7c9..afedab06a11cb 100644 --- a/test/attr/ApplicationMain/attr_main_tuple_extension.swift +++ b/test/attr/ApplicationMain/attr_main_tuple_extension.swift @@ -1,7 +1,7 @@ // RUN: %target-swift-frontend -typecheck -parse-as-library -verify %s @main -extension (Int, String) { // expected-error {{non-nominal type '(Int, String)' cannot be extended}} +extension Int.Type { // expected-error {{cannot extend a metatype 'Int.Type'}} static func main() { } } diff --git a/test/decl/ext/extensions.swift b/test/decl/ext/extensions.swift index ecc25f1b9a554..078024efb00df 100644 --- a/test/decl/ext/extensions.swift +++ b/test/decl/ext/extensions.swift @@ -87,11 +87,6 @@ protocol P1 {} protocol P2 {} -extension () {} // expected-error {{non-nominal type '()' cannot be extended}} {{educational-notes=nominal-types}} - -typealias TupleAlias = (x: Int, y: Int) -extension TupleAlias {} // expected-error{{non-nominal type 'TupleAlias' (aka '(x: Int, y: Int)') cannot be extended}} {{educational-notes=nominal-types}} - // Test property accessors in extended types class C {} extension C { diff --git a/test/decl/protocol/req/associated_type_tuple.swift b/test/decl/protocol/req/associated_type_tuple.swift new file mode 100644 index 0000000000000..22cece2ab38ab --- /dev/null +++ b/test/decl/protocol/req/associated_type_tuple.swift @@ -0,0 +1,24 @@ +// RUN: %target-typecheck-verify-swift -enable-experimental-feature TupleConformances + +typealias Tuple = (repeat each T) + +protocol P1 { + associatedtype A // expected-note {{protocol requires nested type 'A'; add type alias 'A' with underlying type '(repeat (each T).A)' for conformance}} +} + +extension Tuple: P1 where repeat each T: P1 {} // expected-error {{type '(repeat each T)' does not conform to protocol 'P1'}} + +protocol P2 { + associatedtype A = Int // expected-note {{default type 'Int' for associated type 'A' (from protocol 'P2') is unsuitable for tuple conformance; the associated type requirement must be fulfilled by a type alias with underlying type '(repeat (each T).A)'}} +} + +extension Tuple: P2 where repeat each T: P2 {} // expected-error {{type '(repeat each T)' does not conform to protocol 'P2'}} + +protocol P3 { + associatedtype A // expected-note {{unable to infer associated type 'A' for protocol 'P3'}} + func f() -> A +} + +extension Tuple: P3 where repeat each T: P3 { // expected-error {{type '(repeat each T)' does not conform to protocol 'P3'}} + func f() -> Int {} // expected-note {{cannot infer 'A' = 'Int' in tuple conformance because the associated type requirement must be fulfilled by a type alias with underlying type '(repeat (each T).A)'}} +} diff --git a/test/diagnostics/educational-notes.swift b/test/diagnostics/educational-notes.swift index 335c750376534..417be8ed06587 100644 --- a/test/diagnostics/educational-notes.swift +++ b/test/diagnostics/educational-notes.swift @@ -10,10 +10,11 @@ let x = 1 + // NO-COLOR-NOT: {{-+$}} // A diagnostic with an educational note using supported markdown features -extension (Int, Int) {} -// CHECK:{{.*}}[0merror: non-nominal type '(Int, Int)' cannot be extended -// CHECK-NEXT:extension (Int, Int) {} -// CHECK-NEXT:^ ~~~~~~~~~~ +typealias Crap = () -> () +extension Crap {} +// CHECK:{{.*}}[0merror: non-nominal type 'Crap' (aka '() -> ()') cannot be extended +// CHECK-NEXT:extension Crap {} +// CHECK-NEXT:^ ~~~~ // CHECK-NEXT:Nominal Types // CHECK-NEXT:-------------- // CHECK-EMPTY: @@ -39,9 +40,9 @@ extension (Int, Int) {} // CHECK-NEXT:Header 1 // CHECK-NEXT:Header 3 -// NO-COLOR:{{.*}}error: non-nominal type '(Int, Int)' cannot be extended -// NO-COLOR-NEXT:extension (Int, Int) {} -// NO-COLOR-NEXT:^ ~~~~~~~~~~ +// NO-COLOR:{{.*}}error: non-nominal type 'Crap' (aka '() -> ()') cannot be extended +// NO-COLOR-NEXT:extension Crap {} +// NO-COLOR-NEXT:^ ~~~~ // NO-COLOR-NEXT:Nominal Types // NO-COLOR-NEXT:-------------- // NO-COLOR-EMPTY: @@ -69,15 +70,15 @@ extension (Int, Int) {} // CHECK-DESCRIPTIVE: educational-notes.swift // CHECK-DESCRIPTIVE-NEXT: | // A diagnostic with an educational note -// CHECK-DESCRIPTIVE-NEXT: | extension (Int, Int) {} +// CHECK-DESCRIPTIVE-NEXT: | extension Crap {} // CHECK-DESCRIPTIVE-NEXT: | ^ error: expected expression after operator // CHECK-DESCRIPTIVE-NEXT: | // CHECK-DESCRIPTIVE: educational-notes.swift // CHECK-DESCRIPTIVE-NEXT: | // A diagnostic with an educational note -// CHECK-DESCRIPTIVE-NEXT: | extension (Int, Int) {} -// CHECK-DESCRIPTIVE-NEXT: | ~~~~~~~~~~ -// CHECK-DESCRIPTIVE-NEXT: | ^ error: non-nominal type '(Int, Int)' cannot be extended +// CHECK-DESCRIPTIVE-NEXT: | extension Crap {} +// CHECK-DESCRIPTIVE-NEXT: | ~~~~ +// CHECK-DESCRIPTIVE-NEXT: | ^ error: non-nominal type 'Crap' (aka '() -> ()') cannot be extended // CHECK-DESCRIPTIVE-NEXT: | // CHECK-DESCRIPTIVE-NEXT: Nominal Types // CHECK-DESCRIPTIVE-NEXT: ------------- diff --git a/test/diagnostics/verifier.swift b/test/diagnostics/verifier.swift index 000d785549aa3..39ed73d6b4ca6 100644 --- a/test/diagnostics/verifier.swift +++ b/test/diagnostics/verifier.swift @@ -33,13 +33,14 @@ func b() { // CHECK: unexpected warning produced: initialization of immutable value 'c' was never used // CHECK-WARNINGS-AS-ERRORS: unexpected error produced: initialization of immutable value 'c' was never used -extension (Int, Int) {} // expected-error {{non-nominal type '(Int, Int)' cannot be extended}} {{educational-notes=foo-bar-baz}} +typealias Crap = () -> () +extension Crap {} // expected-error {{non-nominal type 'Crap' (aka '() -> ()') cannot be extended}} {{educational-notes=foo-bar-baz}} // CHECK: error: expected educational note(s) not seen; actual educational note(s): {{[{][{]}}educational-notes=nominal-types{{[}][}]}} -extension (Bool, Int) {} // expected-error {{non-nominal type '(Bool, Int)' cannot be extended}} {{educational-notes=nominal-types}} {{educational-notes=nominal-types}} +extension Crap {} // expected-error {{non-nominal type 'Crap' (aka '() -> ()') cannot be extended}} {{educational-notes=nominal-types}} {{educational-notes=nominal-types}} // CHECK: error: each verified diagnostic may only have one {{[{][{]}}educational-notes=<#notes#>{{[}][}]}} declaration -extension (Bool, Bool) {} // expected-error {{non-nominal type '(Bool, Bool)' cannot be extended}} {{educational-notes=nominal-types,foo-bar-baz}} +extension Crap {} // expected-error {{non-nominal type 'Crap' (aka '() -> ()') cannot be extended}} {{educational-notes=nominal-types,foo-bar-baz}} // CHECK: error: expected educational note(s) not seen; actual educational note(s): {{[{][{]}}educational-notes=nominal-types{{[}][}]}} // Verify the serialized diags have the right magic at the top. diff --git a/test/embedded/basic-errors-no-stdlib.swift b/test/embedded/basic-errors-no-stdlib.swift new file mode 100644 index 0000000000000..0d255b2f509e7 --- /dev/null +++ b/test/embedded/basic-errors-no-stdlib.swift @@ -0,0 +1,9 @@ +// RUN: not %target-swift-frontend -emit-ir %s -parse-stdlib -enable-experimental-feature Embedded 2>&1 | %FileCheck %s + +public protocol Player {} +struct Concrete: Player {} + +// CHECK: error: existential can cause metadata allocation or locks +public func test() -> any Player { + Concrete() +} diff --git a/test/embedded/basic-irgen-no-stdlib.swift b/test/embedded/basic-irgen-no-stdlib.swift new file mode 100644 index 0000000000000..6549e5c346ef6 --- /dev/null +++ b/test/embedded/basic-irgen-no-stdlib.swift @@ -0,0 +1,35 @@ +// RUN: %target-swift-emit-ir %s -parse-stdlib -enable-experimental-feature Embedded -target arm64e-apple-none | %FileCheck %s + +// TODO: investigate why windows is generating more metadata. +// XFAIL: OS=windows-msvc + +struct Bool {} + +protocol Player { + func play() + var canPlay: Bool { get } +} + +struct Concrete : Player { + func play() { } + var canPlay: Bool { Bool() } +} + +func start(p: some Player) { + p.play() +} + +public func main() { + start(p: Concrete()) +} + +// CHECK-LABEL: define {{.*}}void @"$s4main8ConcreteVACycfC"() + +// CHECK-LABEL: define {{.*}}void @"$s4main5start1pyx_tAA6PlayerRzlFAA8ConcreteV_Tg5"() + +// CHECK-LABEL: define {{.*}}void @"$s4mainAAyyF"() +// CHECK-NEXT: entry: +// CHECK-NEXT: call swiftcc void @"$s4main8ConcreteVACycfC"() +// CHECK-NEXT: call swiftcc void @"$s4main5start1pyx_tAA6PlayerRzlFAA8ConcreteV_Tg5"() +// CHECK-NEXT: ret void +// CHECK-NEXT: } diff --git a/test/embedded/basic-modules-no-stdlib.swift b/test/embedded/basic-modules-no-stdlib.swift new file mode 100644 index 0000000000000..4d3b862f7a839 --- /dev/null +++ b/test/embedded/basic-modules-no-stdlib.swift @@ -0,0 +1,46 @@ +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s + +// RUN: %target-swift-frontend -swift-version 5 -emit-module -o %t/MyModule.swiftmodule %t/MyModule.swift -parse-stdlib -enable-experimental-feature Embedded +// RUN: %target-swift-frontend -swift-version 5 -emit-ir -I %t %t/Main.swift -parse-stdlib -enable-experimental-feature Embedded | %FileCheck %s + +// TODO: investigate why windows is generating more metadata. +// XFAIL: OS=windows-msvc + +// BEGIN MyModule.swift + +public struct Bool {} + +public protocol Player { + func play() + var canPlay: Bool { get } +} + +public struct Concrete : Player { + public init() { } + public func play() { } + public var canPlay: Bool { Bool() } +} + +public func start(p: some Player) { + p.play() +} + +public func moduleMain() { + start(p: Concrete()) +} + +// BEGIN Main.swift + +import MyModule + +public func main() { + moduleMain() +} + +// CHECK: define {{.*}}@main{{.*}} { +// CHECK: define {{.*}}void @"$s4Main4mainyyF"{{.*}} { +// CHECK: define {{.*}}void @"$s8MyModule10moduleMainyyF"{{.*}} { +// CHECK: define {{.*}}void @"$s8MyModule8ConcreteVACycfC"{{.*}} { +// CHECK: define {{.*}}void @"$s8MyModule5start1pyx_tAA6PlayerRzlFAA8ConcreteV_Tg5"{{.*}} { +// CHECK: define {{.*}}void @"$s8MyModule8ConcreteV4playyyF"{{.*}} { diff --git a/test/embedded/basic-modules-validation-no-stdlib.swift b/test/embedded/basic-modules-validation-no-stdlib.swift new file mode 100644 index 0000000000000..e14ee0561eeca --- /dev/null +++ b/test/embedded/basic-modules-validation-no-stdlib.swift @@ -0,0 +1,29 @@ +// RUN: %empty-directory(%t) +// RUN: %{python} %utils/split_file.py -o %t %s + +// both modules are embedded - ok +// RUN: %target-swift-frontend -emit-module -o %t/MyModule.swiftmodule %t/MyModule.swift -parse-stdlib -enable-experimental-feature Embedded +// RUN: %target-swift-frontend -emit-ir -I %t %t/Main.swift -parse-stdlib -enable-experimental-feature Embedded + +// MyModule is not embedded - error +// RUN: %target-swift-frontend -emit-module -o %t/MyModule.swiftmodule %t/MyModule.swift -parse-stdlib +// RUN: not %target-swift-frontend -emit-ir -I %t %t/Main.swift -parse-stdlib -enable-experimental-feature Embedded 2>&1 | %FileCheck %s --check-prefix CHECK-A + +// main module is not embedded - error +// RUN: %target-swift-frontend -emit-module -o %t/MyModule.swiftmodule %t/MyModule.swift -parse-stdlib -enable-experimental-feature Embedded +// RUN: not %target-swift-frontend -emit-ir -I %t %t/Main.swift -parse-stdlib 2>&1 | %FileCheck %s --check-prefix CHECK-B + +// BEGIN MyModule.swift + +public func foo() { } + +// BEGIN Main.swift + +import MyModule + +public func main() { + foo() +} + +// CHECK-A: error: module 'MyModule' cannot be imported in embedded Swift mode +// CHECK-B: error: module 'MyModule' cannot be imported because it was built with embedded Swift diff --git a/test/embedded/evolution-with-embedded-diag.swift b/test/embedded/evolution-with-embedded-diag.swift new file mode 100644 index 0000000000000..00bd5c9197610 --- /dev/null +++ b/test/embedded/evolution-with-embedded-diag.swift @@ -0,0 +1,4 @@ +// RUN: not %target-swift-frontend -emit-ir %s -enable-library-evolution -enable-experimental-feature Embedded 2>&1 | %FileCheck %s +// RUN: not %target-swift-frontend -emit-ir %s -enable-resilience -enable-experimental-feature Embedded 2>&1 | %FileCheck %s + +// CHECK: error: Library evolution cannot be enabled with embedded Swift. diff --git a/test/expr/cast/as_coerce.swift b/test/expr/cast/as_coerce.swift index 50fae5da5d1a0..e61b997d80012 100644 --- a/test/expr/cast/as_coerce.swift +++ b/test/expr/cast/as_coerce.swift @@ -163,3 +163,28 @@ let _: Int = any as Int // expected-error {{'Any' is not convertible to 'Int'}} // expected-note@-1 {{did you mean to use 'as!' to force downcast?}} {{18-20=as!}} let _: Int? = any as Int // expected-error {{'Any' is not convertible to 'Int'}} // expected-note@-1 {{did you mean to use 'as?' to conditionally downcast?}} {{19-21=as?}} + +// https://github.com/apple/swift/issues/63926 + +do { + func fn(_: Int) {} // expected-note {{found candidate with type '(Int) -> ()'}} + // expected-note@-1 {{candidate '(Int) -> ()' has 1 parameter, but context '() -> Void' has 0}} + func fn(_: Bool) {} // expected-note {{found candidate with type '(Bool) -> ()'}} + // expected-note@-1 {{candidate '(Bool) -> ()' has 1 parameter, but context '() -> Void' has 0}} + + func fn_1(_: Bool) {} + + let i = 0 + // Missing parameters. + (fn as (Int, Int) -> Void)(i, i) // expected-error {{cannot convert value of type '(Int) -> ()' to type '(Int, Int) -> Void' in coercion}} + (fn as (Bool, Bool) -> Void)(i, i) // expected-error {{cannot convert value of type '(Bool) -> ()' to type '(Bool, Bool) -> Void' in coercion}} + // expected-error@-1 2{{type 'Int' cannot be used as a boolean; test for '!= 0' instead}} + (fn as (Int, Bool) -> Void)(i, i) // expected-error {{cannot convert value of type '(Int) -> ()' to type '(Int, Bool) -> Void' in coercion}} + // expected-error@-1 {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}} + (fn as (String) -> Void)(i) // expected-error {{no exact matches in reference to local function 'fn'}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'String'}} + + // Extraneous parameters. + (fn as () -> Void)() // expected-error {{no exact matches in reference to local function 'fn'}} + (fn_1 as () -> Void)() // expected-error {{cannot convert value of type '(Bool) -> ()' to type '() -> Void' in coercion}} +} diff --git a/test/lit.cfg b/test/lit.cfg index 3d2e305ac69d9..62b1c25671b72 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -1643,15 +1643,17 @@ elif (run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'openbsd', 'windows- libdispatch_artifact_dir = config.libdispatch_build_path libdispatch_swift_module_dir = make_path(libdispatch_artifact_dir, 'src', 'swift', 'swift') libdispatch_source_dir = make_path(config.swift_src_root, os.pardir, 'swift-corelibs-libdispatch') + libdispatch_vfs_yaml = make_path(libdispatch_artifact_dir, 'dispatch-vfs-overlay.yaml') libdispatch_artifacts = [ + libdispatch_vfs_yaml, make_path(libdispatch_artifact_dir, 'libdispatch.so'), make_path(libdispatch_artifact_dir, 'libswiftDispatch.so'), make_path(libdispatch_swift_module_dir, 'Dispatch.swiftmodule')] if (all(os.path.exists(p) for p in libdispatch_artifacts)): config.available_features.add('libdispatch') config.libdispatch_artifact_dir = libdispatch_artifact_dir - config.import_libdispatch = ('-I %s -I %s -L %s' - % (libdispatch_source_dir, libdispatch_swift_module_dir, libdispatch_artifact_dir)) + config.import_libdispatch = ('-I %s -I %s -L %s -vfsoverlay %s' + % (libdispatch_source_dir, libdispatch_swift_module_dir, libdispatch_artifact_dir, libdispatch_vfs_yaml)) libdispatch_static_artifact_dir = os.path.join(config.libdispatch_static_build_path, 'lib') libdispatch_static_artifacts = [ diff --git a/test/sil-passpipeline-dump/basic.test-sh b/test/sil-passpipeline-dump/basic.test-sh index b6b3326399070..658689e968124 100644 --- a/test/sil-passpipeline-dump/basic.test-sh +++ b/test/sil-passpipeline-dump/basic.test-sh @@ -7,7 +7,8 @@ // CHECK: --- // CHECK: name: Non-Diagnostic Mandatory Optimizations -// CHECK: passes: [ "for-each-loop-unroll", "mandatory-arc-opts", "onone-prespecializer" ] +// CHECK: passes: [ "for-each-loop-unroll", "mandatory-arc-opts", "onone-prespecializer", +// CHECK-NEXT: "cmo" ] // CHECK: --- // CHECK: name: Serialization // CHECK: passes: [ "serialize-sil", "sil-moved-async-var-dbginfo-propagator", diff --git a/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake b/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake index 7e2e1bc16e763..2293712165751 100644 --- a/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake +++ b/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake @@ -115,12 +115,6 @@ function(add_sourcekit_swift_runtime_link_flags target path HAS_SWIFT_MODULES) LINK_FLAGS " -lobjc ") endif() # HAS_SWIFT_MODULES AND ASKD_BOOTSTRAPPING_MODE - - if(SWIFT_SWIFT_PARSER) - # Add rpath to the host Swift libraries. - file(RELATIVE_PATH relative_hostlib_path "${path}" "${SWIFTLIB_DIR}/host") - list(APPEND RPATH_LIST "@loader_path/${relative_hostlib_path}") - endif() elseif(SWIFT_HOST_VARIANT_SDK MATCHES "LINUX|ANDROID|OPENBSD" AND HAS_SWIFT_MODULES AND ASKD_BOOTSTRAPPING_MODE) set(swiftrt "swiftImageRegistrationObject${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_OBJECT_FORMAT}-${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}-${SWIFT_HOST_VARIANT_ARCH}") if(ASKD_BOOTSTRAPPING_MODE MATCHES "HOSTTOOLS|CROSSCOMPILE") @@ -156,15 +150,22 @@ function(add_sourcekit_swift_runtime_link_flags target path HAS_SWIFT_MODULES) else() message(FATAL_ERROR "Unknown ASKD_BOOTSTRAPPING_MODE '${ASKD_BOOTSTRAPPING_MODE}'") endif() + endif() - if(SWIFT_SWIFT_PARSER) + if(SWIFT_SWIFT_PARSER) + if(SWIFT_HOST_VARIANT_SDK IN_LIST SWIFT_DARWIN_PLATFORMS) + # Add rpath to the host Swift libraries. + file(RELATIVE_PATH relative_hostlib_path "${path}" "${SWIFTLIB_DIR}/host") + list(APPEND RPATH_LIST "@loader_path/${relative_hostlib_path}") + elseif(SWIFT_HOST_VARIANT_SDK MATCHES "LINUX|ANDROID|OPENBSD") # Add rpath to the host Swift libraries. file(RELATIVE_PATH relative_hostlib_path "${path}" "${SWIFTLIB_DIR}/host") list(APPEND RPATH_LIST "$ORIGIN/${relative_hostlib_path}") + else() + target_link_directories(${target} PRIVATE + ${SWIFT_PATH_TO_SWIFT_SDK}/usr/lib/swift/${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}/${SWIFT_HOST_VARIANT_ARCH}) endif() - endif() - if(SWIFT_SWIFT_PARSER) # For the "end step" of bootstrapping configurations on Darwin, need to be # able to fall back to the SDK directory for libswiftCore et al. if (BOOTSTRAPPING_MODE MATCHES "BOOTSTRAPPING.*") @@ -436,7 +437,6 @@ macro(add_sourcekit_framework name) file(RELATIVE_PATH relative_lib_path "${framework_location}/Versions/A" "${SOURCEKIT_LIBRARY_OUTPUT_INTDIR}") list(APPEND RPATH_LIST "@loader_path/${relative_lib_path}") - list(APPEND RPATH_LIST "@loader_path/${relative_lib_path}/swift/host") set_target_properties(${name} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE @@ -472,7 +472,6 @@ macro(add_sourcekit_framework name) file(RELATIVE_PATH relative_lib_path "${framework_location}" "${SOURCEKIT_LIBRARY_OUTPUT_INTDIR}") list(APPEND RPATH_LIST "@loader_path/${relative_lib_path}") - list(APPEND RPATH_LIST "@loader_path/${relative_lib_path}/swift/host") set_target_properties(${name} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE @@ -564,7 +563,6 @@ macro(add_sourcekit_xpc_service name framework_target) file(RELATIVE_PATH relative_lib_path "${xpc_bin_dir}" "${lib_dir}") list(APPEND RPATH_LIST "@loader_path/${relative_lib_path}") - list(APPEND RPATH_LIST "@loader_path/${relative_lib_path}/swift/host") # Add rpath for sourcekitdInProc # lib/${framework_target}.framework/Versions/A/XPCServices/${name}.xpc/Contents/MacOS/${name} diff --git a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp index 18cd8a487f421..1c492e1c855eb 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp @@ -623,7 +623,7 @@ static void reportRelated(ASTContext &Ctx, const Decl *D, passExtends(TD, Consumer); } - passInherits(ED->getInherited(), Consumer); + passInherits(ED->getInherited().getEntries(), Consumer); } else if (auto *TAD = dyn_cast(D)) { @@ -631,7 +631,7 @@ static void reportRelated(ASTContext &Ctx, const Decl *D, // If underlying type exists, report the inheritance and conformance of the // underlying type. if (auto NM = Ty->getAnyNominal()) { - passInherits(NM->getInherited(), Consumer); + passInherits(NM->getInherited().getEntries(), Consumer); passConforms(NM->getSatisfiedProtocolRequirements(/*Sorted=*/true), Consumer); return; diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt index 16a194da9b5f9..f08e56ee3c2f1 100644 --- a/tools/driver/CMakeLists.txt +++ b/tools/driver/CMakeLists.txt @@ -5,6 +5,8 @@ # parser is built in. function(add_swift_parser_link_libraries target) if(SWIFT_SWIFT_PARSER) + target_link_directories(${target} PRIVATE + ${SWIFT_PATH_TO_SWIFT_SDK}/usr/lib/swift/${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}/${SWIFT_HOST_VARIANT_ARCH}) target_link_libraries(${target} PRIVATE swiftCore) diff --git a/tools/libSwiftScan/libSwiftScan.cpp b/tools/libSwiftScan/libSwiftScan.cpp index 95e2804357136..82db8345e26f0 100644 --- a/tools/libSwiftScan/libSwiftScan.cpp +++ b/tools/libSwiftScan/libSwiftScan.cpp @@ -14,21 +14,55 @@ // //===----------------------------------------------------------------------===// -#include "swift/Basic/LLVMInitialize.h" #include "swift/Basic/InitializeSwiftModules.h" -#include "swift/DriverTool/DriverTool.h" +#include "swift/Basic/LLVMInitialize.h" #include "swift/DependencyScan/DependencyScanImpl.h" #include "swift/DependencyScan/DependencyScanningTool.h" #include "swift/DependencyScan/StringUtils.h" -#include "swift/Frontend/CachingUtils.h" +#include "swift/DriverTool/DriverTool.h" +#include "swift/Frontend/CompileJobCacheKey.h" #include "swift/Option/Options.h" +#include "clang/CAS/CASOptions.h" +#include "llvm/CAS/ActionCache.h" +#include "llvm/CAS/BuiltinUnifiedCASDatabases.h" #include "llvm/CAS/ObjectStore.h" +#include "llvm/Support/Error.h" +#include using namespace swift::dependencies; -using namespace swift::cas; + +namespace { +/// Helper class to manage CAS/Caching from libSwiftScan C APIs. +class SwiftScanCAS { +public: + // Compute the CASID for PCH output from invocation. + llvm::Expected computeCacheKey(llvm::ArrayRef Args, + llvm::StringRef InputPath, + swift::file_types::ID OutputKind); + + // Store content into CAS. + llvm::Expected storeContent(llvm::StringRef Content); + + // Construct SwiftScanCAS. + static llvm::Expected + createSwiftScanCAS(llvm::StringRef Path); + + static llvm::Expected + createSwiftScanCAS(clang::CASOptions &CASOpts); + +private: + SwiftScanCAS(std::shared_ptr CAS, + std::shared_ptr Cache) + : CAS(CAS), Cache(Cache) {} + + std::shared_ptr CAS; + std::shared_ptr Cache; +}; +} // namespace DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DependencyScanningTool, swiftscan_scanner_t) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(CachingTool, swiftscan_cas_t) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(clang::CASOptions, swiftscan_cas_options_t) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SwiftScanCAS, swiftscan_cas_t) //=== Private Cleanup Functions -------------------------------------------===// @@ -671,26 +705,58 @@ swiftscan_diagnostics_set_dispose(swiftscan_diagnostic_set_t* diagnostics){ //=== CAS Functions ----------------------------------------------------------// -swiftscan_cas_t swiftscan_cas_create(const char *path) { - std::string CASPath(path); - if (CASPath.empty()) - CASPath = llvm::cas::getDefaultOnDiskCASPath(); +swiftscan_cas_options_t swiftscan_cas_options_create() { + clang::CASOptions *CASOpts = new clang::CASOptions(); + return wrap(CASOpts); +} + +void swiftscan_cas_options_dispose(swiftscan_cas_options_t options) { + delete unwrap(options); +} + +void swiftscan_cas_options_set_ondisk_path(swiftscan_cas_options_t options, + const char *path) { + unwrap(options)->CASPath = path; +} + +void swiftscan_cas_options_set_plugin_path(swiftscan_cas_options_t options, + const char *path) { + unwrap(options)->PluginPath = path; +} + +bool swiftscan_cas_options_set_option(swiftscan_cas_options_t options, + const char *name, const char *value, + swiftscan_string_ref_t *error) { + unwrap(options)->PluginOptions.emplace_back(name, value); + return false; +} - CachingTool *tool = new CachingTool(CASPath); - if (!tool->isValid()) { - delete tool; +swiftscan_cas_t +swiftscan_cas_create_from_options(swiftscan_cas_options_t options, + swiftscan_string_ref_t *error) { + clang::CASOptions *opts = unwrap(options); + auto cas = SwiftScanCAS::createSwiftScanCAS(*opts); + if (!cas) { + *error = + swift::c_string_utils::create_clone(toString(cas.takeError()).c_str()); return nullptr; } - return wrap(tool); + return wrap(*cas); } void swiftscan_cas_dispose(swiftscan_cas_t cas) { delete unwrap(cas); } -swiftscan_string_ref_t -swiftscan_cas_store(swiftscan_cas_t cas, uint8_t *data, unsigned size) { +swiftscan_string_ref_t swiftscan_cas_store(swiftscan_cas_t cas, uint8_t *data, + unsigned size, + swiftscan_string_ref_t *error) { llvm::StringRef StrContent((char*)data, size); auto ID = unwrap(cas)->storeContent(StrContent); - return swift::c_string_utils::create_clone(ID.c_str()); + if (!ID) { + *error = + swift::c_string_utils::create_clone(toString(ID.takeError()).c_str()); + return swift::c_string_utils::create_null(); + } + return swift::c_string_utils::create_clone(ID->c_str()); } static swift::file_types::ID @@ -713,14 +779,62 @@ getFileTypeFromScanOutputKind(swiftscan_output_kind_t kind) { swiftscan_string_ref_t swiftscan_compute_cache_key(swiftscan_cas_t cas, int argc, const char **argv, - const char *input, swiftscan_output_kind_t kind) { + const char *input, swiftscan_output_kind_t kind, + swiftscan_string_ref_t *error) { std::vector Compilation; for (int i = 0; i < argc; ++i) Compilation.push_back(argv[i]); auto ID = unwrap(cas)->computeCacheKey(Compilation, input, getFileTypeFromScanOutputKind(kind)); - return swift::c_string_utils::create_clone(ID.c_str()); + if (!ID) { + *error = + swift::c_string_utils::create_clone(toString(ID.takeError()).c_str()); + return swift::c_string_utils::create_null(); + } + return swift::c_string_utils::create_clone(ID->c_str()); +} + +llvm::Expected +SwiftScanCAS::createSwiftScanCAS(llvm::StringRef Path) { + clang::CASOptions Opts; + Opts.CASPath = Path; + + return createSwiftScanCAS(Opts); +} + +llvm::Expected +SwiftScanCAS::createSwiftScanCAS(clang::CASOptions &CASOpts) { + auto DB = CASOpts.getOrCreateDatabases(); + if (!DB) + return DB.takeError(); + + return new SwiftScanCAS(std::move(DB->first), std::move(DB->second)); +} + +llvm::Expected +SwiftScanCAS::computeCacheKey(llvm::ArrayRef Args, + llvm::StringRef InputPath, + swift::file_types::ID OutputKind) { + auto BaseKey = swift::createCompileJobBaseCacheKey(*CAS, Args); + if (!BaseKey) + return BaseKey.takeError(); + + auto Key = swift::createCompileJobCacheKeyForOutput(*CAS, *BaseKey, InputPath, + OutputKind); + if (!Key) + return Key.takeError(); + + return CAS->getID(*Key).toString(); +} + +llvm::Expected +SwiftScanCAS::storeContent(llvm::StringRef Content) { + auto Result = CAS->storeFromString({}, Content); + if (!Result) + return Result.takeError(); + + return CAS->getID(*Result).toString(); } //=== Experimental Compiler Invocation Functions ------------------------===// diff --git a/tools/libSwiftScan/libSwiftScan.exports b/tools/libSwiftScan/libSwiftScan.exports index 9e30dbb0aaa7a..ae68b6f7d5c34 100644 --- a/tools/libSwiftScan/libSwiftScan.exports +++ b/tools/libSwiftScan/libSwiftScan.exports @@ -75,8 +75,13 @@ swiftscan_scanner_diagnostics_reset swiftscan_diagnostic_get_message swiftscan_diagnostic_get_severity swiftscan_diagnostics_set_dispose -swiftscan_cas_create +swiftscan_cas_create_from_options swiftscan_cas_dispose +swiftscan_cas_options_create +swiftscan_cas_options_dispose +swiftscan_cas_options_set_ondisk_path +swiftscan_cas_options_set_plugin_path +swiftscan_cas_options_set_option swiftscan_cas_store swiftscan_compute_cache_key invoke_swift_compiler diff --git a/tools/swift-plugin-server/CMakeLists.txt b/tools/swift-plugin-server/CMakeLists.txt index 09332309b10c9..1d1b88b22bd8a 100644 --- a/tools/swift-plugin-server/CMakeLists.txt +++ b/tools/swift-plugin-server/CMakeLists.txt @@ -16,6 +16,8 @@ if (SWIFT_SWIFT_PARSER) DEPENDENCIES swiftDemangling $ + SWIFT_COMPONENT + compiler SWIFT_DEPENDENCIES SwiftSyntax::SwiftSyntaxMacros SwiftSyntax::SwiftSyntaxMacroExpansion @@ -25,9 +27,4 @@ if (SWIFT_SWIFT_PARSER) target_include_directories(swift-plugin-server PRIVATE Sources/CSwiftPluginServer/include ) - swift_install_in_component(TARGETS swift-plugin-server - RUNTIME - DESTINATION bin - COMPONENT compiler - ) endif() diff --git a/tools/swift-plugin-server/Sources/CSwiftPluginServer/PluginServer.cpp b/tools/swift-plugin-server/Sources/CSwiftPluginServer/PluginServer.cpp index b84bdeaa173f7..a689f18d8ebc8 100644 --- a/tools/swift-plugin-server/Sources/CSwiftPluginServer/PluginServer.cpp +++ b/tools/swift-plugin-server/Sources/CSwiftPluginServer/PluginServer.cpp @@ -118,7 +118,7 @@ void PluginServer_destroyConnection(const void *server) { delete static_cast(server); } -size_t PluginServer_read(const void *server, void *data, size_t nbyte) { +SwiftInt PluginServer_read(const void *server, void *data, SwiftUInt nbyte) { const auto *connection = static_cast(server); #if defined(_WIN32) return _read(connection->inputFD, data, nbyte); @@ -127,7 +127,7 @@ size_t PluginServer_read(const void *server, void *data, size_t nbyte) { #endif } -size_t PluginServer_write(const void *server, const void *data, size_t nbyte) { +SwiftInt PluginServer_write(const void *server, const void *data, SwiftUInt nbyte) { const auto *connection = static_cast(server); #if defined(_WIN32) return _write(connection->outputFD, data, nbyte); diff --git a/tools/swift-plugin-server/Sources/CSwiftPluginServer/include/PluginServer.h b/tools/swift-plugin-server/Sources/CSwiftPluginServer/include/PluginServer.h index 92e62c3aa7bc4..d30c48b86dbc9 100644 --- a/tools/swift-plugin-server/Sources/CSwiftPluginServer/include/PluginServer.h +++ b/tools/swift-plugin-server/Sources/CSwiftPluginServer/include/PluginServer.h @@ -13,8 +13,68 @@ #ifndef SWIFT_PLUGINSERVER_PLUGINSERVER_H #define SWIFT_PLUGINSERVER_PLUGINSERVER_H -#include +// NOTE: Partially ported from SwiftShim's SwiftStdint.h. We cannot include +// that header here because it belongs to the runtime, but we need the same +// logic for interoperability with Swift code in the compiler itself. +// stdint.h is provided by Clang, but it dispatches to libc's stdint.h. As a +// result, using stdint.h here would pull in Darwin module (which includes +// libc). This creates a dependency cycle, so we can't use stdint.h in +// SwiftShims. +// On Linux, the story is different. We get the error message +// "/usr/include/x86_64-linux-gnu/sys/types.h:146:10: error: 'stddef.h' file not +// found" +// This is a known Clang/Ubuntu bug. + +// Clang has been defining __INTxx_TYPE__ macros for a long time. +// __UINTxx_TYPE__ are defined only since Clang 3.5. +#if defined(_MSC_VER) && !defined(__clang__) +typedef __int64 __swiftc_int64_t; +typedef unsigned __int64 __swiftc_uint64_t; +typedef int __swiftc_int32_t; +typedef unsigned int __swiftc_uint32_t; +#elif !defined(__APPLE__) && !defined(__linux__) && !defined(__OpenBSD__) && !defined(__wasi__) #include +typedef int64_t __swiftc_int64_t; +typedef uint64_t __swiftc_uint64_t; +typedef int32_t __swiftc_int32_t; +typedef uint32_t __swiftc_uint32_t; +typedef intptr_t __swiftc_intptr_t; +typedef uintptr_t __swiftc_uintptr_t; +#else +typedef __INT64_TYPE__ __swiftc_int64_t; +#ifdef __UINT64_TYPE__ +typedef __UINT64_TYPE__ __swiftc_uint64_t; +#else +typedef unsigned __INT64_TYPE__ __swiftc_uint64_t; +#endif + +typedef __INT32_TYPE__ __swiftc_int32_t; +#ifdef __UINT32_TYPE__ +typedef __UINT32_TYPE__ __swiftc_uint32_t; +#else +typedef unsigned __INT32_TYPE__ __swiftc_uint32_t; +#endif +#endif + +#define __swiftc_join3(a,b,c) a ## b ## c + +#define __swiftc_intn_t(n) __swiftc_join3(__swiftc_int, n, _t) +#define __swiftc_uintn_t(n) __swiftc_join3(__swiftc_uint, n, _t) + +#if defined(_MSC_VER) && !defined(__clang__) +#if defined(_WIN64) +typedef __swiftc_int64_t SwiftInt; +typedef __swiftc_uint64_t SwiftUInt; +#elif defined(_WIN32) +typedef __swiftc_int32_t SwiftInt; +typedef __swiftc_uint32_t SwiftUInt; +#else +#error unknown windows pointer width +#endif +#else +typedef __swiftc_intn_t(__INTPTR_WIDTH__) SwiftInt; +typedef __swiftc_uintn_t(__INTPTR_WIDTH__) SwiftUInt; +#endif #ifdef __cplusplus extern "C" { @@ -32,10 +92,10 @@ const void *PluginServer_createConnection(const char **errorMessage); void PluginServer_destroyConnection(const void *connHandle); /// Read bytes from the IPC communication handle. -size_t PluginServer_read(const void *connHandle, void *data, size_t nbyte); +SwiftInt PluginServer_read(const void *connHandle, void *data, SwiftUInt nbyte); /// Write bytes to the IPC communication handle. -size_t PluginServer_write(const void *connHandle, const void *data, size_t nbyte); +SwiftInt PluginServer_write(const void *connHandle, const void *data, SwiftUInt nbyte); //===----------------------------------------------------------------------===// // Dynamic link diff --git a/tools/swift-plugin-server/Sources/swift-plugin-server/swift-plugin-server.swift b/tools/swift-plugin-server/Sources/swift-plugin-server/swift-plugin-server.swift index 8c06e6dcd5d5a..ad117e4d8e50e 100644 --- a/tools/swift-plugin-server/Sources/swift-plugin-server/swift-plugin-server.swift +++ b/tools/swift-plugin-server/Sources/swift-plugin-server/swift-plugin-server.swift @@ -172,13 +172,13 @@ final class PluginHostConnection: MessageConnection { var ptr = buffer.baseAddress! while (bytesToWrite > 0) { - let writtenSize = PluginServer_write(handle, ptr, Int(bytesToWrite)) + let writtenSize = PluginServer_write(handle, ptr, SwiftUInt(bytesToWrite)) if (writtenSize <= 0) { // error e.g. broken pipe. break } - ptr = ptr.advanced(by: writtenSize) - bytesToWrite -= writtenSize + ptr = ptr.advanced(by: Int(writtenSize)) + bytesToWrite -= Int(writtenSize) } return buffer.count - bytesToWrite } @@ -193,13 +193,13 @@ final class PluginHostConnection: MessageConnection { var ptr = buffer.baseAddress! while bytesToRead > 0 { - let readSize = PluginServer_read(handle, ptr, Int(bytesToRead)) + let readSize = PluginServer_read(handle, ptr, SwiftUInt(bytesToRead)) if (readSize <= 0) { // 0: EOF (the host closed), -1: Broken pipe (the host crashed?) break; } - ptr = ptr.advanced(by: readSize) - bytesToRead -= readSize + ptr = ptr.advanced(by: Int(readSize)) + bytesToRead -= Int(readSize) } return buffer.count - bytesToRead } diff --git a/unittests/Sema/BindingInferenceTests.cpp b/unittests/Sema/BindingInferenceTests.cpp index 6eb17238b7b63..9ff2046aa8e26 100644 --- a/unittests/Sema/BindingInferenceTests.cpp +++ b/unittests/Sema/BindingInferenceTests.cpp @@ -395,3 +395,43 @@ TEST_F(SemaTest, TestNoDoubleVoidClosureResultInference) { verifyInference(closureResultWithoutVoid, 3); } + +TEST_F(SemaTest, TestSupertypeInferenceWithDefaults) { + ConstraintSystemOptions options; + ConstraintSystem cs(DC, options); + + auto *genericArg = cs.createTypeVariable( + cs.getConstraintLocator({}, ConstraintLocator::GenericArgument), + /*options=*/0); + + // KeyPath i.e. \.utf8.count or something similar + auto keyPath = + BoundGenericType::get(Context.getKeyPathDecl(), /*parent=*/Type(), + {getStdlibType("String"), getStdlibType("Int")}); + + cs.addConstraint(ConstraintKind::Conversion, keyPath, genericArg, + cs.getConstraintLocator({})); + + cs.addConstraint(ConstraintKind::Defaultable, genericArg, Context.TheAnyType, + cs.getConstraintLocator({})); + + auto bindings = cs.getBindingsFor(genericArg); + TypeVarBindingProducer producer(bindings); + + llvm::SmallVector inferredTypes; + while (auto binding = producer()) { + ASSERT_TRUE(binding.has_value()); + inferredTypes.push_back(binding->getType()); + } + + // The inference should produce 4 types: KeyPath, + // PartialKeyPath, AnyKeyPath and Any - in that order. + + ASSERT_EQ(inferredTypes.size(), 4); + ASSERT_TRUE(inferredTypes[0]->isEqual(keyPath)); + ASSERT_TRUE(inferredTypes[1]->isEqual( + BoundGenericType::get(Context.getPartialKeyPathDecl(), + /*parent=*/Type(), {getStdlibType("String")}))); + ASSERT_TRUE(inferredTypes[2]->isEqual(getStdlibType("AnyKeyPath"))); + ASSERT_TRUE(inferredTypes[3]->isEqual(Context.TheAnyType)); +} diff --git a/utils/swift_build_support/swift_build_support/build_script_invocation.py b/utils/swift_build_support/swift_build_support/build_script_invocation.py index 1e54515905ccf..68ca195fc2ce1 100644 --- a/utils/swift_build_support/swift_build_support/build_script_invocation.py +++ b/utils/swift_build_support/swift_build_support/build_script_invocation.py @@ -603,7 +603,7 @@ def compute_product_pipelines(self): # the build-script code base. The main difference is that these are all # build, tested, and installed all at once instead of performing build, # test, install like a normal build-script product. - builder.begin_impl_pipeline(should_run_epilogue_operations=False) + builder.begin_impl_pipeline(should_run_epilogue_operations=True) builder.add_impl_product(products.LibCXX, is_enabled=self.args.build_libcxx) @@ -613,11 +613,6 @@ def compute_product_pipelines(self): is_enabled=self.args.build_swift) builder.add_impl_product(products.LLDB, is_enabled=self.args.build_lldb) - - # Begin a new build-script-impl pipeline that builds libraries that we - # build as part of build-script-impl but that we should eventually move - # onto build-script products. - builder.begin_impl_pipeline(should_run_epilogue_operations=True) builder.add_impl_product(products.LibDispatch, is_enabled=self.args.build_libdispatch) builder.add_impl_product(products.Foundation, diff --git a/utils/swift_build_support/swift_build_support/products/swiftsyntax.py b/utils/swift_build_support/swift_build_support/products/swiftsyntax.py index 03ec3c83b1af8..5bdf358f5425c 100644 --- a/utils/swift_build_support/swift_build_support/products/swiftsyntax.py +++ b/utils/swift_build_support/swift_build_support/products/swiftsyntax.py @@ -116,13 +116,7 @@ def test(self, host_target): llvm_build_dir = os.path.realpath(llvm_build_dir) self.run_swiftsyntax_build_script(target=host_target, - command='test', - additional_params=[ - '--filecheck-exec', - os.path.join(llvm_build_dir, - 'bin', - 'FileCheck') - ]) + command='test') def should_install(self, host_target): return self.args.install_swiftsyntax diff --git a/utils/update_checkout/update_checkout/update_checkout.py b/utils/update_checkout/update_checkout/update_checkout.py index bf591cffb6775..00143f702895c 100755 --- a/utils/update_checkout/update_checkout/update_checkout.py +++ b/utils/update_checkout/update_checkout/update_checkout.py @@ -567,11 +567,11 @@ def main(): """) parser.add_argument( "--clone", - help="Obtain Sources for Swift and Related Projects", + help="obtain sources for Swift and related projects", action="store_true") parser.add_argument( "--clone-with-ssh", - help="Obtain Sources for Swift and Related Projects via SSH", + help="Obtain sources for Swift and related projects via SSH", action="store_true") parser.add_argument( "--skip-history", diff --git a/validation-test/IDE/crashers_2_fixed/0033-trailing-closure-arg-label-matching.swift b/validation-test/IDE/crashers_2_fixed/0033-trailing-closure-arg-label-matching.swift index c355b2aa1377a..dd0640d17e238 100644 --- a/validation-test/IDE/crashers_2_fixed/0033-trailing-closure-arg-label-matching.swift +++ b/validation-test/IDE/crashers_2_fixed/0033-trailing-closure-arg-label-matching.swift @@ -6,5 +6,6 @@ func foo() { func sink(receiveCompletion: (Int) -> Void, receiveValue: (Int) -> Void) { fatalError() } -// CHECK: Begin completions, 1 items +// CHECK: Begin completions, 2 items // CHECK-DAG: Pattern/Local/Flair[ArgLabels]: {#receiveValue: (Int) -> Void {<#Int#> in|}#}[#(Int) -> Void#]; +// CHECK-DAG: Keyword[self]/CurrNominal: .self[#Void#]; name=self diff --git a/validation-test/SILOptimizer/gh68328.swift b/validation-test/SILOptimizer/gh68328.swift new file mode 100644 index 0000000000000..62cc24896c1fa --- /dev/null +++ b/validation-test/SILOptimizer/gh68328.swift @@ -0,0 +1,16 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -o %t/bin +// RUN: %target-run %t/bin 2> %t/out.txt || true +// RUN: %FileCheck %s < %t/out.txt + +struct Example: ~Copyable { + private var failureString: String { "Goodbye." } + deinit { fatalError("FATAL ERROR: \(failureString)") } +} + +func doit() { + let e = Example() + // CHECK: FATAL ERROR: Goodbye. +} + +doit()