diff --git a/CMakeLists.txt b/CMakeLists.txt index 31d450f959d8d..38f3b831b2f59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -369,6 +369,10 @@ option(SWIFT_REPORT_STATISTICS "Create json files which contain internal compilation statistics" FALSE) +option(SWIFT_DISABLE_OBJC_INTEROP + "Disable Objective-C interoperability even on platforms what would normally have it" + FALSE) + # FIXME(wasm) Reflection tests are temporalily disabled due to lack of linker features option(SWIFTWASM_DISABLE_REFLECTION_TEST "Disable building swift-reflection-test for WebAssembly build" @@ -391,10 +395,6 @@ option(SWIFT_RUNTIME_ENABLE_LEAK_CHECKER "Should the runtime be built with support for non-thread-safe leak detecting entrypoints" FALSE) -option(SWIFT_STDLIB_USE_NONATOMIC_RC - "Build the standard libraries and overlays with nonatomic reference count operations enabled" - FALSE) - option(SWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS "Enable runtime function counters and expose the API." FALSE) @@ -634,6 +634,22 @@ if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC" OR "${CMAKE_CXX_SIMULATE_ID}" STREQU set(SWIFT_COMPILER_IS_MSVC_LIKE TRUE) endif() +if(NOT SWIFT_COMPILER_IS_MSVC_LIKE) + # CMake's default for CMAKE_CXX_FLAGS_RELEASE is "-O3 -DNDEBUG". Let's avoid "-O3" for consistency + # between Release and RelWithDebInfo. Dropping -DNDEBUG from this setting is blocked by triggering + # a test failure of Swift-Unit :: Syntax/./SwiftSyntaxTests/TypeSyntaxTests.MetatypeTypeWithAPIs + # because unit tests don't currently explicitly set -DNDEBUG/-UNDEBUG. + set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG") + + _compute_lto_flag("${SWIFT_TOOLS_ENABLE_LTO}" _lto_flag_out) + if(_lto_flag_out) + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_RELEASE} -gline-tables-only") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -gline-tables-only") + endif() +else() + +endif() + # # Configure SDKs. # @@ -933,7 +949,6 @@ if(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") endif() endif() -find_package(Python2 COMPONENTS Interpreter REQUIRED) find_package(Python3 COMPONENTS Interpreter REQUIRED) # diff --git a/README.md b/README.md index e99f28b549c8d..ab4a2a6033f29 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,14 @@ The required version of Xcode changes frequently, and is often a beta release. Check this document or the host information on for the current required version. +Swift's build tooling is meant to support spaces in the paths passed to them, +but using spaces sometimes tickles bugs in Swift's build scripts or the tools +they rely on. For example, [SR-13441](https://bugs.swift.org/browse/SR-13441) +is caused by a space in the Xcode path used on macOS. If you see Swift's build +tooling misbehave due to a space in a path, please +[report the bug on the Swift bug tracker](https://swift.org/contributing/#reporting-bugs) +and then change the path to work around it. + You will also need [CMake](https://cmake.org) and [Ninja](https://ninja-build.org), which can be installed via a package manager: diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index ef28ed87b2483..1f0f58171f4d7 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -136,6 +136,7 @@ set(SWIFT_BENCH_MODULES single-source/PrefixWhile single-source/Prims single-source/PrimsNonStrongRef + single-source/ProtocolConformance single-source/ProtocolDispatch single-source/ProtocolDispatch2 single-source/Queue diff --git a/benchmark/single-source/ProtocolConformance.swift b/benchmark/single-source/ProtocolConformance.swift new file mode 100644 index 0000000000000..b042065c02ab3 --- /dev/null +++ b/benchmark/single-source/ProtocolConformance.swift @@ -0,0 +1,76 @@ +//===--- ProtocolDispatch.swift -------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import TestsUtils + +public let ProtocolConformance = BenchmarkInfo ( + name: "ProtocolConformance", + runFunction: run_ProtocolConformance, + tags: [.validation, .runtime]) + +protocol P {} + +struct One: P {} +struct Two {} + +struct Cat {} + +extension Cat: P where T: P, U: P {} + +protocol Growable {} +extension Growable { + func grow() -> (Growable, Growable) { + return (Cat(), Cat()) + } +} + +extension One: Growable {} +extension Two: Growable {} +extension Cat: Growable {} + +@inline(never) +public func run_ProtocolConformance(_ N: Int) { + var array: [Growable] = [One(), Two()] + var i = 0 + var checks = 0 + + // The expected number of times we expect `elt is P` to be true. + var expectedConforms = 0 + + // The expected number of times we expect `elt is P` to be true + // per iteration, at the current time. + var expectedConformsPerIter = 1 + + // The number of times we've actually seen `elt is P` be true. + var conforms = 0 + while checks < N * 500 { + let (a, b) = array[i].grow() + array.append(a) + array.append(b) + + // The number of times `elt is P` is true per outer iteration + // goes up by 1 when the array's count is a power of 2. + if array.count & (array.count - 1) == 0 { + expectedConformsPerIter += 1 + } + expectedConforms += expectedConformsPerIter + + for elt in array { + if elt is P { + conforms += 1 + } + checks += 1 + } + i += 1 + } + CheckResults(expectedConforms == conforms) +} diff --git a/benchmark/utils/main.swift b/benchmark/utils/main.swift index b4791ad6208e7..aa3504ba35d72 100644 --- a/benchmark/utils/main.swift +++ b/benchmark/utils/main.swift @@ -131,6 +131,7 @@ import PrefixWhile import Prims import PrimsNonStrongRef import PrimsSplit +import ProtocolConformance import ProtocolDispatch import ProtocolDispatch2 import Queue @@ -317,6 +318,7 @@ registerBenchmark(PrefixWhile) registerBenchmark(Prims) registerBenchmark(PrimsNonStrongRef) registerBenchmark(PrimsSplit) +registerBenchmark(ProtocolConformance) registerBenchmark(ProtocolDispatch) registerBenchmark(ProtocolDispatch2) registerBenchmark(QueueGeneric) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 1db26266cb757..e4304b6b484eb 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -93,7 +93,7 @@ function(_add_host_variant_c_compile_link_flags name) set(_sysroot "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_ARCH_${SWIFT_HOST_VARIANT_ARCH}_PATH}") - if(SWIFT_HOST_VARIANT_SDK IN_LIST SWIFT_APPLE_PLATFORMS) + if(SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_USE_ISYSROOT) target_compile_options(${name} PRIVATE -isysroot;${_sysroot}) elseif(NOT SWIFT_COMPILER_IS_MSVC_LIKE AND NOT "${_sysroot}" STREQUAL "/") target_compile_options(${name} PRIVATE --sysroot=${_sysroot}) @@ -130,13 +130,18 @@ function(_add_host_variant_c_compile_flags target) _add_host_variant_c_compile_link_flags(${target}) is_build_type_optimized("${CMAKE_BUILD_TYPE}" optimized) - if(optimized) - target_compile_options(${target} PRIVATE -O2) + is_build_type_with_debuginfo("${CMAKE_BUILD_TYPE}" debuginfo) + # Add -O0/-O2/-O3/-Os/-g/-momit-leaf-frame-pointer/... based on CMAKE_BUILD_TYPE. + target_compile_options(${target} PRIVATE "${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}") + + if(optimized) # Omit leaf frame pointers on x86 production builds (optimized, no debug # info, and no asserts). - is_build_type_with_debuginfo("${CMAKE_BUILD_TYPE}" debug) - if(NOT debug AND NOT LLVM_ENABLE_ASSERTIONS) + if(NOT debuginfo AND NOT LLVM_ENABLE_ASSERTIONS) + # Unfortunately, this cannot be folded into the standard + # CMAKE_CXX_FLAGS_... because Apple multi-SDK builds use different + # architectures for different SDKs. if(SWIFT_HOST_VARIANT_ARCH MATCHES "i?86") if(NOT SWIFT_COMPILER_IS_MSVC_LIKE) target_compile_options(${target} PRIVATE -momit-leaf-frame-pointer) @@ -145,27 +150,6 @@ function(_add_host_variant_c_compile_flags target) endif() endif() endif() - else() - if(NOT SWIFT_COMPILER_IS_MSVC_LIKE) - target_compile_options(${target} PRIVATE -O0) - else() - target_compile_options(${target} PRIVATE /Od) - endif() - endif() - - # CMake automatically adds the flags for debug info if we use MSVC/clang-cl. - if(NOT SWIFT_COMPILER_IS_MSVC_LIKE) - is_build_type_with_debuginfo("${CMAKE_BUILD_TYPE}" debuginfo) - if(debuginfo) - _compute_lto_flag("${SWIFT_TOOLS_ENABLE_LTO}" _lto_flag_out) - if(_lto_flag_out) - target_compile_options(${target} PRIVATE -gline-tables-only) - else() - target_compile_options(${target} PRIVATE -g) - endif() - else() - target_compile_options(${target} PRIVATE -g0) - endif() endif() if(SWIFT_HOST_VARIANT_SDK STREQUAL WINDOWS) diff --git a/cmake/modules/DarwinSDKs.cmake b/cmake/modules/DarwinSDKs.cmake index 20a5620fba6a7..dc570b7005834 100644 --- a/cmake/modules/DarwinSDKs.cmake +++ b/cmake/modules/DarwinSDKs.cmake @@ -26,6 +26,24 @@ if(swift_build_osx) configure_target_variant(OSX-R "OS X Release" OSX R "Release") endif() +is_sdk_requested(FREESTANDING swift_build_freestanding) +if(swift_build_freestanding) + set(SWIFT_FREESTANDING_SDK "" CACHE STRING + "Which SDK to use when building the FREESTANDING stdlib") + set(SWIFT_FREESTANDING_TRIPLE_NAME "" CACHE STRING + "Which triple name (e.g. 'none-macho') to use when building the FREESTANDING stdlib") + set(SWIFT_FREESTANDING_ARCHS "" CACHE STRING + "Which architectures to build when building the FREESTANDING stdlib") + configure_sdk_darwin( + FREESTANDING "FREESTANDING" "" + "${SWIFT_FREESTANDING_SDK}" freestanding "${SWIFT_FREESTANDING_TRIPLE_NAME}" freestanding "${SWIFT_FREESTANDING_ARCHS}") + set(SWIFT_SDK_FREESTANDING_LIB_SUBDIR "freestanding") + configure_target_variant(FREESTANDING-DA "FREESTANDING Debug+Asserts" FREESTANDING DA "Debug+Asserts") + configure_target_variant(FREESTANDING-RA "FREESTANDING Release+Asserts" FREESTANDING RA "Release+Asserts") + configure_target_variant(FREESTANDING-R "FREESTANDING Release" FREESTANDING R "Release") + configure_target_variant(FREESTANDING-S "FREESTANDING MinSizeRelease" FREESTANDING S "MinSizeRelease") +endif() + # Compatible cross-compile SDKS for Darwin OSes: IOS, IOS_SIMULATOR, TVOS, # TVOS_SIMULATOR, WATCHOS, WATCHOS_SIMULATOR (archs hardcoded below). diff --git a/cmake/modules/SwiftConfigureSDK.cmake b/cmake/modules/SwiftConfigureSDK.cmake index 52c08025e62a0..feb7f513c96ce 100644 --- a/cmake/modules/SwiftConfigureSDK.cmake +++ b/cmake/modules/SwiftConfigureSDK.cmake @@ -145,6 +145,8 @@ endfunction() # SWIFT_SDK_${prefix}_LIB_SUBDIR Library subdir for this SDK # SWIFT_SDK_${prefix}_VERSION_MIN_NAME Version min name for this SDK # SWIFT_SDK_${prefix}_TRIPLE_NAME Triple name for this SDK +# SWIFT_SDK_${prefix}_OBJECT_FORMAT The object file format (e.g. MACHO) +# SWIFT_SDK_${prefix}_USE_ISYSROOT Whether to use -isysroot # SWIFT_SDK_${prefix}_ARCHITECTURES Architectures (as a list) # SWIFT_SDK_${prefix}_IS_SIMULATOR Whether this is a simulator target. # SWIFT_SDK_${prefix}_ARCH_${ARCH}_TRIPLE Triple name @@ -187,6 +189,7 @@ macro(configure_sdk_darwin set(SWIFT_SDK_${prefix}_VERSION_MIN_NAME "${version_min_name}") set(SWIFT_SDK_${prefix}_TRIPLE_NAME "${triple_name}") set(SWIFT_SDK_${prefix}_OBJECT_FORMAT "MACHO") + set(SWIFT_SDK_${prefix}_USE_ISYSROOT TRUE) set(SWIFT_SDK_${prefix}_ARCHITECTURES ${architectures}) if(SWIFT_DARWIN_SUPPORTED_ARCHS) @@ -270,6 +273,7 @@ macro(configure_sdk_unix name architectures) else() set(SWIFT_SDK_${prefix}_OBJECT_FORMAT "ELF") endif() + set(SWIFT_SDK_${prefix}_USE_ISYSROOT FALSE) foreach(arch ${architectures}) if("${prefix}" STREQUAL "ANDROID") @@ -432,6 +436,7 @@ macro(configure_sdk_windows name environment architectures) set(SWIFT_SDK_${prefix}_LIB_SUBDIR "windows") set(SWIFT_SDK_${prefix}_ARCHITECTURES "${architectures}") set(SWIFT_SDK_${prefix}_OBJECT_FORMAT "COFF") + set(SWIFT_SDK_${prefix}_USE_ISYSROOT FALSE) foreach(arch ${architectures}) if(arch STREQUAL armv7) diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst index a65799b8c53cd..9e60d04a4f5e3 100644 --- a/docs/ABI/Mangling.rst +++ b/docs/ABI/Mangling.rst @@ -176,6 +176,11 @@ Globals global ::= global 'MJ' // noncanonical specialized generic type metadata instantiation cache associated with global global ::= global 'MN' // noncanonical specialized generic type metadata for global + #if SWIFT_RUNTIME_VERSION >= 5.4 + global ::= context (decl-name '_')+ 'WZ' // global variable one-time initialization function + global ::= context (decl-name '_')+ 'Wz' // global variable one-time initialization token + #endif + A direct symbol resolves directly to the address of an object. An indirect symbol resolves to the address of a pointer to the object. They are distinct manglings to make a certain class of bugs @@ -1107,3 +1112,40 @@ nominal type descriptor symbol for ``CxxStruct`` while compiling the ``main`` mo .. code:: sSo9CxxStructVMn // -> nominal type descriptor for __C.CxxStruct + +Importing C++ class template instantiations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A class template instantiation is imported as a struct named +``__CxxTemplateInst`` plus Itanium mangled type of the instantiation (see the +``type`` production in the Itanium specification). Note that Itanium mangling is +used on all platforms, regardless of the ABI of the C++ toolchain, to ensure +that the mangled name is a valid Swift type name (this is not the case for MSVC +mangled names). A prefix with a double underscore (to ensure we have a reserved +C++ identifier) is added to limit the possibility for conflicts with names of +user-defined structs. The struct is notionally defined in the ``__C`` module, +similarly to regular C and C++ structs and classes. Consider the following C++ +module: + +.. code-block:: c++ + + template + struct MagicWrapper { + T t; + }; + + struct MagicNumber {}; + + typedef MagicWrapper WrappedMagicNumber; + +``WrappedMagicNumber`` is imported as a typealias for struct +``__CxxTemplateInst12MagicWrapperI11MagicNumberE``. Interface of the imported +module looks as follows: + +.. code-block:: swift + + struct __CxxTemplateInst12MagicWrapperI11MagicNumberE { + var t: MagicNumber + } + struct MagicNumber {} + typealias WrappedMagicNumber = __CxxTemplateInst12MagicWrapperI11MagicNumberE diff --git a/docs/CppInteroperabilityManifesto.md b/docs/CppInteroperabilityManifesto.md index f3a8df51820d2..b23c914268c1b 100644 --- a/docs/CppInteroperabilityManifesto.md +++ b/docs/CppInteroperabilityManifesto.md @@ -67,6 +67,7 @@ Assumptions: + [Function templates: calls with generic type parameters](#function-templates-calls-with-generic-type-parameters) + [Function templates: importing as real generic functions](#function-templates-importing-as-real-generic-functions) + [Class templates](#class-templates) + + [Class templates: importing instantiation behind typedef](#class-templates-importing-instantiation-behind-typedef) + [Class templates: importing specific specilalizations](#class-templates-importing-specific-specilalizations) + [Class templates: using with generic type parameters](#class-templates-using-with-generic-type-parameters) + [Class templates: using in generic code through a synthesized protocol](#class-templates-using-in-generic-code-through-a-synthesized-protocol) @@ -2575,6 +2576,45 @@ We could ignore explicit specializations of function templates, because they don't affect the API. Explicit specializations of class templates can dramatically change the API of the type. +### Class templates: Importing full class template instantiations + +A class template instantiation could be imported as a struct named +`__CxxTemplateInst` plus Itanium mangled type of the instantiation (see the +`type` production in the Itanium specification). Note that Itanium mangling is +used on all platforms, regardless of the ABI of the C++ toolchain, to ensure +that the mangled name is a valid Swift type name (this is not the case for MSVC +mangled names). A prefix with a double underscore (to ensure we have a reserved +C++ identifier) is added to limit the possibility for conflicts with names of +user-defined structs. The struct is notionally defined in the `__C` module, +similarly to regular C and C++ structs and classes. Consider the following C++ +module: + +```c++ +// C++ header. + +template +struct MagicWrapper { + T t; +}; +struct MagicNumber {}; + +typedef MagicWrapper WrappedMagicNumber; +``` + +`WrappedMagicNumber` will be imported as a typealias for a struct +`__CxxTemplateInst12MagicWrapperI11MagicNumberE`. Interface of the imported +module will look as follows: + +```swift +// C++ header imported to Swift. + +struct __CxxTemplateInst12MagicWrapperI11MagicNumberE { + var t: MagicNumber +} +struct MagicNumber {} +typealias WrappedMagicNumber = __CxxTemplateInst12MagicWrapperI11MagicNumberE +``` + ### Class templates: importing specific specilalizations Just like with calls to C++ function templates, it is easy to compile a use of a @@ -2752,7 +2792,7 @@ func useConcrete() { ### Class templates: importing as real generic structs -If we know the complete set of allowed type arguments to a C++ function +If we know the complete set of allowed type arguments to a C++ struct template, we could import it as an actual Swift generic struct. Every method of that struct will perform dynamic dispatch based on type parameters. See the section about function templates for more details. diff --git a/docs/DynamicCasting.md b/docs/DynamicCasting.md new file mode 100644 index 0000000000000..72b369bbb3c7c --- /dev/null +++ b/docs/DynamicCasting.md @@ -0,0 +1,692 @@ +# Dynamic Casting Behavior + +* Author: [Tim Kientzle](https://github.com/tbkka) +* Implementation: [apple/swift#29658](https://github.com/apple/swift/pull/29658) + +## Introduction + +The Swift language has three casting operators: `is`, `as?`, and `as!`. +Each one takes an instance on the left-hand side and a type expression on the right-hand side. + +* The _cast test operator_ `is` tests whether a particular instance can be converted to a particular destination type. It returns a boolean result. + +* The _conditional cast operator_ `as?` attempts the conversion and returns an `Optional` result: `nil` if the conversion failed, and a non-nil optional containing the result otherwise. + +* The _forced cast operator_ `as!` unconditionally performs the casting conversion and returns the result. If an `as!` expression does not succeed, the implementation may terminate the program. + +Note: The static coercion operator `as` serves a different role and its behavior will not be specifically discussed in this document. + +The following invariants relate the three casting operators: +* Cast test: `x is T == ((x as? T) != nil)` +* Conditional cast: `(x as? T) == (x is T) ? .some(x as! T) : nil` +* Forced cast: `x as! T` is equivalent to `(x as? T)!` + +In particular, note that `is` and `as!` can be implemented in terms of `as?` and vice-versa. + +As with other operators with `!` in their names, `as!` is intended to only be invoked in cases where the programmer knows a priori that the cast will succeed. +If the conversion would not succeed, then the behavior may not be fully deterministic. +See the discussion of Array casting below for a specific case where this non-determinism can be important. + +The following sections detail the rules that govern the casting operations for particular Swift types. +Except where noted, casting between types described in different sections below will always fail -- for example, casting a struct instance to a function type or vice-versa. + +Where possible, each section includes machine-verifiable _invariants_ that can be used as the basis for developing a robust test suite for this functionality. + +## Identity Cast + +Casting an instance of a type to its own type will always succeed and return the original value unchanged. + +``` +let a: Int = 7 +a is Int // true +a as? Int // Succeeds +a as! Int == a // true +``` + +## Classes + +Casting among class types follows standard object-oriented programming conventions: + +* Class upcasts: If `C` is a subclass of `SuperC` and `c` is an instance of `C`, then `c is SuperC == true` and `(c as? SuperC) != nil`. (Note: These "upcasts" do not change the in-memory representation.) However, when `c` is accessed via a variable or expression of type `SuperC`, only methods and instance variables defined on `SuperC` are available. + +* Class downcasts: If `C` is a subclass of `SuperC` and `sc` is an instance of `SuperC`, then `sc is C` will be true iff `sc` is actually an instance of `C`. (Note: Again, a downcast does not affect the in-memory representation.) + +* Objective-C class casting: The rules above also apply when one of the classes in question is defined with the `@objc` attribute or inherits from an Objective-C class. + +* Class casts to AnyObject: Any class reference can be cast to `AnyObject` and then cast back to the original type. See "AnyObject" below. + +* If a struct or enum type conforms to `_ObjectiveCBridgeable`, then classes of the associated bridging type can be cast to the struct or enum type and vice versa. See "The `_ObjectiveCBridgeable` Protocol" below. + +Invariants: +* For any two class types `C1` and `C2`: `c is C1 && c is C2` iff `((c as? C1) as? C2) != nil` +* For any class type `C`: `c is C` iff `(c as! AnyObject) is C` +* For any class type `C`: if `c is C`, then `(c as! AnyObject) as! C === c` + +## Structs and Enums + +You cannot cast between different concrete struct or enum types. +More formally: + +* If `S` and `T` are struct or enum types and `s is S == true`, then `s is T` iff `S.self == T.self`. + +## Tuples + +Casting from a tuple type T1 to a tuple type T2 will succeed iff the following hold: +* T1 and T2 have the same number of elements +* If an element has a label in both T1 and T2, the labels are identical +* Each element of T1 can be individually cast to the corresponding type of T2 + +## Functions + +Casting from a function type F1 to a function type F2 will succeed iff the following hold: +* The two types have the same number of arguments +* Corresponding arguments have identical types +* The return types are identical +* If F1 is a throwing function type, then F2 must be a throwing function type. If F1 is not throwing, then F2 may be a throwing or non-throwing function type. + +Note that it is _not_ sufficient for argument and return types to be castable; they must actually be identical. + +## Optionals + +Casting to and from optional types will transparently unwrap optionals as much as necessary, including nested optional types. + +* If `T` and `U` are any two types, and `t` is an instance of `T`, then `.some(t) is Optional == t is U` +* Optional injection: if `T` and `U` are any two types, `t` is a non-nil instance of `T`, then `t is Optional == t is U` +* Optional projection: if `T` and `U` are any two types, and `t` is an instance of `T`, then `.some(t) is U == t is U` +* Nil Casting: if `T` and `U` are any two types, then `Optional.none is Optional == true` + +Note: For "Optional Injection" above, the requirement that `t` is a non-nil instance of `T` implies that either `T` is not an `Optional` or that `T` is `Optional` and `t` has the form `.some(u)` + +Examples +``` +// T and U are any two distinct types (possibly optional) +// NO is any non-optional type +let t: T +let u: U +let no: NO +// Casting freely adds/removes optional wrappers +t is Optional == true +t is Optional> == true +Optional.some(t) is T == true +Optional>.some(.some(t)) is T == true +// Non-optionals cast to optionals iff they cast to the inner type +no is Optional == no is U +Optional.some(no) is Optional == no is U +// Non-nil optionals cast to a different type iff the inner value does +Optional.some(t) is U == t is U +Optional>.some(.some(t)) is U == t is U +// Nil optionals always cast to other optional types +Optional.none is Optional == true +// Nil optionals never cast to non-optionals +Optional.none is NO == false +``` + +Depth Preservation: +The rules above imply that nested optionals are transparently unwrapped to arbitrary depth. +For example, if an instance of `T` can be cast to type `U`, then `T????` can be cast to `U????`. +This can be ambiguous if the former contains a `nil` value; +casting the nil to `U????` might end up with any of the following distinct values `.none`, `.some(.none)`, `.some(.some(.none))`, or `.some(.some(.some(.none)))`. + +To resolve this ambiguity, the implementation should first inspect the type of the inner `.none` value and count the optional depth. +Note that "optional depth" here refers to the number of optional wrappers needed to get from the innermost non-optional type to the type of the `.none`. + +1. If the target allows it, the value should inject into the target with the same optional depth as the source. +2. Otherwise, the value should inject with the greatest optional depth possible. + +Examples +``` +// Depth preservation +// The `.none` here has type `T?` with optional depth 1 +let t1: T???? = .some(.some(.some(.none))) +// This `.none` has type `T????` with optional depth 4 +let t4: T???? = .none +// Result has optional depth 1, matching source +t1 as! U???? // Produces .some(.some(.some(.none))) +t1 as! U??? // Produces .some(.some(.none)) +t1 as! U?? // Produces .some(.none) +t1 as! U? // Produces .none +// Result has optional depth 2, because 4 is not possible +t4 as! U?? // Produces .none +// Remember that `as?` adds a layer of optional +// These casts succeed, hence the outer `.some` +t1 as? U???? // Produces .some(.some(.some(.some(.none)))) +t1 as? U??? // Produces .some(.some(.some(.none))) +t1 as? U?? // Produces .some(.some(.none)) +t1 as? U? // Produces .some(.none) +t4 as? U?? // Produces .some(.none) +``` + +## Any + +Any Swift instance can be cast to the type `Any`. +An instance of `Any` has no useful methods or properties; to utilize the contents, you must cast it to another type. +Every type identifier is an instance of the metatype `Any.Type`. + +Invariants +* If `t` is any instance, then `t is Any == true` +* If `t` is any instance, `t as! Any` always succeeds +* For every type `T` (including protocol types), `T.self is Any.Type` +* If `t` is any instance and `U` is any `Equatable` type, then `t as? U == (t as! Any) as? U`. + +This last invariant deserves some explanation, as a similar pattern appears repeatedly throughout this document. +In essence, this invariant just says that putting something into an "Any box" (`t as! Any`) and taking it out again (`as? U`) does not change the result. +The requirement that `U` be `Equatable` is a technical necessity for using `==` in this statement. + +Note that in many cases, we've shortened such invariants to the form `t is U == (t as! Any) is U`. +Using `is` here simply avoids the technical necessity that `U` be `Equatable` but except where explicitly called out, the intention in every case is that such casting does not change the value. + +## AnyObject + +Any class, enum, struct, tuple, function, metatype, or existential metatype instance can be cast to `AnyObject`. + +XXX TODO The runtime logic has code to cast protocol types to `AnyObject` only if they are compatible with `__SwiftValue`. What is the practical effect of this logic? Does it mean that casting a protocol type to `AnyObject` will sometimes unwrap (if the protocol is incompatible) and sometimes not? What protocols are affected by this? + +The contents of an `AnyObject` container can be accessed by casting to another type: +* If `t` is any instance, `U` is any type, `t is AnyObject` and `t is U`, then `(t as! AnyObject) is U`. + +Implementation Note: `AnyObject` is represented in memory as a pointer to a refcounted object. The dynamic type of the object can be recovered from the "isa" field of the object. The optional form `AnyObject?` is the same except that it allows null. Reference types (class, metatype, or existential metatype instances) can be directly assigned to an `AnyObject` without any conversion. For non-reference types -- including struct, enum, and tuple types -- the casting logic will first look for an `_ObjectiveCBridgeable` conformance that it can use to convert the source into a tailored reference type. If that fails, the value will be copied into an opaque `_SwiftValue` container. + +(See "The _ObjectiveCBridgeable Protocol" below for more details.) + +### Objective-C Interactions + +Note the invariant above cannot be an equality because Objective-C bridging allows libraries to introduce new relationships that can alter the behavior of seemingly-unrelated casts. +One example of this is Foundation's `NSNumber` type which conditionally bridges to several Swift numeric types. +As a result, when Foundation is in scope, `Int(7) is Double == false` but `(Int(7) as! AnyObject) is Double == true`. +In general, the ability to add new bridging behaviors from a single type to several distinct types implies that Swift casting cannot be transitive. + +## Error (SE-0112) + +Although the Error protocol is specially handled by the Swift compiler and runtime (as detailed in [SE-0112](https://github.com/apple/swift-evolution/blob/master/proposals/0112-nserror-bridging.md)), it behaves like an ordinary protocol type for casting purposes. + +(See "Note: 'Self-conforming' protocols" below for additional details relevant to the Error protocol.) + +## AnyHashable (SE-0131) + +For casting purposes, `AnyHashable` behaves like a protocol type. + +## Existential/Protocol types + +Caveat: +Protocols that have `associatedtype` properties or which make use of the `Self` typealias cannot be used as independent types. +As such, the discussion below does not apply to them. + +Any Swift instance of a concrete type `T` can be cast to `P` iff `T` conforms to `P`. +The result is a "protocol witness" instance that provides access only to those methods and properties defined on `P`. +Other capabilities of the type `T` are not accessible from a `P` instance. + +The contents of a protocol witness can be accessed by casting to some other appropriate type: +* For any protocol `P`, instance `t`, and type `U`, if `t is P`, then `t as? U == (t as! P) as? U` + +XXX TODO: The invariant above does not apply to AnyObject, AnyHashable. +Does it suffice to explicitly exclude those two, or do other protocols share that behavior? The alternative would seem to be to change the equality here into an implication. + +In addition to the protocol witness type, every Swift protocol `P` implicitly defines two other types: +`P.Protocol` is the "protocol metatype", the type of `P.self`. +`P.Type` is the "protocol existential metatype". +These are described in more detail below. + +Regarding Protocol casts and Optionals + +When casting an Optional to a protocol type, the optional is preserved if possible. +Given an instance `o` of type `Optional` and a protocol `P`, the cast request `o as? P` will produce different results depending on whether `Optional` directly conforms to `P`: + +* If `Optional` conforms to `P`, then the result will be a protocol witness wrapping the `o` instance. In this case, a subsequent cast to `Optional` will restore the original instance. In particular, this case will preserve `nil` instances. + +* If `Optional` does not directly conform, then `o` will be unwrapped and the cast will be attempted with the contained object. If `o == nil`, this will fail. In the case of a nested optional `T???` this will result in fully unwrapping the inner non-optional. + +* If all of the above fail, then the cast will fail. + +For example, `Optional` conforms to `CustomDebugStringConvertible` but not to `CustomStringConvertible`. +Casting an optional instance to the first of these protocols will result in an item whose `.debugDescription` will describe the optional instance. +Casting an optional instance to the second will provide an instance whose `.description` property describes the inner non-Optional instance. + +## Array/Set/Dictionary Casts + +For Array, Set, or Dictionary types, you can use the casting operators to translate to another instance of the same outer container (Array, Set, or Dictionary respectively) with a different component type. +Note that the following discussion applies only to these specific types. +It does not apply to any other types, nor is there any mechanism to add this behavior to other types. + +Example: Given an `arr` of type `Array`, you can cast `arr as? Array`. +The result will be a new array where each `Int` in the original array has been individually cast to an `Any`. + +However, if any component item cannot be cast, then the outer cast will also fail. +For example, consider the following: +``` +let a: Array = [Int(7), "string"] +a as? Array // Fails because "string" cannot be cast to `Int` +``` + +Specifically, the casting operator acts for `Array` as if it were implemented as follows. +In particular, note that an empty array can be successfully cast to any destination array type. +``` +func arrayCast(source: Array) -> Optional> { + var result = Array() + for t in source { + if let u = t as? U { + result.append(u) + } else { + return nil + } + } + return result +} +``` + +Invariants +* Arrays cast iff their contents do: If `t` is an instance of `T` and `U` is any type, then `t is U == [t] is [U]` +* Empty arrays always cast: If `T` and `U` are any types, `Array() is Array` + +Similar logic applies to `Set` and `Dictionary` casts. +Note that the resulting `Set` or `Dictionary` may have fewer items than the original if the component casting operation converts non-equal items in the source into equal items in the destination. + +Specifically, the casting operator acts on `Set` and `Dictionary` as if by the following code: +``` +func setCast(source: Set) -> Optional> { + var result = Set() + for t in source { + if let u = t as? U { + result.append(u) + } else { + return nil + } + } + return result +} + +func dictionaryCast(source: Dictionary) -> Optional> { + var result = Dictionary() + for (k,v) in source { + if let k2 = k as? K2, v2 = v as? V2 { + result[k2] = v2 + } else { + return nil + } + } + return result +} +``` + +### Collection Casting performance and `as!` + +For `as?` casts, the casting behavior above requires that every element be converted separately. +This can be a particular bottleneck when trying to share large containers between Swift and Objective-C code. + +However, for `as!` casts, it is the programmer's responsibility to guarantee that the operation will succeed before requesting the conversion. +The implementation is allowed (but not required) to exploit this by deferring the inner component casts until the relevant item is needed. +Such lazy conversion can provide a significant performance improvement in cases where the data is known (by the programmer) to be safe and where the inner component casts are non-trivial. +However, if the conversion cannot be completed, it is indeterminate whether the cast request will fail immediately or whether the program will fail at some later point. + +## Metatypes + +For every type `T`, there is a unique instance `T.self` that represents the type at runtime. +As with all instances, `T.self` has a type. +We call this type the "metatype of `T`". +Technically, static variables or methods of a type belong to the `T.self` instance and are defined by the metatype of `T`: + +Example: +``` +struct S { + let ivar = 2 + static let svar = 1 +} +S.ivar // Error: only available on an instance +S().ivar // 2 +type(of: S()) == S.self +S.self.svar // 1 +S.svar // Shorthand for S.self.svar +``` + +For most Swift types, the metatype of `T` is named `T.Type`. +However, in two cases the metatype has a different name: +* For a nominal protocol type `P`, the metatype is named `P.Protocol` +* For a type bound to a generic variable `G`, the metatype is named `G.Type` _even if `G` is bound to a protocol type_. Specifically, if `G` is bound to the nominal protocol type `P`, then `G.Type` is another name for the metatype `P.Protocol`, and hence `G.Type.self == P.Protocol.self`. + +Example: +``` +// Metatype of a struct type +struct S: P {} +S.self is S.Type // always true +S.Type.self is S.Type.Type // always true +let s = S() +type(of: s) == S.self // always true +type(of: S.self) == S.Type.self + +// Metatype of a protocol type +protocol P {} +P.self is P.Protocol // always true +// P.Protocol is a metatype, not a protocol, so: +P.Protocol.self is P.Protocol.Type // always true +let p = s as! P +type(of: p) == P.self // always true + +// Metatype for a type bound to a generic type variable +f(s) // Bind G to S +f(p) // Bind G to P +func f(_ g: G) { + G.self is G.Type // always true +} +``` + +Invariants +* For a nominal non-protocol type `T`, `T.self is T.Type` +* For a nominal protocol type `P`, `P.self is P.Protocol` +* `P.Protocol` is a singleton: `T.self is P.Protocol` iff `T` is exactly `P` +* A non-protocol type `T` conforms to a protocol `P` iff `T.self is P.Type` +* `T` is a subtype of a non-protocol type `U` iff `T.self is U.Type` +* Subtypes define metatype subtypes: if `T` and `U` are non-protocol types, `T.self is U.Type == T.Type.self is U.Type.Type` +* Subtypes define metatype subtypes: if `T` is a non-protocol type and `P` is a protocol type, `T.self is P.Protocol == T.Type.self is P.Protocol.Type` + +## Existential Metatypes + +Protocols can specify constraints and provide default implementations for instances of types. +They can also specify constraints and provide default implementations for static members of types. +As described above, casting a regular instance of a type to a protocol type produces a protocol witness instance that exposes only those features required or provided by the protocol. +Similarly, a type identifier instance (`T.self`) can be cast to a protocol's "existential metatype" to expose just the parts of the type corresponding to the protocol's static requirements. + +The existential metatype of a protocol `P` is called `P.Type`. +(Recall that for a non-protocol type `T`, the expression `T.Type` refers to the regular metatype. +Non-protocol types do not have existential metatypes. +For a generic variable `G`, the expression also refers to the regular metatype, even if the generic variable is bound to a protocol. +There is no mechanism in Swift to refer to the existential metatype via a generic variable.) + +Example +``` +protocol P { + var ivar: Int { get } + static svar: Int { get } +} +struct S: P { + let ivar = 1 + static let svar = 2 +} +S().ivar // 1 +S.self.svar // 2 +(S() as! P).ivar // 1 +(S.self as! P.Type).svar // 2 +``` + +Invariants +* If `T` conforms to `P` and `t` is an instance of `T`, then `t is P` and `T.self is P.Type` +* If `P` is a sub-protocol of `P1` and `T` is any type, then `T.self is P.Type` implies that `T.self is P1.Type` +* Since every type `T` conforms to `Any`, `T.self is Any.Type` is always true +* Since every class type `C` conforms to `AnyObject`, `C.self is AnyObject.Type` is always true (this includes Objective-C class types) + +### Note: "Self conforming" protocols + +As mentioned above, a protocol definition for `P` implicitly defines types `P.Type` (the existential metatype) and `P.Protocol` (the metatype). +It also defines an associated type called `P` which is the type of a container that can hold any object whose concrete type conforms to the protocol `P`. + +A protocol is "self conforming" if the container type `P` conforms to the protocol `P`. +This is equivalent to saying that `P.self` is an instance of `P.Type`. +(Remember that `P.self` is always an instance of `P.Protocol`.) + +This is a concern for Swift because of the following construct, which attempts to invoke a generic `f` in a situation where the concrete instance clearly conforms to `P` but is represented as a `P` existential: +``` +func f(t: T) { .. use t .. } +let a : P = something +f(a) +``` +This construct is valid only if `T` conforms to `P` when `T = P`; that is, if `P` self-conforms. + +A similar situation arises with generic types: +``` +struct MyGenericType { + init(_ value: T) { ... } +} +let a : P +let b : MyGenericType(a) +``` +As above, since `a` has type `P`, this code is instantiating `MyGenericType` with `T = P`, which is only valid if `P` conforms to `P`. + +Note that any protocol that specifies static methods, static properties, associated types, or initializers cannot possibly be self-conforming. +As of Swift 5.3, the only self-conforming protocols are `Any`, `Error`, and Objective-C protocols that have no static requirements. + +Invariants +* `Any` self-conforms: `Any.self is Any.Type == true` +* `Error` self-conforms: `Error.self is Error.Type == true` +* If `P` self-conforms and is a sub-protocol of `P1`, then `P.self is P1.Type == true` + +For example, the last invariant here implies that for any Objective-C protocol `OP` that has no static requirements, `OP.self is AnyObject.Type`. This follows from the fact that `OP` self-conforms and that every Objective-C protocol has `AnyObject` as an implicit parent protocol. + +## CoreFoundation types + +* If `CF` is a CoreFoundation type, `cf` is an instance of `CF`, and `NS` is the corresponding Objective-C type, then `cf is NS == true` +* Further, since every Objective-C type inherits from `NSObject`, `cf is NSObject == true` +* In the above situation, if `T` is some other type and `cf is NS == true`, then `cf as! NS is T` iff `cf is T`. + +The intention of the above is to treat instances of CoreFoundation types as being simultaneously instances of the corresponding Objective-C type, in keeping with the general dual nature of these types. +In particular, if a protocol conformance is declared on the Objective-C type, then instances of the CoreFoundation type can be cast to the protocol type directly. + +XXX TODO: Converse? If ObjC instance has CF equivalent and CF type is extended, ... ?? + +## Objective-C types + +The following discussion applies in three different cases: +* _Explicit_ conversions from use of the `is`, `as?`, and `as!` operators. +* _Implicit_ conversions from Swift to Objective-C: These conversions are generated automatically when Swift code calls an Objective-C function or method with an argument that is not already of an Objective-C type, or when a Swift function returns a value to an Objective-C caller. +* _Implicit_ conversions from Objective-C to Swift: These are generated automatically when arguments are passed from an Objective-C caller to a Swift function, or when an Objective-C function returns a value to a Swift caller. +Unless stated otherwise, all of the following cases apply equally to all three of the above cases. + +Explicit casts among Swift and Objective-C class types follow the same general rules described earlier for class types in general. +Likewise, explicitly casting a class instance to an Objective-C protocol type follows the general rules for casts to protocol types. + +XXX TODO EXPLAIN Implicit conversions from Objective-C types to Swift types XXXX. + +CoreFoundation types can be explicitly cast to and from their corresponding Objective-C types as described above. + +Objective-C types and protocols +* `T` is an Objective-C class type iff `T.self is NSObject.Type` +* `P` is an Objective-C protocol iff XXX TODO XXX + +## The `_ObjectiveCBridgeable` Protocol + +The `_ObjectiveCBridgeable` protocol allows certain types to opt into custom casting behavior. +Note that although this mechanism was explicitly designed to simplify Swift interoperability with Objective-C, it is not necessarily tied to Objective-C. + +The `_ObjectiveCBridgeable` protocol defines an associated reference type `_ObjectiveCType`, along with a collection of methods that support casting to and from the associated `_ObjectiveCType`. +This protocol allows library code to provide tailored mechanisms for casting Swift types to reference types. +When casting to `AnyObject`, the casting logic prefers this tailored mechanism to the general `_SwiftValue` container mentioned above. + +Note: The associated `_ObjectiveCType` is constrained to be a subtype of `AnyObject`; it is not limited to being an actual Objective-C type. +In particular, this mechanism is equally available to the Swift implementation of Foundation on non-Apple platforms and the Objective-C Foundation on Apple platforms. + +Example #1: Foundation extends the `Array` type in the standard library with an `_ObjectiveCBridgeable` conformance to `NSArray`. This allows Swift arrays to be cast to and from Foundation `NSArray` instances. +``` +let a = [1, 2, 3] // Array +let b = a as? AnyObject // casts to NSArray +``` + +Example #2: Foundation also extends each Swift numeric type with an `_ObjectiveCBridgeable` conformance to `NSNumber`. +``` +let a = 1 // Int +// After the next line, b is an Optional +// holding a reference to an NSNumber +let b = a as? AnyObject +// NSNumber is bridgeable to Double +let c = b as? Double +``` + +## Implementation Notes + +Casting operators that appear in source code are translated into SIL in a variety of ways depending on the details of the types involved. +One common path renders `as!` into some variant of the `unconditional_checked_cast` instruction and renders `as?` and `is` into a conditional branch instruction such as `checked_cast_br`. + +SIL optimization passes attempt to simplify these. +In some cases, the result of the cast can be fully determined at compile time. +In a few cases, the compiler can generate tailored code to perform the cast (for example, assigning a reference to an `AnyObject` variable). +In other cases, the compiler can determine whether the cast will succeed without necessarily being able to compute the result. +For example, casting a class reference to a superclass will always succeed, which may allow a `checked_cast_br` instruction to be simplified into a non-branching `unconditional_checked_cast`. +Similarly, an `as?` cast that can be statically proven to always fail can be simplified into a constant `nil` value. +Note that these SIL functions are also used for other purposes, including implicit bridging conversions when calling into Objective-C. +This makes them common enough to be subject to some limited optimizations even in `-Onone` mode. + +When SIL is translated into LLVM IR, the remaining cast operations are rendered into calls to appropriate runtime functions. +The most general such function is `swift_dynamicCast` which accepts a pointer to the input value, a location in which to store the result, and metadata describing the types involved. +When possible, the compiler prefers to instead emit calls to specialized variants of this function with names like `swift_dynamicCastClass` and `swift_dynamicCastMetatypeToObject` (a full list is in the [Runtime Documentation](/docs/Runtime.md)). +These specialized versions require fewer arguments and perform fewer internal checks, which makes them cheaper to use. + +The `swift_dynamicCast` function examines the input and output types to determine appropriate conversions. +This process recurses on the input type to examine the contents of an existential container or `Optional`. +If the output is an existential container or `Optional` type, it will also recurse on the output type to determine a suitable base conversion and then must configure the container appropriately for the contents. +It may also perform additional metadata lookups to determine whether either type conforms to `Hashable`, `Error`, or `ObjectiveCBridgeable` protocols. +For collections, this process may end up recursively attempting to convert each element. + +## Compared to Swift 5.3 + +These are some of the ways in which Swift 5.3 differs from the behavior described above: + +* Casts for which the target type is "more Optional" than the static source type previously produced errors. This disallowed all of the following: injecting an `Int` into an `Int?`, extracting an `Int?` from an opaque `Any` container, and casting an `Array` to an `Array`. This document allows all of these. + +``` +let a = 7 +// Swift 5.3: error: cannot downcast to a more optional type +// Specification: returns true +a is Int? +// Swift 5.3: error: cannot downcast to a more optional type +// Specification: returns false +a is Optional + +let b: Int? = 7 +let c: Any = b +// Swift 5.3: error: cannot downcast to a more optional type +// Specification: returns true +c is Int? +``` + +* An instance of a CoreFoundation type could sometimes be cast to a protocol defined on the companion Obj-C type and sometimes not. To make the behavior consistent, we had to choose one; having such casts always succeed seems more consistent with the general dual nature of Obj-C/CF types. + +``` +import Foundation +protocol P {} +extension NSString: P {} +let a = CFStringCreateWithCString(nil, "hello, world", + CFStringBuiltInEncodings.UTF8.rawValue) +// Swift 5.3: prints "true" +print(a is P) +let b: Any = a +// Swift 5.3: prints "false" +// Specification: prints "true" +print(b is P) +``` + +* The Swift 5.3 compiler asserts attempting to cast a struct to AnyObject + +``` +struct S {} +let s = S() +// Swift 5.3: Compiler crash (in asserts build) +// Specification: Succeeds via _SwiftValue boxing +s as? AnyObject +``` + +* `NSNumber()` does not cast to itself via `as?` in unoptimized builds + +``` +import Foundation +let a = NSNumber() +// true in 5.3 for optimized builds; false for unoptimized builds +print((a as? NSNumber) != nil) +``` + +* `Optional` does not project + +``` +import Foundation +let a: Optional = NSNumber() +// Swift 5.3: false +// Specification: true +print(a is NSNumber) +// Swift 5.3: nil +// Specification: .some(NSNumber()) +print(a as? NSNumber) +``` + +* Casting `NSNumber()` to `Any` crashes at runtime + +``` +import Foundation +let a = NSNumber() +// Swift 5.3: Runtime crash (both optimized and unoptimized builds) +// Specification: Succeeds +print(a is Any) +``` + +* SR-2289: CF types cannot be cast to protocol existentials + +``` +import Foundation +protocol P {} +extension CFBitVector : P { + static func makeImmutable(from values: Array) -> CFBitVector { + return CFBitVectorCreate(nil, values, values.count * 8) + } +} +// Swift 5.3: Crashes in unoptimized build, prints true in optimized build +// Specification: prints true +print(CFBitVector.makeImmutable(from: [10,20]) is P) +``` + +* SR-4552: Cannot cast `Optional as Any` to protocol type. Note that this is a particular problem for reflection with weak fields, since `Mirror` reflects those as `Any` containing an `Optional` value. + +``` +protocol P {} +class C: P {} +let c: C? = C() +let a = c as? Any +// Swift 5.3: prints "false" +// Specification: prints "true" +print(a is P) +``` + +* SR-8964: `Any` containing `Optional` cannot cast to `Error` + +``` +struct MyError: Error { } +let a: Any? = MyError() +let b: Any = a +// Swift 5.3: Prints false +// Specification: prints true +print(b is Error) +``` + +* SR-6126: Inconsistent results for nested optionals + +``` +// Note: SR-6126 includes many cases similar to the following +let x: Int? = nil +print(x as Int??) // ==> "Optional(nil)" +// Swift 5.3: prints "nil" +// Specification: should print "Optional(nil)" (same as above) +print((x as? Int??)!) +``` + +* `Error.self` does not fully self-conform + +``` +// Swift 5.3: Prints "false" +// Specification: prints "true" +print(Error.self is Error.Type) +``` + +* Objective-C protocol metatypes do not fully self-conform + +``` +import Foundation +let a = NSObjectProtocol.self +print(a is NSObjectProtocol.Type) +``` + +* SR-1999: Cannot cast `Any` contents to a protocol type + +``` +protocol P {} +class Foo: P {} +let optionalFoo: Foo? = Foo() +let any: Any = optionalFoo +// Swift 5.3: Prints "false" +// Specification: prints "true" +print(any as? P) +``` + +* XXX TODO List others diff --git a/docs/README.md b/docs/README.md index b3e2c3f976d4d..d5b028f34b736 100644 --- a/docs/README.md +++ b/docs/README.md @@ -159,6 +159,8 @@ documentation, please create a thread on the Swift forums under the Documents the Swift Intermediate Language (SIL). - [TransparentAttr.md](/docs/TransparentAttr.md): Documents the semantics of the `@_transparent` attribute. +- [DynamicCasting.md](/docs/DynamicCasting.md): + Behavior of the dynamic casting operators `is`, `as?`, and `as!`. - [Runtime.md](/docs/Runtime.md): Describes the ABI interface to the Swift runtime. diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h index 2f6d07561224b..0ac4ab8943c42 100644 --- a/include/swift/ABI/Metadata.h +++ b/include/swift/ABI/Metadata.h @@ -3772,6 +3772,21 @@ struct TargetSingletonMetadataInitialization { const TargetTypeContextDescriptor *description) const; }; +template +struct TargetCanonicalSpecializedMetadatasListCount { + uint32_t count; +}; + +template +struct TargetCanonicalSpecializedMetadatasListEntry { + TargetRelativeDirectPointer, /*Nullable*/ false> metadata; +}; + +template +struct TargetCanonicalSpecializedMetadataAccessorsListEntry { + TargetRelativeDirectPointer accessor; +}; + template class TargetTypeContextDescriptor : public TargetContextDescriptor { @@ -3821,6 +3836,10 @@ class TargetTypeContextDescriptor return getTypeContextDescriptorFlags().hasForeignMetadataInitialization(); } + bool hasCanonicicalMetadataPrespecializations() const { + return getTypeContextDescriptorFlags().hasCanonicalMetadataPrespecializations(); + } + /// Given that this type has foreign metadata initialization, return the /// control structure for it. const TargetForeignMetadataInitialization & @@ -3853,6 +3872,9 @@ class TargetTypeContextDescriptor return words + offset; } + const llvm::ArrayRef, /*Nullable*/ false>> + getCanonicicalMetadataPrespecializations() const; + static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() >= ContextDescriptorKind::Type_First && cd->getKind() <= ContextDescriptorKind::Type_Last; @@ -3990,7 +4012,10 @@ class TargetClassDescriptor final TargetMethodDescriptor, TargetOverrideTableHeader, TargetMethodOverrideDescriptor, - TargetObjCResilientClassStubInfo> { + TargetObjCResilientClassStubInfo, + TargetCanonicalSpecializedMetadatasListCount, + TargetCanonicalSpecializedMetadatasListEntry, + TargetCanonicalSpecializedMetadataAccessorsListEntry> { private: using TrailingGenericContextObjects = swift::TrailingGenericContextObjects, @@ -4002,7 +4027,10 @@ class TargetClassDescriptor final TargetMethodDescriptor, TargetOverrideTableHeader, TargetMethodOverrideDescriptor, - TargetObjCResilientClassStubInfo>; + TargetObjCResilientClassStubInfo, + TargetCanonicalSpecializedMetadatasListCount, + TargetCanonicalSpecializedMetadatasListEntry, + TargetCanonicalSpecializedMetadataAccessorsListEntry>; using TrailingObjects = typename TrailingGenericContextObjects::TrailingObjects; @@ -4020,6 +4048,16 @@ class TargetClassDescriptor final TargetSingletonMetadataInitialization; using ObjCResilientClassStubInfo = TargetObjCResilientClassStubInfo; + using Metadata = + TargetRelativeDirectPointer, /*Nullable*/ false>; + using MetadataListCount = + TargetCanonicalSpecializedMetadatasListCount; + using MetadataListEntry = + TargetCanonicalSpecializedMetadatasListEntry; + using MetadataAccessor = + TargetRelativeDirectPointer; + using MetadataAccessorListEntry = + TargetCanonicalSpecializedMetadataAccessorsListEntry; using StoredPointer = typename Runtime::StoredPointer; using StoredPointerDifference = typename Runtime::StoredPointerDifference; @@ -4139,6 +4177,24 @@ class TargetClassDescriptor final return hasObjCResilientClassStub() ? 1 : 0; } + size_t numTrailingObjects(OverloadToken) const { + return this->hasCanonicicalMetadataPrespecializations() ? + 1 + : 0; + } + + size_t numTrailingObjects(OverloadToken) const { + return this->hasCanonicicalMetadataPrespecializations() ? + this->template getTrailingObjects()->count + : 0; + } + + size_t numTrailingObjects(OverloadToken) const { + return this->hasCanonicicalMetadataPrespecializations() ? + this->template getTrailingObjects()->count + : 0; + } + public: const TargetRelativeDirectPointer & getResilientSuperclass() const { @@ -4276,6 +4332,32 @@ class TargetClassDescriptor final ->Stub.get(); } + llvm::ArrayRef getCanonicicalMetadataPrespecializations() const { + if (!this->hasCanonicicalMetadataPrespecializations()) { + return {}; + } + + auto *listCount = this->template getTrailingObjects(); + auto *list = this->template getTrailingObjects(); + return llvm::ArrayRef( + reinterpret_cast(list), + listCount->count + ); + } + + llvm::ArrayRef getCanonicalMetadataPrespecializationAccessors() const { + if (!this->hasCanonicicalMetadataPrespecializations()) { + return {}; + } + + auto *listCount = this->template getTrailingObjects(); + auto *list = this->template getTrailingObjects(); + return llvm::ArrayRef( + reinterpret_cast(list), + listCount->count + ); + } + static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() == ContextDescriptorKind::Class; } @@ -4301,19 +4383,29 @@ class TargetStructDescriptor final TargetTypeGenericContextDescriptorHeader, /*additional trailing objects*/ TargetForeignMetadataInitialization, - TargetSingletonMetadataInitialization> { + TargetSingletonMetadataInitialization, + TargetCanonicalSpecializedMetadatasListCount, + TargetCanonicalSpecializedMetadatasListEntry> { public: using ForeignMetadataInitialization = TargetForeignMetadataInitialization; using SingletonMetadataInitialization = TargetSingletonMetadataInitialization; + using Metadata = + TargetRelativeDirectPointer, /*Nullable*/ false>; + using MetadataListCount = + TargetCanonicalSpecializedMetadatasListCount; + using MetadataListEntry = + TargetCanonicalSpecializedMetadatasListEntry; private: using TrailingGenericContextObjects = swift::TrailingGenericContextObjects, TargetTypeGenericContextDescriptorHeader, ForeignMetadataInitialization, - SingletonMetadataInitialization>; + SingletonMetadataInitialization, + MetadataListCount, + MetadataListEntry>; using TrailingObjects = typename TrailingGenericContextObjects::TrailingObjects; @@ -4331,6 +4423,18 @@ class TargetStructDescriptor final return this->hasSingletonMetadataInitialization() ? 1 : 0; } + size_t numTrailingObjects(OverloadToken) const { + return this->hasCanonicicalMetadataPrespecializations() ? + 1 + : 0; + } + + size_t numTrailingObjects(OverloadToken) const { + return this->hasCanonicicalMetadataPrespecializations() ? + this->template getTrailingObjects()->count + : 0; + } + public: using TrailingGenericContextObjects::getGenericContext; using TrailingGenericContextObjects::getGenericContextHeader; @@ -4363,6 +4467,19 @@ class TargetStructDescriptor final return TargetStructMetadata::getGenericArgumentOffset(); } + llvm::ArrayRef getCanonicicalMetadataPrespecializations() const { + if (!this->hasCanonicicalMetadataPrespecializations()) { + return {}; + } + + auto *listCount = this->template getTrailingObjects(); + auto *list = this->template getTrailingObjects(); + return llvm::ArrayRef( + reinterpret_cast(list), + listCount->count + ); + } + static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() == ContextDescriptorKind::Struct; } @@ -4377,19 +4494,29 @@ class TargetEnumDescriptor final TargetTypeGenericContextDescriptorHeader, /*additional trailing objects*/ TargetForeignMetadataInitialization, - TargetSingletonMetadataInitialization> { + TargetSingletonMetadataInitialization, + TargetCanonicalSpecializedMetadatasListCount, + TargetCanonicalSpecializedMetadatasListEntry> { public: using SingletonMetadataInitialization = TargetSingletonMetadataInitialization; using ForeignMetadataInitialization = TargetForeignMetadataInitialization; + using Metadata = + TargetRelativeDirectPointer, /*Nullable*/ false>; + using MetadataListCount = + TargetCanonicalSpecializedMetadatasListCount; + using MetadataListEntry = + TargetCanonicalSpecializedMetadatasListEntry; private: using TrailingGenericContextObjects = swift::TrailingGenericContextObjects, TargetTypeGenericContextDescriptorHeader, ForeignMetadataInitialization, - SingletonMetadataInitialization>; + SingletonMetadataInitialization, + MetadataListCount, + MetadataListEntry>; using TrailingObjects = typename TrailingGenericContextObjects::TrailingObjects; @@ -4407,6 +4534,18 @@ class TargetEnumDescriptor final return this->hasSingletonMetadataInitialization() ? 1 : 0; } + size_t numTrailingObjects(OverloadToken) const { + return this->hasCanonicicalMetadataPrespecializations() ? + 1 + : 0; + } + + size_t numTrailingObjects(OverloadToken) const { + return this->hasCanonicicalMetadataPrespecializations() ? + this->template getTrailingObjects()->count + : 0; + } + public: using TrailingGenericContextObjects::getGenericContext; using TrailingGenericContextObjects::getGenericContextHeader; @@ -4453,6 +4592,19 @@ class TargetEnumDescriptor final return *this->template getTrailingObjects(); } + llvm::ArrayRef getCanonicicalMetadataPrespecializations() const { + if (!this->hasCanonicicalMetadataPrespecializations()) { + return {}; + } + + auto *listCount = this->template getTrailingObjects(); + auto *list = this->template getTrailingObjects(); + return llvm::ArrayRef( + reinterpret_cast(list), + listCount->count + ); + } + static bool classof(const TargetContextDescriptor *cd) { return cd->getKind() == ContextDescriptorKind::Enum; } @@ -4587,6 +4739,24 @@ TargetTypeContextDescriptor::getSingletonMetadataInitialization() const } } +template +inline const llvm::ArrayRef, /*Nullable*/ false>> +TargetTypeContextDescriptor::getCanonicicalMetadataPrespecializations() const { + switch (this->getKind()) { + case ContextDescriptorKind::Enum: + return llvm::cast>(this) + ->getCanonicicalMetadataPrespecializations(); + case ContextDescriptorKind::Struct: + return llvm::cast>(this) + ->getCanonicicalMetadataPrespecializations(); + case ContextDescriptorKind::Class: + return llvm::cast>(this) + ->getCanonicicalMetadataPrespecializations(); + default: + swift_runtime_unreachable("Not a type context descriptor."); + } +} + /// An entry in the chain of dynamic replacement functions. struct DynamicReplacementChainEntry { void *implementationFunction; diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h index b5b62a7edf5f0..54232972ca9fd 100644 --- a/include/swift/ABI/MetadataValues.h +++ b/include/swift/ABI/MetadataValues.h @@ -1326,6 +1326,10 @@ class TypeContextDescriptorFlags : public FlagSet { /// Meaningful for all type-descriptor kinds. HasImportInfo = 2, + /// Set if the type descriptor has a pointer to a list of canonical + /// prespecializations. + HasCanonicalMetadataPrespecializations = 3, + // Type-specific flags: /// The kind of reference that this class makes to its resilient superclass @@ -1393,6 +1397,8 @@ class TypeContextDescriptorFlags : public FlagSet { FLAGSET_DEFINE_FLAG_ACCESSORS(HasImportInfo, hasImportInfo, setHasImportInfo) + FLAGSET_DEFINE_FLAG_ACCESSORS(HasCanonicalMetadataPrespecializations, hasCanonicalMetadataPrespecializations, setHasCanonicalMetadataPrespecializations) + FLAGSET_DEFINE_FLAG_ACCESSORS(Class_HasVTable, class_hasVTable, class_setHasVTable) diff --git a/include/swift/ABI/ObjectFile.h b/include/swift/ABI/ObjectFile.h new file mode 100644 index 0000000000000..cd570132cdc0a --- /dev/null +++ b/include/swift/ABI/ObjectFile.h @@ -0,0 +1,99 @@ +//===--- ObjectFile.h - Object File Related Information ------*- C++ -*-===// +// +// Object File related data structures. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_ABI_OBJECTFILE_H +#define SWIFT_ABI_OBJECTFILE_H + +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/StringRef.h" + +namespace swift { + +/// Represents the six reflection sections used by Swift +enum ReflectionSectionKind : uint8_t { + fieldmd, + assocty, + builtin, + capture, + typeref, + reflstr +}; + +/// Abstract base class responsible for providing the correct reflection section +/// string identifier for a given object file type (Mach-O, ELF, COFF). +class SwiftObjectFileFormat { +public: + virtual ~SwiftObjectFileFormat() {} + virtual llvm::StringRef getSectionName(ReflectionSectionKind section) = 0; +}; + +/// Responsible for providing the Mach-O reflection section identifiers. +class SwiftObjectFileFormatMachO : SwiftObjectFileFormat { +public: + llvm::StringRef getSectionName(ReflectionSectionKind section) override { + switch (section) { + case fieldmd: + return "__swift5_fieldmd"; + case assocty: + return "__swift5_assocty"; + case builtin: + return "__swift5_builtin"; + case capture: + return "__swift5_capture"; + case typeref: + return "__swift5_typeref"; + case reflstr: + return "__swift5_reflstr"; + } + llvm_unreachable("Section type not found."); + } +}; + +/// Responsible for providing the ELF reflection section identifiers. +class SwiftObjectFileFormatELF : SwiftObjectFileFormat { +public: + llvm::StringRef getSectionName(ReflectionSectionKind section) override { + switch (section) { + case fieldmd: + return "swift5_fieldmd"; + case assocty: + return "swift5_assocty"; + case builtin: + return "swift5_builtin"; + case capture: + return "swift5_capture"; + case typeref: + return "swift5_typeref"; + case reflstr: + return "swift5_reflstr"; + } + llvm_unreachable("Section type not found."); + } +}; + +/// Responsible for providing the COFF reflection section identifiers +class SwiftObjectFileFormatCOFF : SwiftObjectFileFormat { +public: + llvm::StringRef getSectionName(ReflectionSectionKind section) override { + switch (section) { + case fieldmd: + return ".sw5flmd"; + case assocty: + return ".sw5asty"; + case builtin: + return ".sw5bltn"; + case capture: + return ".sw5cptr"; + case typeref: + return ".sw5tyrf"; + case reflstr: + return ".sw5rfst"; + } + llvm_unreachable("Section not found."); + } +}; +} // namespace swift +#endif // SWIFT_ABI_OBJECTFILE_H diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index e3745be52d7b2..7697baf4d1d01 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -62,6 +62,7 @@ namespace swift { class BoundGenericType; class ClangModuleLoader; class ClangNode; + class ClangTypeConverter; class ConcreteDeclRef; class ConstructorDecl; class Decl; @@ -586,6 +587,10 @@ class ASTContext final { Type getBridgedToObjC(const DeclContext *dc, Type type, Type *bridgedValueType = nullptr) const; +private: + ClangTypeConverter &getClangTypeConverter(); + +public: /// Get the Clang type corresponding to a Swift function type. /// /// \param params The function parameters. @@ -595,6 +600,14 @@ class ASTContext final { getClangFunctionType(ArrayRef params, Type resultTy, FunctionTypeRepresentation trueRep); + /// Get the canonical Clang type corresponding to a SIL function type. + /// + /// SIL analog of \c ASTContext::getClangFunctionType . + const clang::Type * + getCanonicalClangFunctionType( + ArrayRef params, Optional result, + SILFunctionType::Representation trueRep); + /// Get the Swift declaration that a Clang declaration was exported from, /// if applicable. const Decl *getSwiftDeclForExportedClangDecl(const clang::Decl *decl); @@ -669,6 +682,10 @@ class ASTContext final { /// compiler for the target platform. AvailabilityContext getSwift53Availability(); + /// Get the runtime availability of features introduced in the Swift 5.4 + /// compiler for the target platform. + AvailabilityContext getSwift54Availability(); + /// Get the runtime availability of features that have been introduced in the /// Swift compiler for future versions of the target platform. AvailabilityContext getSwiftFutureAvailability(); @@ -735,6 +752,12 @@ class ASTContext final { ModuleDependenciesCache &cache, InterfaceSubContextDelegate &delegate); + /// Retrieve the module dependencies for the Swift module with the given name. + Optional getSwiftModuleDependencies( + StringRef moduleName, + ModuleDependenciesCache &cache, + InterfaceSubContextDelegate &delegate); + /// Load extensions to the given nominal type from the external /// module loaders. /// diff --git a/include/swift/AST/ASTMangler.h b/include/swift/AST/ASTMangler.h index 50c401e7ee2bc..b244e766ffc52 100644 --- a/include/swift/AST/ASTMangler.h +++ b/include/swift/AST/ASTMangler.h @@ -146,7 +146,8 @@ class ASTMangler : public Mangler { std::string mangleGlobalVariableFull(const VarDecl *decl); - std::string mangleGlobalInit(const VarDecl *decl, int counter, + std::string mangleGlobalInit(const PatternBindingDecl *decl, + unsigned entry, bool isInitFunc); std::string mangleReabstractionThunkHelper(CanSILFunctionType ThunkType, diff --git a/include/swift/AST/ASTPrinter.h b/include/swift/AST/ASTPrinter.h index 3c28d725ab6bb..3273d3ec4d7f4 100644 --- a/include/swift/AST/ASTPrinter.h +++ b/include/swift/AST/ASTPrinter.h @@ -325,7 +325,7 @@ class ExtraIndentStreamPrinter : public StreamPrinter { ExtraIndentStreamPrinter(raw_ostream &out, StringRef extraIndent) : StreamPrinter(out), ExtraIndent(extraIndent) { } - virtual void printIndent() { + virtual void printIndent() override { printText(ExtraIndent); StreamPrinter::printIndent(); } diff --git a/include/swift/AST/ASTTypeIDZone.def b/include/swift/AST/ASTTypeIDZone.def index bf6aeaf1e65dc..fa9dd1d3a8d3c 100644 --- a/include/swift/AST/ASTTypeIDZone.def +++ b/include/swift/AST/ASTTypeIDZone.def @@ -28,6 +28,7 @@ SWIFT_TYPEID(Requirement) SWIFT_TYPEID(ResilienceExpansion) SWIFT_TYPEID(FragileFunctionKind) SWIFT_TYPEID(TangentPropertyInfo) +SWIFT_TYPEID(SymbolSourceMap) SWIFT_TYPEID(Type) SWIFT_TYPEID(TypePair) SWIFT_TYPEID(TypeWitnessAndDecl) diff --git a/include/swift/AST/ASTTypeIDs.h b/include/swift/AST/ASTTypeIDs.h index 973f7dc2c9836..6fc964d6fa305 100644 --- a/include/swift/AST/ASTTypeIDs.h +++ b/include/swift/AST/ASTTypeIDs.h @@ -60,6 +60,7 @@ class Requirement; enum class ResilienceExpansion : unsigned; struct FragileFunctionKind; class SourceFile; +class SymbolSourceMap; struct TangentPropertyInfo; class Type; class TypeAliasDecl; diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def index b6fea6459d533..2c744e4c0769a 100644 --- a/include/swift/AST/Attr.def +++ b/include/swift/AST/Attr.def @@ -53,6 +53,7 @@ TYPE_ATTR(noescape) TYPE_ATTR(escaping) TYPE_ATTR(differentiable) TYPE_ATTR(noDerivative) +TYPE_ATTR(async) // SIL-specific attributes TYPE_ATTR(block_storage) @@ -560,6 +561,11 @@ SIMPLE_DECL_ATTR(noDerivative, NoDerivative, ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, 100) +SIMPLE_DECL_ATTR(asyncHandler, AsyncHandler, + OnFunc | UserInaccessible | + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + 101) + #undef TYPE_ATTR #undef DECL_ATTR_ALIAS #undef CONTEXTUAL_DECL_ATTR_ALIAS diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h index 25fa621adf0bc..0c67ece50d09f 100644 --- a/include/swift/AST/Attr.h +++ b/include/swift/AST/Attr.h @@ -1427,7 +1427,7 @@ class SpecializeAttr : public DeclAttribute { TrailingWhereClause *getTrailingWhereClause() const; - GenericSignature getSpecializedSgnature() const { + GenericSignature getSpecializedSignature() const { return specializedSignature; } diff --git a/include/swift/AST/ClangModuleLoader.h b/include/swift/AST/ClangModuleLoader.h index 64bc7e7d58413..06c41a3d8e61e 100644 --- a/include/swift/AST/ClangModuleLoader.h +++ b/include/swift/AST/ClangModuleLoader.h @@ -109,7 +109,7 @@ class StableSerializationPath { class ClangModuleLoader : public ModuleLoader { private: - virtual void anchor(); + virtual void anchor() override; protected: using ModuleLoader::ModuleLoader; diff --git a/include/swift/AST/ClangNode.h b/include/swift/AST/ClangNode.h index cbf120840b661..73a633bacd70e 100644 --- a/include/swift/AST/ClangNode.h +++ b/include/swift/AST/ClangNode.h @@ -13,6 +13,7 @@ #ifndef SWIFT_CLANGNODE_H #define SWIFT_CLANGNODE_H +#include "swift/Basic/Debug.h" #include "llvm/ADT/PointerUnion.h" namespace clang { @@ -98,6 +99,8 @@ class ClangNode { clang::SourceLocation getLocation() const; clang::SourceRange getSourceRange() const; + SWIFT_DEBUG_DUMP; + void *getOpaqueValue() const { return Ptr.getOpaqueValue(); } static inline ClangNode getFromOpaqueValue(void *VP) { ClangNode N; diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index e3fb02109d10b..5842456999735 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -63,6 +63,7 @@ namespace swift { class Type; class Expr; class DeclRefExpr; + class ForeignAsyncConvention; class ForeignErrorConvention; class LiteralExpr; class BraceStmt; @@ -283,7 +284,7 @@ class alignas(1 << DeclAlignInBits) Decl { protected: union { uint64_t OpaqueBits; - SWIFT_INLINE_BITFIELD_BASE(Decl, bitmax(NumDeclKindBits,8)+1+1+1+1+1, + SWIFT_INLINE_BITFIELD_BASE(Decl, bitmax(NumDeclKindBits,8)+1+1+1+1, Kind : bitmax(NumDeclKindBits,8), /// Whether this declaration is invalid. @@ -385,7 +386,7 @@ class alignas(1 << DeclAlignInBits) Decl { SWIFT_INLINE_BITFIELD(SubscriptDecl, VarDecl, 2, StaticSpelling : 2 ); - SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+1+1+1+1+1+1+1, + SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+8+1+1+1+1+1+1, /// \see AbstractFunctionDecl::BodyKind BodyKind : 3, @@ -2996,11 +2997,29 @@ class TypeAliasDecl : public GenericTypeDecl { /// Retrieve a sugared interface type containing the structure of the interface /// type before any semantic validation has occured. Type getStructuralType() const; - + + /// Whether the typealias forwards perfectly to its underlying type. + /// + /// If true, this typealias was created by ClangImporter to preserve source + /// compatibility with a previous language version's name for a type. Many + /// checks in Sema look through compatibility aliases even when they would + /// operate on other typealiases. + /// + /// \warning This has absolutely nothing to do with the Objective-C + /// \c compatibility_alias keyword. bool isCompatibilityAlias() const { return Bits.TypeAliasDecl.IsCompatibilityAlias; } + /// Sets whether the typealias forwards perfectly to its underlying type. + /// + /// Marks this typealias as having been created by ClangImporter to preserve + /// source compatibility with a previous language version's name for a type. + /// Many checks in Sema look through compatibility aliases even when they + /// would operate on other typealiases. + /// + /// \warning This has absolutely nothing to do with the Objective-C + /// \c compatibility_alias keyword. void markAsCompatibilityAlias(bool newValue = true) { Bits.TypeAliasDecl.IsCompatibilityAlias = newValue; } @@ -5598,17 +5617,20 @@ enum class ObjCSubscriptKind { /// signatures (indices and element type) are distinct. /// class SubscriptDecl : public GenericContext, public AbstractStorageDecl { + friend class ResultTypeRequest; + SourceLoc StaticLoc; SourceLoc ArrowLoc; SourceLoc EndLoc; ParameterList *Indices; TypeLoc ElementTy; -public: + void setElementInterfaceType(Type type); + SubscriptDecl(DeclName Name, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, SourceLoc SubscriptLoc, ParameterList *Indices, - SourceLoc ArrowLoc, TypeLoc ElementTy, DeclContext *Parent, + SourceLoc ArrowLoc, TypeRepr *ElementTyR, DeclContext *Parent, GenericParamList *GenericParams) : GenericContext(DeclContextKind::SubscriptDecl, Parent, GenericParams), AbstractStorageDecl(DeclKind::Subscript, @@ -5616,10 +5638,31 @@ class SubscriptDecl : public GenericContext, public AbstractStorageDecl { Parent, Name, SubscriptLoc, /*will be overwritten*/ StorageIsNotMutable), StaticLoc(StaticLoc), ArrowLoc(ArrowLoc), - Indices(nullptr), ElementTy(ElementTy) { + Indices(nullptr), ElementTy(ElementTyR) { Bits.SubscriptDecl.StaticSpelling = static_cast(StaticSpelling); setIndices(Indices); } + +public: + /// Factory function only for use by deserialization. + static SubscriptDecl *createDeserialized(ASTContext &Context, DeclName Name, + StaticSpellingKind StaticSpelling, + Type ElementTy, DeclContext *Parent, + GenericParamList *GenericParams); + + static SubscriptDecl *create(ASTContext &Context, DeclName Name, + SourceLoc StaticLoc, + StaticSpellingKind StaticSpelling, + SourceLoc SubscriptLoc, ParameterList *Indices, + SourceLoc ArrowLoc, TypeRepr *ElementTyR, + DeclContext *Parent, + GenericParamList *GenericParams); + + static SubscriptDecl *createImported(ASTContext &Context, DeclName Name, + SourceLoc SubscriptLoc, + ParameterList *Indices, + SourceLoc ArrowLoc, Type ElementTy, + DeclContext *Parent, ClangNode ClangN); /// \returns the way 'static'/'class' was spelled in the source. StaticSpellingKind getStaticSpelling() const { @@ -5646,8 +5689,11 @@ class SubscriptDecl : public GenericContext, public AbstractStorageDecl { /// Retrieve the type of the element referenced by a subscript /// operation. Type getElementInterfaceType() const; - TypeLoc &getElementTypeLoc() { return ElementTy; } - const TypeLoc &getElementTypeLoc() const { return ElementTy; } + + TypeRepr *getElementTypeRepr() const { return ElementTy.getTypeRepr(); } + SourceRange getElementTypeSourceRange() const { + return ElementTy.getSourceRange(); + } /// Determine the kind of Objective-C subscripting this declaration /// implies. @@ -5888,6 +5934,16 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl { /// type of the function will be `async` as well. bool hasAsync() const { return Bits.AbstractFunctionDecl.Async; } + /// Returns true if the function is a suitable 'async' context. + /// + /// Functions that are an 'async' context can make calls to 'async' functions. + bool isAsyncContext() const { + return hasAsync() || isAsyncHandler(); + } + + /// Returns true if the function is an @asyncHandler. + bool isAsyncHandler() const; + /// Returns true if the function body throws. bool hasThrows() const { return Bits.AbstractFunctionDecl.Throws; } @@ -5935,13 +5991,14 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl { /// Note that parsing for the body was delayed. void setBodyDelayed(SourceRange bodyRange) { - assert(getBodyKind() == BodyKind::None || - getBodyKind() == BodyKind::Skipped); + assert(getBodyKind() == BodyKind::None); assert(bodyRange.isValid()); BodyRange = bodyRange; setBodyKind(BodyKind::Unparsed); } + void setBodyToBeReparsed(SourceRange bodyRange); + /// Provide the parsed body for the function. void setBodyParsed(BraceStmt *S) { setBody(S, BodyKind::Parsed); @@ -6007,6 +6064,19 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl { /// Retrieve the source range of the function body. SourceRange getBodySourceRange() const; + /// Keep current \c getBodySourceRange() as the "original" body source range + /// iff the this method hasn't been called on this object. The current body + /// source range must be in the same buffer as the location of the declaration + /// itself. + void keepOriginalBodySourceRange(); + + /// Retrieve the source range of the *original* function body. + /// + /// This may be different from \c getBodySourceRange() that returns the source + /// range of the *current* body. It happens when the body is parsed from other + /// source buffers for e.g. code-completion. + SourceRange getOriginalBodySourceRange() const; + /// Retrieve the source range of the function declaration name + patterns. SourceRange getSignatureSourceRange() const; @@ -6079,7 +6149,15 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl { /// being dropped altogether. `None` is returned for a normal function /// or method. Optional getForeignFunctionAsMethodSelfParameterIndex() const; - + + /// Set information about the foreign async convention used by this + /// declaration. + void setForeignAsyncConvention(const ForeignAsyncConvention &convention); + + /// Get information about the foreign async convention used by this + /// declaration, given that it is @objc and 'async'. + Optional getForeignAsyncConvention() const; + static bool classof(const Decl *D) { return D->getKind() >= DeclKind::First_AbstractFunctionDecl && D->getKind() <= DeclKind::Last_AbstractFunctionDecl; @@ -6122,6 +6200,7 @@ class FuncDecl : public AbstractFunctionDecl { friend class AbstractFunctionDecl; friend class SelfAccessKindRequest; friend class IsStaticRequest; + friend class ResultTypeRequest; SourceLoc StaticLoc; // Location of the 'static' token or invalid. SourceLoc FuncLoc; // Location of the 'func' token. @@ -6156,6 +6235,8 @@ class FuncDecl : public AbstractFunctionDecl { Bits.FuncDecl.HasTopLevelLocalContextCaptures = false; } + void setResultInterfaceType(Type type); + private: static FuncDecl *createImpl(ASTContext &Context, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, @@ -6183,25 +6264,32 @@ class FuncDecl : public AbstractFunctionDecl { public: /// Factory function only for use by deserialization. - static FuncDecl *createDeserialized(ASTContext &Context, SourceLoc StaticLoc, + static FuncDecl *createDeserialized(ASTContext &Context, StaticSpellingKind StaticSpelling, - SourceLoc FuncLoc, - DeclName Name, SourceLoc NameLoc, - bool Async, SourceLoc AsyncLoc, - bool Throws, SourceLoc ThrowsLoc, + DeclName Name, bool Async, bool Throws, GenericParamList *GenericParams, - DeclContext *Parent); + Type FnRetType, DeclContext *Parent); static FuncDecl *create(ASTContext &Context, SourceLoc StaticLoc, - StaticSpellingKind StaticSpelling, - SourceLoc FuncLoc, - DeclName Name, SourceLoc NameLoc, - bool Async, SourceLoc AsyncLoc, - bool Throws, SourceLoc ThrowsLoc, + StaticSpellingKind StaticSpelling, SourceLoc FuncLoc, + DeclName Name, SourceLoc NameLoc, bool Async, + SourceLoc AsyncLoc, bool Throws, SourceLoc ThrowsLoc, GenericParamList *GenericParams, - ParameterList *ParameterList, - TypeLoc FnRetType, DeclContext *Parent, - ClangNode ClangN = ClangNode()); + ParameterList *BodyParams, TypeRepr *ResultTyR, + DeclContext *Parent); + + static FuncDecl *createImplicit(ASTContext &Context, + StaticSpellingKind StaticSpelling, + DeclName Name, SourceLoc NameLoc, bool Async, + bool Throws, GenericParamList *GenericParams, + ParameterList *BodyParams, Type FnRetType, + DeclContext *Parent); + + static FuncDecl *createImported(ASTContext &Context, SourceLoc FuncLoc, + DeclName Name, SourceLoc NameLoc, + bool Async, bool Throws, + ParameterList *BodyParams, Type FnRetType, + DeclContext *Parent, ClangNode ClangN); bool isStatic() const; @@ -6245,8 +6333,10 @@ class FuncDecl : public AbstractFunctionDecl { } SourceRange getSourceRange() const; - TypeLoc &getBodyResultTypeLoc() { return FnRetType; } - const TypeLoc &getBodyResultTypeLoc() const { return FnRetType; } + TypeRepr *getResultTypeRepr() const { return FnRetType.getTypeRepr(); } + SourceRange getResultTypeSourceRange() const { + return FnRetType.getSourceRange(); + } /// Retrieve the result interface type of this function. Type getResultInterfaceType() const; @@ -6367,15 +6457,12 @@ class AccessorDecl final : public FuncDecl { public: static AccessorDecl *createDeserialized(ASTContext &ctx, - SourceLoc declLoc, - SourceLoc accessorKeywordLoc, - AccessorKind accessorKind, - AbstractStorageDecl *storage, - SourceLoc staticLoc, - StaticSpellingKind staticSpelling, - bool throws, SourceLoc throwsLoc, - GenericParamList *genericParams, - DeclContext *parent); + AccessorKind accessorKind, + AbstractStorageDecl *storage, + StaticSpellingKind staticSpelling, + bool throws, + GenericParamList *genericParams, + Type fnRetType, DeclContext *parent); static AccessorDecl *create(ASTContext &ctx, SourceLoc declLoc, SourceLoc accessorKeywordLoc, @@ -6386,7 +6473,7 @@ class AccessorDecl final : public FuncDecl { bool throws, SourceLoc throwsLoc, GenericParamList *genericParams, ParameterList *parameterList, - TypeLoc fnRetType, DeclContext *parent, + Type fnRetType, DeclContext *parent, ClangNode clangNode = ClangNode()); SourceLoc getAccessorKeywordLoc() const { return AccessorKeywordLoc; } diff --git a/include/swift/AST/DiagnosticEngine.h b/include/swift/AST/DiagnosticEngine.h index ee3c776cd9db6..6d4fe61bbd4e2 100644 --- a/include/swift/AST/DiagnosticEngine.h +++ b/include/swift/AST/DiagnosticEngine.h @@ -20,8 +20,9 @@ #include "swift/AST/DeclNameLoc.h" #include "swift/AST/DiagnosticConsumer.h" -#include "swift/AST/LocalizationFormat.h" #include "swift/AST/TypeLoc.h" +#include "swift/Localization/LocalizationFormat.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/FileSystem.h" @@ -987,7 +988,8 @@ namespace swift { void emitTentativeDiagnostics(); public: - const char *diagnosticStringFor(const DiagID id, bool printDiagnosticName); + llvm::StringRef diagnosticStringFor(const DiagID id, + bool printDiagnosticName); /// If there is no clear .dia file for a diagnostic, put it in the one /// corresponding to the SourceLoc given here. @@ -1056,6 +1058,12 @@ namespace swift { } } + bool hasDiagnostics() const { + return std::distance(Engine.TentativeDiagnostics.begin() + + PrevDiagnostics, + Engine.TentativeDiagnostics.end()) > 0; + } + /// Abort and close this transaction and erase all diagnostics /// record while it was open. void abort() { diff --git a/include/swift/AST/DiagnosticsCommon.def b/include/swift/AST/DiagnosticsCommon.def index cdeef09e3058e..72d8d64bbecb7 100644 --- a/include/swift/AST/DiagnosticsCommon.def +++ b/include/swift/AST/DiagnosticsCommon.def @@ -185,5 +185,22 @@ WARNING(cross_imported_by_both_modules, none, ERROR(scanner_find_cycle, none, "dependency scanner detected dependency cycle: '%0'", (StringRef)) +ERROR(scanner_arguments_invalid, none, + "dependencies scanner cannot be configured with arguments: '%0'", (StringRef)) + +//------------------------------------------------------------------------------ +// MARK: custom attribute diagnostics +//------------------------------------------------------------------------------ + +ERROR(ambiguous_custom_attribute_ref,none, + "ambiguous use of attribute %0", (Identifier)) +NOTE(ambiguous_custom_attribute_ref_fix,none, + "use '%0.' to reference the attribute %1 in module %2", + (StringRef, Identifier, Identifier)) +NOTE(found_attribute_candidate,none, + "found this attribute", ()) +ERROR(unknown_attribute,none, + "unknown attribute '%0'", (StringRef)) + #define UNDEFINE_DIAGNOSTIC_MACROS #include "DefineDiagnosticMacros.h" diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def index 6f88d42b6b517..c49f47f65493e 100644 --- a/include/swift/AST/DiagnosticsFrontend.def +++ b/include/swift/AST/DiagnosticsFrontend.def @@ -270,6 +270,14 @@ ERROR(placeholder_dependency_module_map_corrupted,none, "Swift placeholder dependency module map from %0 is malformed", (StringRef)) +ERROR(batch_scan_input_file_missing,none, + "cannot open batch dependencies scan input file from %0", + (StringRef)) + +ERROR(batch_scan_input_file_corrupted,none, + "batch dependencies scan input file from %0 is malformed", + (StringRef)) + REMARK(default_previous_install_name, none, "default previous install name for %0 is %1", (StringRef, StringRef)) diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index 6c7f4e6533b04..3a278eb7dea14 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -1324,8 +1324,6 @@ ERROR(replace_equal_with_colon_for_value,none, "'=' has been replaced with ':' in attribute arguments", ()) ERROR(expected_attribute_name,none, "expected an attribute name", ()) -ERROR(unknown_attribute,none, - "unknown attribute '%0'", (StringRef)) ERROR(unexpected_lparen_in_attribute,none, "unexpected '(' in attribute '%0'", (StringRef)) ERROR(duplicate_attribute,none, diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 1998449474d87..9374d59db3e3f 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -112,6 +112,9 @@ ERROR(expected_argument_in_contextual_member,none, "member %0 expects argument of type %1", (DeclName, Type)) ERROR(expected_parens_in_contextual_member,none, "member %0 is a function; did you mean to call it?", (DeclName)) +ERROR(expected_parens_in_contextual_member_type,none, + "member %0 is a function that produces expected type %1; did you mean to " + "call it?", (DeclName, Type)) ERROR(expected_result_in_contextual_member,none, "member %0 in %2 produces result of type %1, but context expects %2", @@ -453,6 +456,10 @@ ERROR(cannot_convert_closure_result_nil,none, ERROR(cannot_convert_parent_type,none, "cannot convert parent type %0 to expected type %1", (Type, Type)) +ERROR(cannot_convert_chain_result_type,none, + "member chain produces result of type %0 but contextual base was " + "inferred as %1", + (Type, Type)) NOTE(generic_argument_mismatch,none, "arguments to generic parameter %0 (%1 and %2) are expected to be equal", @@ -708,12 +715,12 @@ ERROR(sema_opening_import,Fatal, ERROR(serialization_load_failed,Fatal, "failed to load module '%0'", (StringRef)) ERROR(module_interface_build_failed,Fatal, - "failed to build module '%0' from its module interface; " - "%select{the compiler that produced it, '%2', may have used features " - "that aren't supported by this compiler, '%3'" - "|it may have been damaged or it may have triggered a bug in the Swift " - "compiler when it was produced}1", - (StringRef, bool, StringRef, StringRef)) + "failed to %select{build module '%1' from its module interface|verify " + "module interface of '%1'}0; %select{the compiler that produced it, " + "'%3', may have used features that aren't supported by this compiler, " + "'%4'|it may have been damaged or it may have triggered a bug in the " + "Swift compiler when it was produced}2", + (bool, StringRef, bool, StringRef, StringRef)) ERROR(serialization_malformed_module,Fatal, "malformed compiled module: %0", (StringRef)) ERROR(serialization_module_too_new,Fatal, @@ -1082,6 +1089,9 @@ NOTE(unwrap_with_guard,none, ERROR(optional_base_not_unwrapped,none, "value of optional type %0 must be unwrapped to refer to member %1 of " "wrapped base type %2", (Type, DeclNameRef, Type)) +ERROR(invalid_optional_infered_keypath_root, none, + "key path root inferred as optional type %0 must be unwrapped to refer to member %1 " + "of unwrapped type %2", (Type, DeclNameRef, Type)) NOTE(optional_base_chain,none, "chain the optional using '?' to access member %0 only for non-'nil' " "base values", (DeclNameRef)) @@ -1089,6 +1099,12 @@ NOTE(optional_base_remove_optional_for_keypath_root, none, "use unwrapped type %0 as key path root", (Type)) NOTE(optional_keypath_application_base, none, "use '?' to access key path subscript only for non-'nil' base values", ()) +NOTE(optional_key_path_root_base_chain, none, + "chain the optional using '?.' to access unwrapped type member %0", + (DeclNameRef)) +NOTE(optional_key_path_root_base_unwrap, none, + "unwrap the optional using '!.' to access unwrapped type member %0", + (DeclNameRef)) ERROR(missing_unwrap_optional_try,none, "value of optional type %0 not unwrapped; did you mean to use 'try!' " @@ -1294,8 +1310,9 @@ ERROR(nominal_type_not_attribute,none, ERROR(mutating_invalid_global_scope,none, "%0 is only valid on methods", (SelfAccessKind)) -ERROR(mutating_invalid_classes,none, "%0 isn't valid on methods in " - "classes or class-bound protocols", (SelfAccessKind)) +ERROR(mutating_invalid_classes,none, "%0 is not valid on %1s in " + "%select{classes|class-bound protocols}2", + (SelfAccessKind, DescriptiveDeclKind, bool)) ERROR(functions_mutating_and_not,none, "method must not be declared both %0 and %1", @@ -2174,9 +2191,6 @@ NOTE(protocol_witness_settable_conflict,none, "candidate is not settable, but protocol requires it", ()) NOTE(protocol_witness_rethrows_conflict,none, "candidate is not 'rethrows', but protocol requires it", ()) -NOTE(protocol_witness_async_conflict,none, - "candidate is %select{not |}0'async', but protocol requirement is%select{| not}0", - (bool)) NOTE(protocol_witness_throws_conflict,none, "candidate throws, but protocol does not allow it", ()) NOTE(protocol_witness_not_objc,none, @@ -2765,8 +2779,9 @@ ERROR(cannot_synthesize_init_in_extension_of_nonfinal,none, "be satisfied by a 'required' initializer in the class definition", (Type, DeclName)) ERROR(cannot_synthesize_in_crossfile_extension,none, - "implementation of %0 cannot be automatically synthesized in an extension " - "in a different file to the type", (Type)) + "extension outside of file declaring %0 %1 prevents automatic synthesis " + "of %2 for protocol %3", + (DescriptiveDeclKind, DeclName, DeclName, Type)) ERROR(broken_additive_arithmetic_requirement,none, "AdditiveArithmetic protocol is broken: unexpected requirement", ()) @@ -4016,10 +4031,13 @@ ERROR(throw_in_nonexhaustive_catch,none, "error is not handled because the enclosing catch is not exhaustive", ()) ERROR(throwing_call_in_illegal_context,none, - "call can throw, but errors cannot be thrown out of %0", - (StringRef)) + "call can throw, but errors cannot be thrown out of " + "%select{<>|a default argument|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0", + (unsigned)) ERROR(throw_in_illegal_context,none, - "errors cannot be thrown out of %0", (StringRef)) + "errors cannot be thrown out of " + "%select{<>|a default argument|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0", + (unsigned)) ERROR(throwing_operator_without_try,none, "operator can throw but expression is not marked with 'try'", ()) @@ -4033,10 +4051,6 @@ NOTE(note_error_to_optional,none, "did you mean to handle error as optional value?", ()) NOTE(note_disable_error_propagation,none, "did you mean to disable error propagation?", ()) -ERROR(async_call_without_await,none, - "call is 'async' but is not marked with 'await'", ()) -WARNING(no_async_in_await,none, - "no calls to 'async' functions occur within 'await' expression", ()) WARNING(no_throw_in_try,none, "no calls to throwing functions occur within 'try' expression", ()) @@ -4044,6 +4058,63 @@ WARNING(no_throw_in_try,none, WARNING(no_throw_in_do_with_catch,none, "'catch' block is unreachable because no errors are thrown in 'do' block", ()) +//------------------------------------------------------------------------------ +// MARK: Concurrency +//------------------------------------------------------------------------------ +ERROR(async_call_without_await,none, + "call is 'async' but is not marked with 'await'", ()) +ERROR(async_call_without_await_in_autoclosure,none, + "call is 'async' in an autoclosure argument that is not marked with 'await'", ()) +WARNING(no_async_in_await,none, + "no calls to 'async' functions occur within 'await' expression", ()) +ERROR(async_call_in_illegal_context,none, + "'async' call cannot occur in " + "%select{<>|a default argument|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0", + (unsigned)) +ERROR(await_in_illegal_context,none, + "'await' operation cannot occur in " + "%select{<>|a default argument|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0", + (unsigned)) +ERROR(async_in_nonasync_function,none, + "%select{'async'|'await'}0 in %select{a function|an autoclosure}1 that " + "does not support concurrency", + (bool, bool)) +NOTE(note_add_async_to_function,none, + "add 'async' to function %0 to make it asynchronous", (DeclName)) +NOTE(note_add_asynchandler_to_function,none, + "add '@asyncHandler' to function %0 to create an implicit asynchronous context", (DeclName)) +ERROR(not_objc_function_async,none, + "'async' function cannot be represented in Objective-C", ()) +NOTE(not_objc_function_type_async,none, + "'async' function types cannot be represented in Objective-C", ()) +NOTE(protocol_witness_async_conflict,none, + "candidate is %select{not |}0'async', but protocol requirement is%select{| not}0", + (bool)) +ERROR(async_autoclosure_nonasync_function,none, + "'async' autoclosure parameter in a non-'async' function", ()) + +ERROR(asynchandler_attr_requires_concurrency,none, + "'@asyncHandler' is only valid when experimental concurrency is enabled", + ()) +ERROR(asynchandler_non_func,none, + "'@asyncHandler' can only be applied to functions", + ()) +ERROR(asynchandler_returns_value,none, + "'@asyncHandler' function can only return 'Void'", + ()) +ERROR(asynchandler_throws,none, + "'@asyncHandler' function cannot throw", + ()) +ERROR(asynchandler_async,none, + "'@asyncHandler' function cannot be 'async' itself", + ()) +ERROR(asynchandler_inout_parameter,none, + "'inout' parameter is not allowed in '@asyncHandler' function", + ()) +ERROR(asynchandler_mutating,none, + "'@asyncHandler' function cannot be 'mutating'", + ()) + //------------------------------------------------------------------------------ // MARK: Type Check Types //------------------------------------------------------------------------------ @@ -4398,10 +4469,6 @@ NOTE(not_objc_generic_type_param,none, NOTE(not_objc_function_type_param,none, "function types cannot be represented in Objective-C unless their " "parameters and returns can be", ()) -ERROR(not_objc_function_async,none, - "'async' function cannot be represented in Objective-C", ()) -NOTE(not_objc_function_type_async,none, - "'async' function types cannot be represented in Objective-C", ()) NOTE(not_objc_function_type_throwing,none, "throwing function types cannot be represented in Objective-C", ()) NOTE(objc_inferring_on_objc_protocol_member,none, diff --git a/include/swift/AST/Evaluator.h b/include/swift/AST/Evaluator.h index 5235343ebe779..212682d0bc121 100644 --- a/include/swift/AST/Evaluator.h +++ b/include/swift/AST/Evaluator.h @@ -65,7 +65,7 @@ class PrettyStackTraceRequest : public llvm::PrettyStackTraceEntry { public: PrettyStackTraceRequest(const Request &request) : request(request) { } - void print(llvm::raw_ostream &out) const { + void print(llvm::raw_ostream &out) const override { out << "While evaluating request "; simple_display(out, request); out << "\n"; @@ -85,9 +85,9 @@ struct CyclicalRequestError : CyclicalRequestError(const Request &request, const Evaluator &evaluator) : request(request), evaluator(evaluator) {} - virtual void log(llvm::raw_ostream &out) const; + virtual void log(llvm::raw_ostream &out) const override; - virtual std::error_code convertToErrorCode() const { + virtual std::error_code convertToErrorCode() const override { // This is essentially unused, but is a temporary requirement for // llvm::ErrorInfo subclasses. llvm_unreachable("shouldn't get std::error_code from CyclicalRequestError"); diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index a75d9d56b39e4..b53a279a93b4c 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -249,17 +249,8 @@ class alignas(8) Expr { NumArgLabels : 16 ); - SWIFT_INLINE_BITFIELD_FULL(UnresolvedMemberExpr, Expr, 1+1+1+16, - /// Whether the UnresolvedMemberExpr has arguments. - HasArguments : 1, - /// Whether the UnresolvedMemberExpr also has source locations for the - /// argument label. - HasArgLabelLocs : 1, - /// Whether the last argument is a trailing closure. - HasTrailingClosure : 1, - : NumPadBits, - /// # of argument labels stored after the UnresolvedMemberExpr. - NumArgLabels : 16 + SWIFT_INLINE_BITFIELD_FULL(UnresolvedMemberExpr, Expr, 2, + FunctionRefKind : 2 ); SWIFT_INLINE_BITFIELD(OverloadSetRefExpr, Expr, 2, @@ -1841,71 +1832,49 @@ class DynamicSubscriptExpr final /// member, which is to be resolved with context sensitive type information into /// bar.foo. These always have unresolved type. class UnresolvedMemberExpr final - : public Expr, - public TrailingCallArguments { + : public Expr { SourceLoc DotLoc; DeclNameLoc NameLoc; DeclNameRef Name; - Expr *Argument; - - UnresolvedMemberExpr(SourceLoc dotLoc, DeclNameLoc nameLoc, - DeclNameRef name, Expr *argument, - ArrayRef argLabels, - ArrayRef argLabelLocs, - bool hasTrailingClosure, - bool implicit); public: - /// Create a new unresolved member expression with no arguments. - static UnresolvedMemberExpr *create(ASTContext &ctx, SourceLoc dotLoc, - DeclNameLoc nameLoc, DeclNameRef name, - bool implicit); - - /// Create a new unresolved member expression. - static UnresolvedMemberExpr *create(ASTContext &ctx, SourceLoc dotLoc, - DeclNameLoc nameLoc, DeclNameRef name, - SourceLoc lParenLoc, - ArrayRef args, - ArrayRef argLabels, - ArrayRef argLabelLocs, - SourceLoc rParenLoc, - ArrayRef trailingClosures, - bool implicit); + UnresolvedMemberExpr(SourceLoc dotLoc, DeclNameLoc nameLoc, DeclNameRef name, + bool implicit) + : Expr(ExprKind::UnresolvedMember, implicit), DotLoc(dotLoc), + NameLoc(nameLoc), Name(name) { + // FIXME: Really, we should be setting this to `FunctionRefKind::Compound` + // if `NameLoc` is compound, but this would be a source break for cases like + // ``` + // struct S { + // static func makeS(_: Int) -> S! { S() } + // } + // + // let s: S = .makeS(_:)(0) + // ``` + // Instead, we should store compound-ness as a separate bit from applied/ + // unapplied. + Bits.UnresolvedMemberExpr.FunctionRefKind = + static_cast(FunctionRefKind::Unapplied); + } DeclNameRef getName() const { return Name; } DeclNameLoc getNameLoc() const { return NameLoc; } SourceLoc getDotLoc() const { return DotLoc; } - Expr *getArgument() const { return Argument; } - void setArgument(Expr *argument) { Argument = argument; } - - /// Whether this reference has arguments. - bool hasArguments() const { - return Bits.UnresolvedMemberExpr.HasArguments; - } - unsigned getNumArguments() const { - return Bits.UnresolvedMemberExpr.NumArgLabels; - } - - bool hasArgumentLabelLocs() const { - return Bits.UnresolvedMemberExpr.HasArgLabelLocs; - } + SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); } - /// Whether this call with written with a trailing closure. - bool hasTrailingClosure() const { - return Bits.UnresolvedMemberExpr.HasTrailingClosure; - } + SourceLoc getStartLoc() const { return DotLoc; } + SourceLoc getEndLoc() const { return NameLoc.getSourceRange().End; } - /// Return the index of the unlabeled trailing closure argument. - Optional getUnlabeledTrailingClosureIndex() const { - return getArgument()->getUnlabeledTrailingClosureIndexOfPackedArgument(); + /// Retrieve the kind of function reference. + FunctionRefKind getFunctionRefKind() const { + return static_cast( + Bits.UnresolvedMemberExpr.FunctionRefKind); } - SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); } - - SourceLoc getStartLoc() const { return DotLoc; } - SourceLoc getEndLoc() const { - return (Argument ? Argument->getEndLoc() : NameLoc.getSourceRange().End); + /// Set the kind of function reference. + void setFunctionRefKind(FunctionRefKind refKind) { + Bits.UnresolvedMemberExpr.FunctionRefKind = static_cast(refKind); } static bool classof(const Expr *E) { @@ -2088,6 +2057,31 @@ class ParenExpr : public IdentityExpr { static bool classof(const Expr *E) { return E->getKind() == ExprKind::Paren; } }; + +/// Represents the result of a chain of accesses or calls hanging off of an +/// \c UnresolvedMemberExpr at the root. This is only used during type checking +/// to give the result type of such a chain representation in the AST. This +/// expression type is always implicit. +class UnresolvedMemberChainResultExpr : public IdentityExpr { + /// The base of this chain of member accesses. + UnresolvedMemberExpr *ChainBase; +public: + UnresolvedMemberChainResultExpr(Expr *subExpr, UnresolvedMemberExpr *base, + Type ty = Type()) + : IdentityExpr(ExprKind::UnresolvedMemberChainResult, subExpr, ty, + /*isImplicit=*/true), + ChainBase(base) { + assert(base); + } + + UnresolvedMemberExpr *getChainBase() const { return ChainBase; } + + SWIFT_FORWARD_SOURCE_LOCS_TO(getSubExpr()) + + static bool classof(const Expr *E) { + return E->getKind() == ExprKind::UnresolvedMemberChainResult; + } +}; /// AwaitExpr - An 'await' surrounding an expression, marking that the /// expression contains code which is a coroutine that may block. @@ -3815,6 +3809,9 @@ class ClosureExpr : public AbstractClosureExpr { /// this information directly on the ClosureExpr. VarDecl * CapturedSelfDecl; + /// The location of the "async", if present. + SourceLoc AsyncLoc; + /// The location of the "throws", if present. SourceLoc ThrowsLoc; @@ -3833,14 +3830,15 @@ class ClosureExpr : public AbstractClosureExpr { llvm::PointerIntPair Body; public: ClosureExpr(SourceRange bracketRange, VarDecl *capturedSelfDecl, - ParameterList *params, SourceLoc throwsLoc, SourceLoc arrowLoc, - SourceLoc inLoc, TypeExpr *explicitResultType, + ParameterList *params, SourceLoc asyncLoc, SourceLoc throwsLoc, + SourceLoc arrowLoc, SourceLoc inLoc, TypeExpr *explicitResultType, unsigned discriminator, DeclContext *parent) : AbstractClosureExpr(ExprKind::Closure, Type(), /*Implicit=*/false, discriminator, parent), BracketRange(bracketRange), CapturedSelfDecl(capturedSelfDecl), - ThrowsLoc(throwsLoc), ArrowLoc(arrowLoc), InLoc(inLoc), + AsyncLoc(asyncLoc), ThrowsLoc(throwsLoc), ArrowLoc(arrowLoc), + InLoc(inLoc), ExplicitResultTypeAndBodyState(explicitResultType, BodyState::Parsed), Body(nullptr) { setParameterList(params); @@ -3888,7 +3886,12 @@ class ClosureExpr : public AbstractClosureExpr { SourceLoc getInLoc() const { return InLoc; } - + + /// Retrieve the location of the 'async' for a closure that has it. + SourceLoc getAsyncLoc() const { + return AsyncLoc; + } + /// Retrieve the location of the 'throws' for a closure that has it. SourceLoc getThrowsLoc() const { return ThrowsLoc; @@ -5648,7 +5651,13 @@ class KeyPathExpr : public Expr { /// components from the argument array. void resolveComponents(ASTContext &C, ArrayRef resolvedComponents); - + + /// Indicates if the key path expression is composed by a single invalid + /// component. e.g. missing component `\Root` + bool hasSingleInvalidComponent() const { + return Components.size() == 1 && !Components.front().isValid(); + } + /// Retrieve the string literal expression, which will be \c NULL prior to /// type checking and a string literal after type checking for an /// @objc key path. diff --git a/include/swift/AST/ExprNodes.def b/include/swift/AST/ExprNodes.def index 53ee2da310a42..7c98a83c0afd9 100644 --- a/include/swift/AST/ExprNodes.def +++ b/include/swift/AST/ExprNodes.def @@ -104,7 +104,8 @@ ABSTRACT_EXPR(Identity, Expr) EXPR(Paren, IdentityExpr) EXPR(DotSelf, IdentityExpr) EXPR(Await, IdentityExpr) - EXPR_RANGE(Identity, Paren, Await) + EXPR(UnresolvedMemberChainResult, IdentityExpr) + EXPR_RANGE(Identity, Paren, UnresolvedMemberChainResult) ABSTRACT_EXPR(AnyTry, Expr) EXPR(Try, AnyTryExpr) EXPR(ForceTry, AnyTryExpr) diff --git a/include/swift/AST/ExtInfo.h b/include/swift/AST/ExtInfo.h index 639b982d25e73..55ea27bc47dc8 100644 --- a/include/swift/AST/ExtInfo.h +++ b/include/swift/AST/ExtInfo.h @@ -194,16 +194,8 @@ class ASTExtInfoBuilder { using Representation = FunctionTypeRepresentation; - static void assertIsFunctionType(const clang::Type *); - ASTExtInfoBuilder(unsigned bits, ClangTypeInfo clangTypeInfo) - : bits(bits), clangTypeInfo(clangTypeInfo) { - // TODO: [clang-function-type-serialization] Once we start serializing - // the Clang type, we should also assert that the pointer is non-null. - auto Rep = Representation(bits & RepresentationMask); - if ((Rep == Representation::CFunctionPointer) && clangTypeInfo.type) - assertIsFunctionType(clangTypeInfo.type); - } + : bits(bits), clangTypeInfo(clangTypeInfo) {} public: // Constructor with all defaults. @@ -254,10 +246,7 @@ class ASTExtInfoBuilder { DifferentiabilityKind::NonDifferentiable; } - /// Get the underlying ClangTypeInfo value if it is not the default value. - Optional getClangTypeInfo() const { - return clangTypeInfo.empty() ? Optional() : clangTypeInfo; - } + ClangTypeInfo getClangTypeInfo() const { return clangTypeInfo; } constexpr SILFunctionTypeRepresentation getSILRepresentation() const { unsigned rawRep = bits & RepresentationMask; @@ -404,9 +393,7 @@ class ASTExtInfo { constexpr bool isDifferentiable() const { return builder.isDifferentiable(); } - Optional getClangTypeInfo() const { - return builder.getClangTypeInfo(); - } + ClangTypeInfo getClangTypeInfo() const { return builder.getClangTypeInfo(); } constexpr bool hasSelfParam() const { return builder.hasSelfParam(); } @@ -436,6 +423,14 @@ class ASTExtInfo { return builder.withThrows(throws).build(); } + /// Helper method for changing only the async field. + /// + /// Prefer using \c ASTExtInfoBuilder::withAsync for chaining. + LLVM_NODISCARD + ASTExtInfo withAsync(bool async = true) const { + return builder.withAsync(async).build(); + } + bool isEqualTo(ASTExtInfo other, bool useClangTypes) const { return builder.isEqualTo(other.builder, useClangTypes); } @@ -487,16 +482,17 @@ class SILExtInfoBuilder { // If bits are added or removed, then TypeBase::SILFunctionTypeBits // and NumMaskBits must be updated, and they must match. - // |representation|pseudogeneric| noescape |differentiability| - // | 0 .. 3 | 4 | 5 | 6 .. 7 | + // |representation|pseudogeneric| noescape | async | differentiability| + // | 0 .. 3 | 4 | 5 | 6 | 7 .. 8 | // enum : unsigned { RepresentationMask = 0xF << 0, PseudogenericMask = 1 << 4, NoEscapeMask = 1 << 5, - DifferentiabilityMaskOffset = 6, + AsyncMask = 1 << 6, + DifferentiabilityMaskOffset = 7, DifferentiabilityMask = 0x3 << DifferentiabilityMaskOffset, - NumMaskBits = 8 + NumMaskBits = 9 }; unsigned bits; // Naturally sized for speed. @@ -509,19 +505,32 @@ class SILExtInfoBuilder { SILExtInfoBuilder(unsigned bits, ClangTypeInfo clangTypeInfo) : bits(bits), clangTypeInfo(clangTypeInfo) {} + static constexpr unsigned makeBits(Representation rep, bool isPseudogeneric, + bool isNoEscape, bool isAsync, + DifferentiabilityKind diffKind) { + return ((unsigned)rep) | (isPseudogeneric ? PseudogenericMask : 0) | + (isNoEscape ? NoEscapeMask : 0) | (isAsync ? AsyncMask : 0) | + (((unsigned)diffKind << DifferentiabilityMaskOffset) & + DifferentiabilityMask); + } + public: // Constructor with all defaults. - SILExtInfoBuilder() : bits(0), clangTypeInfo(ClangTypeInfo(nullptr)) {} + SILExtInfoBuilder() : SILExtInfoBuilder(0, ClangTypeInfo(nullptr)) {} // Constructor for polymorphic type. SILExtInfoBuilder(Representation rep, bool isPseudogeneric, bool isNoEscape, - DifferentiabilityKind diffKind, const clang::Type *type) - : SILExtInfoBuilder( - ((unsigned)rep) | (isPseudogeneric ? PseudogenericMask : 0) | - (isNoEscape ? NoEscapeMask : 0) | - (((unsigned)diffKind << DifferentiabilityMaskOffset) & - DifferentiabilityMask), - ClangTypeInfo(type)) {} + bool isAsync, DifferentiabilityKind diffKind, + const clang::Type *type) + : SILExtInfoBuilder(makeBits(rep, isPseudogeneric, isNoEscape, isAsync, + diffKind), + ClangTypeInfo(type)) {} + + SILExtInfoBuilder(ASTExtInfoBuilder info, bool isPseudogeneric) + : SILExtInfoBuilder(makeBits(info.getSILRepresentation(), isPseudogeneric, + info.isNoEscape(), info.isAsync(), + info.getDifferentiabilityKind()), + info.getClangTypeInfo()) {} void checkInvariants() const; @@ -544,6 +553,8 @@ class SILExtInfoBuilder { // Is this function guaranteed to be no-escape by the type system? constexpr bool isNoEscape() const { return bits & NoEscapeMask; } + constexpr bool isAsync() const { return bits & AsyncMask; } + constexpr DifferentiabilityKind getDifferentiabilityKind() const { return DifferentiabilityKind((bits & DifferentiabilityMask) >> DifferentiabilityMaskOffset); @@ -554,10 +565,8 @@ class SILExtInfoBuilder { DifferentiabilityKind::NonDifferentiable; } - /// Get the underlying ClangTypeInfo value if it is not the default value. - Optional getClangTypeInfo() const { - return clangTypeInfo.empty() ? Optional() : clangTypeInfo; - } + /// Get the underlying ClangTypeInfo value. + ClangTypeInfo getClangTypeInfo() const { return clangTypeInfo; } constexpr bool hasSelfParam() const { switch (getRepresentation()) { @@ -608,6 +617,10 @@ class SILExtInfoBuilder { : (bits & ~NoEscapeMask), clangTypeInfo); } + SILExtInfoBuilder withAsync(bool isAsync = true) const { + return SILExtInfoBuilder(isAsync ? (bits | AsyncMask) : (bits & ~AsyncMask), + clangTypeInfo); + } SILExtInfoBuilder withDifferentiabilityKind(DifferentiabilityKind differentiability) const { return SILExtInfoBuilder( @@ -649,8 +662,8 @@ class SILExtInfo { static SILExtInfo getThin() { return SILExtInfoBuilder(SILExtInfoBuilder::Representation::Thin, false, - false, DifferentiabilityKind::NonDifferentiable, - nullptr) + false, false, + DifferentiabilityKind::NonDifferentiable, nullptr) .build(); } @@ -673,15 +686,15 @@ class SILExtInfo { constexpr bool isNoEscape() const { return builder.isNoEscape(); } + constexpr bool isAsync() const { return builder.isAsync(); } + constexpr DifferentiabilityKind getDifferentiabilityKind() const { return builder.getDifferentiabilityKind(); } constexpr bool isDifferentiable() const { return builder.isDifferentiable(); } - Optional getClangTypeInfo() const { - return builder.getClangTypeInfo(); - } + ClangTypeInfo getClangTypeInfo() const { return builder.getClangTypeInfo(); } constexpr bool hasSelfParam() const { return builder.hasSelfParam(); } diff --git a/include/swift/AST/ForeignAsyncConvention.h b/include/swift/AST/ForeignAsyncConvention.h new file mode 100644 index 0000000000000..f3657766e02af --- /dev/null +++ b/include/swift/AST/ForeignAsyncConvention.h @@ -0,0 +1,81 @@ +//===--- ForeignAsyncConvention.h - Async conventions -----------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This file defines the ForeignAsyncConvention structure, which +// describes the rules for how to detect that a foreign API is asynchronous. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_FOREIGN_ASYNC_CONVENTION_H +#define SWIFT_FOREIGN_ASYNC_CONVENTION_H + +#include "swift/AST/Type.h" + +namespace swift { + +/// A small structure describing the async convention of a foreign declaration. +class ForeignAsyncConvention { + /// The index of the completion handler parameters. + unsigned CompletionHandlerParamIndex; + + /// When non-zero, indicates which parameter to the completion handler is the + /// Error? parameter (minus one) that makes this async function also throwing. + unsigned CompletionHandlerErrorParamIndex; +public: + ForeignAsyncConvention() + : CompletionHandlerParamIndex(0), CompletionHandlerErrorParamIndex(0) { } + + ForeignAsyncConvention(unsigned completionHandlerParamIndex, + Optional completionHandlerErrorParamIndex) + : CompletionHandlerParamIndex(completionHandlerParamIndex), + CompletionHandlerErrorParamIndex( + completionHandlerErrorParamIndex + ? *completionHandlerErrorParamIndex + 1 + : 0) {} + + /// Retrieve the index of the completion handler parameter, which will be + /// erased from the Swift signature of the imported async function. + unsigned completionHandlerParamIndex() const { + return CompletionHandlerParamIndex; + } + + /// Retrieve the index of the \c Error? parameter in the completion handler's + /// parameter list. When argument passed to this parameter is non-null, the + /// provided error will be thrown by the async function. + Optional completionHandlerErrorParamIndex() const { + if (CompletionHandlerErrorParamIndex == 0) + return None; + + return CompletionHandlerErrorParamIndex - 1; + } + + /// Whether the async function is throwing due to the completion handler + /// having an \c Error? parameter. + /// + /// Equivalent to \c static_cast(completionHandlerErrorParamIndex()). + bool isThrowing() const { + return CompletionHandlerErrorParamIndex != 0; + } + + bool operator==(ForeignAsyncConvention other) const { + return CompletionHandlerParamIndex == other.CompletionHandlerParamIndex + && CompletionHandlerErrorParamIndex == + other.CompletionHandlerErrorParamIndex; + } + bool operator!=(ForeignAsyncConvention other) const { + return !(*this == other); + } +}; + +} + +#endif diff --git a/include/swift/AST/ForeignErrorConvention.h b/include/swift/AST/ForeignErrorConvention.h index 48d65d4612856..d09a7a80c0d86 100644 --- a/include/swift/AST/ForeignErrorConvention.h +++ b/include/swift/AST/ForeignErrorConvention.h @@ -81,6 +81,10 @@ class ForeignErrorConvention { } Info() = default; + + Kind getKind() const { + return static_cast(TheKind); + } }; private: @@ -178,11 +182,24 @@ class ForeignErrorConvention { /// Returns the physical result type of the function, for functions /// that completely erase this information. CanType getResultType() const { - assert(getKind() == ZeroResult || - getKind() == NonZeroResult); + assert(resultTypeErasedToVoid(getKind())); return ResultType; } - + + /// Whether this kind of error import erases the result type to 'Void'. + static bool resultTypeErasedToVoid(Kind kind) { + switch (kind) { + case ZeroResult: + case NonZeroResult: + return true; + + case ZeroPreservedResult: + case NilResult: + case NonNilError: + return false; + } + } + bool operator==(ForeignErrorConvention other) const { return info.TheKind == other.info.TheKind && info.ErrorIsOwned == other.info.ErrorIsOwned diff --git a/include/swift/AST/GenericEnvironment.h b/include/swift/AST/GenericEnvironment.h index 144ed20c6621e..a47067b940fa7 100644 --- a/include/swift/AST/GenericEnvironment.h +++ b/include/swift/AST/GenericEnvironment.h @@ -149,13 +149,6 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final std::pair mapConformanceRefIntoContext(Type conformingType, ProtocolConformanceRef conformance) const; - - /// Get the sugared form of a generic parameter type. - GenericTypeParamType *getSugaredType(GenericTypeParamType *type) const; - - /// Get the sugared form of a type by substituting any - /// generic parameter types by their sugared form. - Type getSugaredType(Type type) const; SubstitutionMap getForwardingSubstitutionMap() const; diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h index 6f840022dba9a..3a29d21fbd890 100644 --- a/include/swift/AST/GenericSignature.h +++ b/include/swift/AST/GenericSignature.h @@ -397,11 +397,18 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final /// /// then this will return 0 for t_0_0, 1 for t_0_1, and 2 for t_1_0. unsigned getGenericParamOrdinal(GenericTypeParamType *param) const; - + /// Get a substitution map that maps all of the generic signature's /// generic parameters to themselves. SubstitutionMap getIdentitySubstitutionMap() const; + /// Get the sugared form of a generic parameter type. + GenericTypeParamType *getSugaredType(GenericTypeParamType *type) const; + + /// Get the sugared form of a type by substituting any + /// generic parameter types by their sugared form. + Type getSugaredType(Type type) const; + /// Whether this generic signature involves a type variable. bool hasTypeVariable() const; diff --git a/include/swift/AST/KnownIdentifiers.def b/include/swift/AST/KnownIdentifiers.def index a9e0f46cb4783..37898169a6707 100644 --- a/include/swift/AST/KnownIdentifiers.def +++ b/include/swift/AST/KnownIdentifiers.def @@ -33,7 +33,6 @@ IDENTIFIER(atIndexedSubscript) IDENTIFIER_(bridgeToObjectiveC) IDENTIFIER(buildArray) IDENTIFIER(buildBlock) -IDENTIFIER(buildDo) IDENTIFIER(buildEither) IDENTIFIER(buildExpression) IDENTIFIER(buildFinalResult) diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index 0a1ff8f42ba2a..5a9334a41b8f0 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -685,6 +685,12 @@ class ModuleDecl : public DeclContext, public TypeDecl { void getImportedModulesForLookup(SmallVectorImpl &imports) const; + /// Has \p module been imported via an '@_implementationOnly' import + /// instead of another kind of import? + /// + /// This assumes that \p module was imported. + bool isImportedImplementationOnly(const ModuleDecl *module) const; + /// Uniques the items in \p imports, ignoring the source locations of the /// access paths. /// diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index 44cceb47af7ba..5eab3844b32d8 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -107,6 +107,9 @@ class SwiftModuleDependenciesStorage : public ModuleDependenciesStorageBase { /// The hash value that will be used for the generated module const std::string contextHash; + /// A flag that indicates this dependency is a framework + const bool isFramework; + /// Bridging header file, if there is one. Optional bridgingHeaderFile; @@ -125,7 +128,8 @@ class SwiftModuleDependenciesStorage : public ModuleDependenciesStorageBase { ArrayRef compiledModuleCandidates, ArrayRef buildCommandLine, ArrayRef extraPCMArgs, - StringRef contextHash + StringRef contextHash, + bool isFramework ) : ModuleDependenciesStorageBase(ModuleDependenciesKind::Swift, compiledModulePath), swiftInterfaceFile(swiftInterfaceFile), @@ -133,7 +137,7 @@ class SwiftModuleDependenciesStorage : public ModuleDependenciesStorageBase { compiledModuleCandidates.end()), buildCommandLine(buildCommandLine.begin(), buildCommandLine.end()), extraPCMArgs(extraPCMArgs.begin(), extraPCMArgs.end()), - contextHash(contextHash) { } + contextHash(contextHash), isFramework(isFramework) { } ModuleDependenciesStorageBase *clone() const override { return new SwiftModuleDependenciesStorage(*this); @@ -242,21 +246,22 @@ class ModuleDependencies { ArrayRef compiledCandidates, ArrayRef buildCommands, ArrayRef extraPCMArgs, - StringRef contextHash) { + StringRef contextHash, + bool isFramework) { std::string compiledModulePath; return ModuleDependencies( std::make_unique( compiledModulePath, swiftInterfaceFile, compiledCandidates, buildCommands, - extraPCMArgs, contextHash)); + extraPCMArgs, contextHash, isFramework)); } /// Describe the module dependencies for a serialized or parsed Swift module. static ModuleDependencies forSwiftModule( - const std::string &compiledModulePath) { + const std::string &compiledModulePath, bool isFramework) { return ModuleDependencies( std::make_unique( compiledModulePath, None, ArrayRef(), ArrayRef(), - ArrayRef(), StringRef())); + ArrayRef(), StringRef(), isFramework)); } /// Describe the main Swift module. @@ -265,7 +270,7 @@ class ModuleDependencies { return ModuleDependencies( std::make_unique( compiledModulePath, None, ArrayRef(), - ArrayRef(), extraPCMArgs, StringRef())); + ArrayRef(), extraPCMArgs, StringRef(), false)); } /// Describe the module dependencies for a Clang module that can be diff --git a/include/swift/AST/ModuleLoader.h b/include/swift/AST/ModuleLoader.h index 1460daf9f44c1..3660f00461f94 100644 --- a/include/swift/AST/ModuleLoader.h +++ b/include/swift/AST/ModuleLoader.h @@ -24,6 +24,7 @@ #include "llvm/ADT/SetVector.h" #include "llvm/ADT/TinyPtrVector.h" #include "swift/AST/ModuleDependencies.h" +#include namespace llvm { class FileCollector; @@ -103,17 +104,18 @@ struct SubCompilerInstanceInfo { /// Abstract interface to run an action in a sub ASTContext. struct InterfaceSubContextDelegate { - virtual bool runInSubContext(StringRef moduleName, - StringRef interfacePath, - StringRef outputPath, - SourceLoc diagLoc, - llvm::function_ref, - ArrayRef, StringRef)> action) = 0; - virtual bool runInSubCompilerInstance(StringRef moduleName, - StringRef interfacePath, - StringRef outputPath, - SourceLoc diagLoc, - llvm::function_ref action) = 0; + virtual std::error_code runInSubContext(StringRef moduleName, + StringRef interfacePath, + StringRef outputPath, + SourceLoc diagLoc, + llvm::function_ref, + ArrayRef, StringRef)> action) = 0; + virtual std::error_code runInSubCompilerInstance(StringRef moduleName, + StringRef interfacePath, + StringRef outputPath, + SourceLoc diagLoc, + llvm::function_ref action) = 0; virtual ~InterfaceSubContextDelegate() = default; }; diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h index ea847ce01c1ba..3411da322aa83 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -375,7 +375,7 @@ class LambdaDeclConsumer : public VisibleDeclConsumer { public: LambdaDeclConsumer(Fn &&callback) : Callback(std::move(callback)) {} - void foundDecl(ValueDecl *VD, DeclVisibilityKind reason, DynamicLookupInfo) { + void foundDecl(ValueDecl *VD, DeclVisibilityKind reason, DynamicLookupInfo) override { Callback(VD, reason); } }; @@ -741,8 +741,6 @@ class ASTScope { return Mem; } - static bool areInactiveIfConfigClausesSupported(); - private: static ast_scope::ASTSourceFileScope *createScopeTree(SourceFile *); diff --git a/include/swift/AST/Pattern.h b/include/swift/AST/Pattern.h index 6424dd12a72f2..13630507bb3a5 100644 --- a/include/swift/AST/Pattern.h +++ b/include/swift/AST/Pattern.h @@ -554,6 +554,9 @@ class EnumElementPattern : public Pattern { bool hasUnresolvedOriginalExpr() const { return ElementDeclOrUnresolvedOriginalExpr.is(); } + void setUnresolvedOriginalExpr(Expr *e) { + ElementDeclOrUnresolvedOriginalExpr = e; + } DeclNameLoc getNameLoc() const { return NameLoc; } SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); } diff --git a/include/swift/AST/PrettyStackTrace.h b/include/swift/AST/PrettyStackTrace.h index 51d047ecbb1b5..e08b7bb9aa9d8 100644 --- a/include/swift/AST/PrettyStackTrace.h +++ b/include/swift/AST/PrettyStackTrace.h @@ -51,7 +51,7 @@ class PrettyStackTraceLocation : public llvm::PrettyStackTraceEntry { PrettyStackTraceLocation(const ASTContext &C, const char *action, SourceLoc loc) : Context(C), Loc(loc), Action(action) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; void printDeclDescription(llvm::raw_ostream &out, const Decl *D, @@ -65,7 +65,7 @@ class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry { public: PrettyStackTraceDecl(const char *action, const Decl *D) : TheDecl(D), Action(action) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; /// PrettyStackTraceAnyFunctionRef - Observe that we are processing a specific @@ -76,7 +76,7 @@ class PrettyStackTraceAnyFunctionRef : public llvm::PrettyStackTraceEntry { public: PrettyStackTraceAnyFunctionRef(const char *action, AnyFunctionRef ref) : TheRef(ref), Action(action) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; void printExprDescription(llvm::raw_ostream &out, Expr *E, @@ -91,7 +91,7 @@ class PrettyStackTraceExpr : public llvm::PrettyStackTraceEntry { public: PrettyStackTraceExpr(const ASTContext &C, const char *action, Expr *E) : Context(C), TheExpr(E), Action(action) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; void printStmtDescription(llvm::raw_ostream &out, Stmt *S, @@ -106,7 +106,7 @@ class PrettyStackTraceStmt : public llvm::PrettyStackTraceEntry { public: PrettyStackTraceStmt(const ASTContext &C, const char *action, Stmt *S) : Context(C), TheStmt(S), Action(action) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; void printPatternDescription(llvm::raw_ostream &out, Pattern *P, @@ -121,7 +121,7 @@ class PrettyStackTracePattern : public llvm::PrettyStackTraceEntry { public: PrettyStackTracePattern(const ASTContext &C, const char *action, Pattern *P) : Context(C), ThePattern(P), Action(action) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; void printTypeDescription(llvm::raw_ostream &out, Type T, @@ -135,7 +135,7 @@ class PrettyStackTraceType : public llvm::PrettyStackTraceEntry { public: PrettyStackTraceType(const ASTContext &C, const char *action, Type type) : Context(C), TheType(type), Action(action) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; /// PrettyStackTraceClangType - Observe that we are processing a @@ -146,7 +146,7 @@ class PrettyStackTraceClangType : public llvm::PrettyStackTraceEntry { public: PrettyStackTraceClangType(const char *action, const clang::Type *type) : TheType(type), Action(action) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; /// Observe that we are processing a specific type representation. @@ -158,7 +158,7 @@ class PrettyStackTraceTypeRepr : public llvm::PrettyStackTraceEntry { PrettyStackTraceTypeRepr(const ASTContext &C, const char *action, TypeRepr *type) : Context(C), TheType(type), Action(action) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; /// PrettyStackTraceConformance - Observe that we are processing a @@ -171,7 +171,7 @@ class PrettyStackTraceConformance : public llvm::PrettyStackTraceEntry { PrettyStackTraceConformance(const ASTContext &C, const char *action, const ProtocolConformance *conformance) : Context(C), Conformance(conformance), Action(action) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; void printConformanceDescription(llvm::raw_ostream &out, @@ -217,7 +217,7 @@ class PrettyStackTraceDifferentiabilityWitness PrettyStackTraceDifferentiabilityWitness( const char *action, const SILDifferentiabilityWitnessKey key) : Key(key), Action(action) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; void printDifferentiabilityWitnessDescription( @@ -232,7 +232,7 @@ class PrettyStackTraceDeclContext : public llvm::PrettyStackTraceEntry { public: PrettyStackTraceDeclContext(const char *action, const DeclContext *DC) : DC(DC), Action(action) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; } // end namespace swift diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h index 38611e1245b56..abfebaf3ffb48 100644 --- a/include/swift/AST/PrintOptions.h +++ b/include/swift/AST/PrintOptions.h @@ -24,7 +24,7 @@ namespace swift { class ASTPrinter; -class GenericEnvironment; +class GenericSignatureImpl; class CanType; class Decl; class Pattern; @@ -423,8 +423,8 @@ struct PrintOptions { /// Replaces the name of private and internal properties of types with '_'. bool OmitNameOfInaccessibleProperties = false; - /// Print dependent types as references into this generic environment. - GenericEnvironment *GenericEnv = nullptr; + /// Use this signature to re-sugar dependent types. + const GenericSignatureImpl *GenericSig = nullptr; /// Print types with alternative names from their canonical names. llvm::DenseMap *AlternativeTypeNames = nullptr; diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h index 1136fb5be73cd..1f61cdf438175 100644 --- a/include/swift/AST/ProtocolConformance.h +++ b/include/swift/AST/ProtocolConformance.h @@ -465,21 +465,22 @@ class NormalProtocolConformance : public RootProtocolConformance, uint64_t LoaderContextData; friend class ASTContext; + void resolveLazyInfo() const; + + void differenceAndStoreConditionalRequirements() const; + +public: NormalProtocolConformance(Type conformingType, ProtocolDecl *protocol, SourceLoc loc, DeclContext *dc, ProtocolConformanceState state) - : RootProtocolConformance(ProtocolConformanceKind::Normal, conformingType), - ProtocolAndState(protocol, state), Loc(loc), ContextAndInvalid(dc, false) - { + : RootProtocolConformance(ProtocolConformanceKind::Normal, + conformingType), + ProtocolAndState(protocol, state), Loc(loc), + ContextAndInvalid(dc, false) { assert(!conformingType->hasArchetype() && "ProtocolConformances should store interface types"); } - void resolveLazyInfo() const; - - void differenceAndStoreConditionalRequirements() const; - -public: /// Get the protocol being conformed to. ProtocolDecl *getProtocol() const { return ProtocolAndState.getPointer(); } diff --git a/include/swift/AST/SearchPathOptions.h b/include/swift/AST/SearchPathOptions.h index 08757ffd796de..52eeace6a1460 100644 --- a/include/swift/AST/SearchPathOptions.h +++ b/include/swift/AST/SearchPathOptions.h @@ -93,6 +93,9 @@ class SearchPathOptions { /// A map of placeholder Swift module dependency information. std::string PlaceholderDependencyModuleMap; + + /// A file containing modules we should perform batch scanning. + std::string BatchScanInputFilePath; private: static StringRef pathStringFromFrameworkSearchPath(const FrameworkSearchPath &next) { diff --git a/include/swift/AST/SourceFile.h b/include/swift/AST/SourceFile.h index ca305f8675db8..96c25e4ab5ae1 100644 --- a/include/swift/AST/SourceFile.h +++ b/include/swift/AST/SourceFile.h @@ -172,7 +172,7 @@ class SourceFile final : public FileUnit { bool IsPrimary; /// The scope map that describes this source file. - std::unique_ptr Scope; + NullablePtr Scope = nullptr; /// The set of validated opaque return type decls in the source file. llvm::SmallVector OpaqueReturnTypes; @@ -468,6 +468,10 @@ class SourceFile final : public FileUnit { /// Retrieve the scope that describes this source file. ASTScope &getScope(); + void clearScope() { + Scope = nullptr; + } + /// Retrieves the previously set delayed parser state, asserting that it /// exists. PersistentParserState *getDelayedParserState() { diff --git a/include/swift/AST/TBDGenRequests.h b/include/swift/AST/TBDGenRequests.h index 66ac0ef814e04..413f79b326568 100644 --- a/include/swift/AST/TBDGenRequests.h +++ b/include/swift/AST/TBDGenRequests.h @@ -19,6 +19,9 @@ #include "swift/AST/ASTTypeIDs.h" #include "swift/AST/SimpleRequest.h" +#include "swift/IRGen/Linking.h" +#include "swift/SIL/SILDeclRef.h" +#include "swift/TBDGen/TBDGen.h" namespace llvm { @@ -37,12 +40,11 @@ namespace swift { class FileUnit; class ModuleDecl; -struct TBDGenOptions; class TBDGenDescriptor final { using FileOrModule = llvm::PointerUnion; FileOrModule Input; - const TBDGenOptions &Opts; + TBDGenOptions Opts; TBDGenDescriptor(FileOrModule input, const TBDGenOptions &opts) : Input(input), Opts(opts) { @@ -62,6 +64,7 @@ class TBDGenDescriptor final { /// Returns the TBDGen options. const TBDGenOptions &getOptions() const { return Opts; } + TBDGenOptions &getOptions() { return Opts; } const llvm::DataLayout &getDataLayout() const; const llvm::Triple &getTarget() const; @@ -117,6 +120,123 @@ class PublicSymbolsRequest evaluate(Evaluator &evaluator, TBDGenDescriptor desc) const; }; +/// Describes the origin of a particular symbol, including the stage of +/// compilation it is introduced, as well as information on what decl introduces +/// it. +class SymbolSource { +public: + enum class Kind { + /// A symbol introduced when emitting a SIL decl. + SIL, + + /// A symbol introduced when emitting LLVM IR. + IR, + + /// A symbol used to customize linker behavior, introduced by TBDGen. + LinkerDirective, + + /// A symbol with an unknown origin. + // FIXME: This should be eliminated. + Unknown + }; + Kind kind; + +private: + union { + SILDeclRef silDeclRef; + irgen::LinkEntity irEntity; + }; + + explicit SymbolSource(SILDeclRef ref) : kind(Kind::SIL) { + silDeclRef = ref; + } + explicit SymbolSource(irgen::LinkEntity entity) : kind(Kind::IR) { + irEntity = entity; + } + explicit SymbolSource(Kind kind) : kind(kind) { + assert(kind == Kind::LinkerDirective || kind == Kind::Unknown); + } + +public: + static SymbolSource forSILDeclRef(SILDeclRef ref) { + return SymbolSource{ref}; + } + static SymbolSource forIRLinkEntity(irgen::LinkEntity entity) { + return SymbolSource{entity}; + } + static SymbolSource forLinkerDirective() { + return SymbolSource{Kind::LinkerDirective}; + } + static SymbolSource forUnknown() { + return SymbolSource{Kind::Unknown}; + } + + bool isLinkerDirective() const { + return kind == Kind::LinkerDirective; + } + + SILDeclRef getSILDeclRef() const { + assert(kind == Kind::SIL); + return silDeclRef; + } + irgen::LinkEntity getIRLinkEntity() const { + assert(kind == Kind::IR); + return irEntity; + } +}; + +/// Maps a symbol back to its source for lazy compilation. +class SymbolSourceMap { + friend class SymbolSourceMapRequest; + + using Storage = llvm::StringMap; + const Storage *storage; + + explicit SymbolSourceMap(const Storage *storage) : storage(storage) { + assert(storage); + } + +public: + Optional find(StringRef symbol) const { + auto result = storage->find(symbol); + if (result == storage->end()) + return None; + return result->second; + } + + friend bool operator==(const SymbolSourceMap &lhs, + const SymbolSourceMap &rhs) { + return lhs.storage == rhs.storage; + } + friend bool operator!=(const SymbolSourceMap &lhs, + const SymbolSourceMap &rhs) { + return !(lhs == rhs); + } + + friend void simple_display(llvm::raw_ostream &out, const SymbolSourceMap &) { + out << "(symbol storage map)"; + } +}; + +/// Computes a map of symbols to their SymbolSource for a file or module. +class SymbolSourceMapRequest + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + // Evaluation. + SymbolSourceMap evaluate(Evaluator &evaluator, TBDGenDescriptor desc) const; + +public: + // Cached. + bool isCached() const { return true; } +}; + /// Report that a request of the given kind is being evaluated, so it /// can be recorded by the stats reporter. template diff --git a/include/swift/AST/TBDGenTypeIDZone.def b/include/swift/AST/TBDGenTypeIDZone.def index b175b8ac19bd3..71eb7ad25a68a 100644 --- a/include/swift/AST/TBDGenTypeIDZone.def +++ b/include/swift/AST/TBDGenTypeIDZone.def @@ -19,3 +19,6 @@ SWIFT_REQUEST(TBDGen, GenerateTBDRequest, TBDFile(TBDGenDescriptor), SWIFT_REQUEST(TBDGen, PublicSymbolsRequest, std::vector(TBDGenDescriptor), Uncached, NoLocationInfo) +SWIFT_REQUEST(TBDGen, SymbolSourceMapRequest, + SymbolSourceMap(TBDGenDescriptor), + Cached, NoLocationInfo) diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index f067218db105e..c73b37dd18e2b 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -781,6 +781,24 @@ class SelfAccessKindRequest : void cacheResult(SelfAccessKind value) const; }; +/// Determine whether the given function is an @asyncHandler. +class IsAsyncHandlerRequest : + public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + bool evaluate(Evaluator &evaluator, FuncDecl *func) const; + +public: + // Caching + bool isCached() const { return true; } +}; + /// Request whether the storage has a mutating getter. class IsGetterMutatingRequest : public SimpleRequest getYields() const { return const_cast(this)->getMutableYields(); @@ -5724,6 +5731,31 @@ TypeVariableType : public TypeBase { }; DEFINE_EMPTY_CAN_TYPE_WRAPPER(TypeVariableType, Type) +/// HoleType - This represents a placeholder type for a type variable +/// or dependent member type that cannot be resolved to a concrete type +/// because the expression is ambiguous. This type is only used by the +/// constraint solver and transformed into UnresolvedType to be used in AST. +class HoleType : public TypeBase { + using OriginatorType = + llvm::PointerUnion; + + OriginatorType Originator; + + HoleType(ASTContext &C, OriginatorType originator, + RecursiveTypeProperties properties) + : TypeBase(TypeKind::Hole, &C, properties), Originator(originator) {} + +public: + static Type get(ASTContext &ctx, OriginatorType originatorType); + + OriginatorType getOriginatorType() const { return Originator; } + + static bool classof(const TypeBase *T) { + return T->getKind() == TypeKind::Hole; + } +}; +DEFINE_EMPTY_CAN_TYPE_WRAPPER(HoleType, Type) + inline bool TypeBase::isTypeVariableOrMember() { if (is()) return true; diff --git a/include/swift/Basic/Lazy.h b/include/swift/Basic/Lazy.h index 521227f4db231..87eecbe295c3c 100644 --- a/include/swift/Basic/Lazy.h +++ b/include/swift/Basic/Lazy.h @@ -14,7 +14,9 @@ #define SWIFT_BASIC_LAZY_H #include -#ifdef __APPLE__ +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME +// No dependencies on single-threaded environments. +#elif defined(__APPLE__) #include #elif defined(__wasi__) // No pthread on wasi, see https://bugs.swift.org/browse/SR-12097 for more details. @@ -44,7 +46,11 @@ inline void wasi_call_once(int *flag, void *context, void (*func)(void *)) { namespace swift { -#ifdef __APPLE__ +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + using OnceToken_t = bool; +# define SWIFT_ONCE_F(TOKEN, FUNC, CONTEXT) \ + if (!TOKEN) { TOKEN = true; (FUNC)(CONTEXT); } +#elif defined(__APPLE__) using OnceToken_t = dispatch_once_t; # define SWIFT_ONCE_F(TOKEN, FUNC, CONTEXT) \ ::dispatch_once_f(&TOKEN, CONTEXT, FUNC) diff --git a/include/swift/Basic/SourceManager.h b/include/swift/Basic/SourceManager.h index e26e44e78cef9..a12aa169f7c51 100644 --- a/include/swift/Basic/SourceManager.h +++ b/include/swift/Basic/SourceManager.h @@ -38,6 +38,20 @@ class SourceManager { /// to speed up stats. mutable llvm::DenseMap StatusCache; + struct ReplacedRangeType { + SourceRange Original; + SourceRange New; + ReplacedRangeType() {} + ReplacedRangeType(NoneType) {} + ReplacedRangeType(SourceRange Original, SourceRange New) + : Original(Original), New(New) { + assert(Original.isValid() && New.isValid()); + } + + explicit operator bool() const { return Original.isValid(); } + }; + ReplacedRangeType ReplacedRange; + // \c #sourceLocation directive handling. struct VirtualFile { CharSourceRange Range; @@ -89,6 +103,9 @@ class SourceManager { SourceLoc getCodeCompletionLoc() const; + const ReplacedRangeType &getReplacedRange() const { return ReplacedRange; } + void setReplacedRange(const ReplacedRangeType &val) { ReplacedRange = val; } + /// Returns true if \c LHS is before \c RHS in the source buffer. bool isBeforeInBuffer(SourceLoc LHS, SourceLoc RHS) const { return LHS.Value.getPointer() < RHS.Value.getPointer(); diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def index 468a0711f90f4..1c3c612f9e98a 100644 --- a/include/swift/Demangling/DemangleNodes.def +++ b/include/swift/Demangling/DemangleNodes.def @@ -294,6 +294,9 @@ NODE(CanonicalSpecializedGenericTypeMetadataAccessFunction) NODE(MetadataInstantiationCache) NODE(NoncanonicalSpecializedGenericTypeMetadata) NODE(NoncanonicalSpecializedGenericTypeMetadataCache) +NODE(GlobalVariableOnceFunction) +NODE(GlobalVariableOnceToken) +NODE(GlobalVariableOnceDeclList) #undef CONTEXT_NODE #undef NODE diff --git a/include/swift/Demangling/TypeDecoder.h b/include/swift/Demangling/TypeDecoder.h index e591e978dccd1..074e4aa26027d 100644 --- a/include/swift/Demangling/TypeDecoder.h +++ b/include/swift/Demangling/TypeDecoder.h @@ -18,10 +18,12 @@ #ifndef SWIFT_DEMANGLING_TYPEDECODER_H #define SWIFT_DEMANGLING_TYPEDECODER_H +#include "TypeLookupError.h" #include "swift/ABI/MetadataValues.h" +#include "swift/Basic/LLVM.h" #include "swift/Demangling/Demangler.h" #include "swift/Demangling/NamespaceMacros.h" -#include "swift/Basic/LLVM.h" +#include "swift/Runtime/Portability.h" #include "swift/Runtime/Unreachable.h" #include "swift/Strings.h" #include "llvm/ADT/ArrayRef.h" @@ -238,49 +240,60 @@ class ImplFunctionTypeFlags { unsigned Rep : 3; unsigned Pseudogeneric : 1; unsigned Escaping : 1; + unsigned Async : 1; unsigned DifferentiabilityKind : 2; public: ImplFunctionTypeFlags() - : Rep(0), Pseudogeneric(0), Escaping(0), DifferentiabilityKind(0) {} + : Rep(0), Pseudogeneric(0), Escaping(0), Async(0), + DifferentiabilityKind(0) {} ImplFunctionTypeFlags(ImplFunctionRepresentation rep, bool pseudogeneric, - bool noescape, + bool noescape, bool async, ImplFunctionDifferentiabilityKind diffKind) : Rep(unsigned(rep)), Pseudogeneric(pseudogeneric), Escaping(noescape), - DifferentiabilityKind(unsigned(diffKind)) {} + Async(async), DifferentiabilityKind(unsigned(diffKind)) {} ImplFunctionTypeFlags withRepresentation(ImplFunctionRepresentation rep) const { return ImplFunctionTypeFlags( - rep, Pseudogeneric, Escaping, + rep, Pseudogeneric, Escaping, Async, + ImplFunctionDifferentiabilityKind(DifferentiabilityKind)); + } + + ImplFunctionTypeFlags + withAsync() const { + return ImplFunctionTypeFlags( + ImplFunctionRepresentation(Rep), Pseudogeneric, Escaping, true, ImplFunctionDifferentiabilityKind(DifferentiabilityKind)); } ImplFunctionTypeFlags withEscaping() const { return ImplFunctionTypeFlags( - ImplFunctionRepresentation(Rep), Pseudogeneric, true, + ImplFunctionRepresentation(Rep), Pseudogeneric, true, Async, ImplFunctionDifferentiabilityKind(DifferentiabilityKind)); } ImplFunctionTypeFlags withPseudogeneric() const { return ImplFunctionTypeFlags( - ImplFunctionRepresentation(Rep), true, Escaping, + ImplFunctionRepresentation(Rep), true, Escaping, Async, ImplFunctionDifferentiabilityKind(DifferentiabilityKind)); } ImplFunctionTypeFlags withDifferentiabilityKind(ImplFunctionDifferentiabilityKind diffKind) const { return ImplFunctionTypeFlags(ImplFunctionRepresentation(Rep), Pseudogeneric, - Escaping, diffKind); + Escaping, Async, diffKind); } ImplFunctionRepresentation getRepresentation() const { return ImplFunctionRepresentation(Rep); } + bool isAsync() const { return Async; } + bool isEscaping() const { return Escaping; } bool isPseudogeneric() const { return Pseudogeneric; } @@ -317,6 +330,14 @@ getObjCClassOrProtocolName(NodePointer node) { } #endif +#define MAKE_NODE_TYPE_ERROR(Node, Fmt, ...) \ + TypeLookupError("TypeDecoder.h:%d: Node kind %u \"%.*s\" - " Fmt, __LINE__, \ + Node->getKind(), \ + Node->hasText() ? (int)Node->getText().size() : 0, \ + Node->hasText() ? Node->getText().data() : "", __VA_ARGS__) + +#define MAKE_NODE_TYPE_ERROR0(Node, Str) MAKE_NODE_TYPE_ERROR(Node, "%s", Str) + /// Decode a mangled type to construct an abstract type, forming such /// types by invoking a custom builder. template @@ -333,24 +354,25 @@ class TypeDecoder { : Builder(Builder) {} /// Given a demangle tree, attempt to turn it into a type. - BuiltType decodeMangledType(NodePointer Node) { - if (!Node) return BuiltType(); + TypeLookupErrorOr decodeMangledType(NodePointer Node) { + if (!Node) + return TypeLookupError("Node is NULL"); using NodeKind = Demangle::Node::Kind; switch (Node->getKind()) { case NodeKind::Global: if (Node->getNumChildren() < 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children."); return decodeMangledType(Node->getChild(0)); case NodeKind::TypeMangling: if (Node->getNumChildren() < 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children."); return decodeMangledType(Node->getChild(0)); case NodeKind::Type: if (Node->getNumChildren() < 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children."); return decodeMangledType(Node->getChild(0)); case NodeKind::Class: @@ -369,8 +391,8 @@ class TypeDecoder { BuiltTypeDecl typeDecl = BuiltTypeDecl(); BuiltType parent = BuiltType(); bool typeAlias = false; - if (!decodeMangledTypeDecl(Node, typeDecl, parent, typeAlias)) - return BuiltType(); + if (auto error = decodeMangledTypeDecl(Node, typeDecl, parent, typeAlias)) + return *error; if (typeAlias) return Builder.createTypeAliasType(typeDecl, parent); @@ -384,19 +406,21 @@ class TypeDecoder { case NodeKind::BoundGenericTypeAlias: case NodeKind::BoundGenericOtherNominalType: { if (Node->getNumChildren() < 2) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR(Node, + "fewer children (%u) than required (2)", + Node->getNumChildren()); llvm::SmallVector args; const auto &genericArgs = Node->getChild(1); if (genericArgs->getKind() != NodeKind::TypeList) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(genericArgs, "is not TypeList"); for (auto genericArg : *genericArgs) { auto paramType = decodeMangledType(genericArg); - if (!paramType) - return BuiltType(); - args.push_back(paramType); + if (paramType.isError()) + return paramType; + args.push_back(paramType.getType()); } auto ChildNode = Node->getChild(0); @@ -413,9 +437,9 @@ class TypeDecoder { BuiltTypeDecl typeDecl = BuiltTypeDecl(); BuiltType parent = BuiltType(); bool typeAlias = false; - if (!decodeMangledTypeDecl(ChildNode, typeDecl, - parent, typeAlias)) - return BuiltType(); + if (auto error = + decodeMangledTypeDecl(ChildNode, typeDecl, parent, typeAlias)) + return *error; return Builder.createBoundGenericType(typeDecl, args, parent); } @@ -445,11 +469,15 @@ class TypeDecoder { // But when resolving it to a type, we want to *keep* the argument // so that the parent type becomes 'S' and not 'P'. if (Node->getNumChildren() < 2) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR(Node, + "fewer children (%u) than required (2)", + Node->getNumChildren()); const auto &genericArgs = Node->getChild(1); if (genericArgs->getNumChildren() != 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR(genericArgs, + "expected 1 generic argument, saw %u", + genericArgs->getNumChildren()); return decodeMangledType(genericArgs->getChild(0)); } @@ -469,7 +497,7 @@ class TypeDecoder { auto reprNode = Node->getChild(i++); if (reprNode->getKind() != NodeKind::MetatypeRepresentation || !reprNode->hasText()) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(reprNode, "wrong node kind or no text"); if (reprNode->getText() == "@thin") repr = ImplMetatypeRepresentation::Thin; else if (reprNode->getText() == "@thick") @@ -477,26 +505,28 @@ class TypeDecoder { else if (reprNode->getText() == "@objc_metatype") repr = ImplMetatypeRepresentation::ObjC; } else if (Node->getNumChildren() < 1) { - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children"); } auto instance = decodeMangledType(Node->getChild(i)); - if (!instance) - return BuiltType(); + if (instance.isError()) + return instance; if (Node->getKind() == NodeKind::Metatype) { - return Builder.createMetatypeType(instance, repr); + return Builder.createMetatypeType(instance.getType(), repr); } else if (Node->getKind() == NodeKind::ExistentialMetatype) { - return Builder.createExistentialMetatypeType(instance, repr); + return Builder.createExistentialMetatypeType(instance.getType(), repr); } else { assert(false); - return nullptr; + return MAKE_NODE_TYPE_ERROR0(Node, + "Metatype/ExistentialMetatype Node " + "had a different kind when re-checked"); } } case NodeKind::ProtocolList: case NodeKind::ProtocolListWithAnyObject: case NodeKind::ProtocolListWithClass: { if (Node->getNumChildren() < 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children"); // Find the protocol list. llvm::SmallVector Protocols; @@ -511,7 +541,8 @@ class TypeDecoder { if (auto Protocol = decodeMangledProtocolType(componentType)) Protocols.push_back(Protocol); else - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(componentType, + "failed to decode protocol type"); } // Superclass or AnyObject, if present. @@ -519,11 +550,15 @@ class TypeDecoder { auto Superclass = BuiltType(); if (Node->getKind() == NodeKind::ProtocolListWithClass) { if (Node->getNumChildren() < 2) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR(Node, + "fewer children (%u) than required (2)", + Node->getNumChildren()); auto superclassNode = Node->getChild(1); - Superclass = decodeMangledType(superclassNode); - if (!Superclass) return BuiltType(); + auto result = decodeMangledType(superclassNode); + if (result.isError()) + return result; + Superclass = result.getType(); IsClassBound = true; } else if (Node->getKind() == NodeKind::ProtocolListWithAnyObject) { @@ -541,17 +576,18 @@ class TypeDecoder { /*IsClassBound=*/false); } - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "failed to decode protocol type"); } case NodeKind::DynamicSelf: { if (Node->getNumChildren() != 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR(Node, "expected 1 child, saw %u", + Node->getNumChildren()); auto selfType = decodeMangledType(Node->getChild(0)); - if (!selfType) - return BuiltType(); + if (selfType.isError()) + return selfType; - return Builder.createDynamicSelfType(selfType); + return Builder.createDynamicSelfType(selfType.getType()); } case NodeKind::DependentGenericParamType: { auto depth = Node->getChild(0)->getIndex(); @@ -571,7 +607,9 @@ class TypeDecoder { case NodeKind::EscapingLinearFunctionType: case NodeKind::FunctionType: { if (Node->getNumChildren() < 2) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR(Node, + "fewer children (%u) than required (2)", + Node->getNumChildren()); FunctionTypeFlags flags; if (Node->getKind() == NodeKind::ObjCBlock || @@ -611,13 +649,16 @@ class TypeDecoder { flags = flags.withAsync(isAsync).withThrows(isThrow); if (Node->getNumChildren() < firstChildIdx + 2) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR(Node, + "fewer children (%u) than required (%u)", + Node->getNumChildren(), firstChildIdx + 2); bool hasParamFlags = false; llvm::SmallVector, 8> parameters; if (!decodeMangledFunctionInputType(Node->getChild(firstChildIdx), parameters, hasParamFlags)) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node->getChild(firstChildIdx), + "failed to decode function type"); flags = flags.withNumParameters(parameters.size()) .withParameterFlags(hasParamFlags) @@ -631,8 +672,9 @@ class TypeDecoder { NodeKind::EscapingLinearFunctionType); auto result = decodeMangledType(Node->getChild(firstChildIdx+1)); - if (!result) return BuiltType(); - return Builder.createFunctionType(parameters, result, flags); + if (result.isError()) + return result; + return Builder.createFunctionType(parameters, result.getType(), flags); } case NodeKind::ImplFunctionType: { auto calleeConvention = ImplParameterConvention::Direct_Unowned; @@ -646,7 +688,7 @@ class TypeDecoder { if (child->getKind() == NodeKind::ImplConvention) { if (!child->hasText()) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(child, "expected text"); if (child->getText() == "@convention(thin)") { flags = @@ -656,7 +698,7 @@ class TypeDecoder { } } else if (child->getKind() == NodeKind::ImplFunctionAttribute) { if (!child->hasText()) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(child, "expected text"); StringRef text = child->getText(); if (text == "@convention(c)") { @@ -676,15 +718,18 @@ class TypeDecoder { flags = flags.withEscaping(); } else if (child->getKind() == NodeKind::ImplParameter) { if (decodeImplFunctionParam(child, parameters)) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(child, + "failed to decode function parameter"); } else if (child->getKind() == NodeKind::ImplResult) { if (decodeImplFunctionParam(child, results)) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(child, + "failed to decode function parameter"); } else if (child->getKind() == NodeKind::ImplErrorResult) { if (decodeImplFunctionPart(child, errorResults)) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(child, + "failed to decode function part"); } else { - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(child, "unexpected kind"); } } @@ -696,7 +741,8 @@ class TypeDecoder { errorResult = errorResults.front(); break; default: - return BuiltType(); + return MAKE_NODE_TYPE_ERROR(Node, "got %zu errors", + errorResults.size()); } // TODO: Some cases not handled above, but *probably* they cannot @@ -711,13 +757,13 @@ class TypeDecoder { case NodeKind::ArgumentTuple: if (Node->getNumChildren() < 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children"); return decodeMangledType(Node->getChild(0)); case NodeKind::ReturnType: if (Node->getNumChildren() < 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children"); return decodeMangledType(Node->getChild(0)); @@ -726,12 +772,13 @@ class TypeDecoder { std::string labels; for (auto &element : *Node) { if (element->getKind() != NodeKind::TupleElement) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "unexpected kind"); // If the tuple element is labeled, add its label to 'labels'. unsigned typeChildIndex = 0; if (element->getChild(typeChildIndex)->getKind() == NodeKind::VariadicMarker) { - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(element->getChild(typeChildIndex), + "no children"); } if (element->getChild(typeChildIndex)->getKind() == NodeKind::TupleElementName) { // Add spaces to terminate all the previous labels if this @@ -749,22 +796,23 @@ class TypeDecoder { } // Decode the element type. - BuiltType elementType = - decodeMangledType(element->getChild(typeChildIndex)); - if (!elementType) - return BuiltType(); + auto elementType = decodeMangledType(element->getChild(typeChildIndex)); + if (elementType.isError()) + return elementType; - elements.push_back(elementType); + elements.push_back(elementType.getType()); } return Builder.createTupleType(elements, std::move(labels)); } case NodeKind::TupleElement: if (Node->getNumChildren() < 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children"); if (Node->getChild(0)->getKind() == NodeKind::TupleElementName) { if (Node->getNumChildren() < 2) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR(Node, + "fewer children (%u) than required (2)", + Node->getNumChildren()); return decodeMangledType(Node->getChild(1)); } @@ -772,68 +820,75 @@ class TypeDecoder { case NodeKind::DependentGenericType: { if (Node->getNumChildren() < 2) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR(Node, + "fewer children (%u) than required (2)", + Node->getNumChildren()); return decodeMangledType(Node->getChild(1)); } case NodeKind::DependentMemberType: { if (Node->getNumChildren() < 2) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR(Node, + "fewer children (%u) than required (2)", + Node->getNumChildren()); auto base = decodeMangledType(Node->getChild(0)); - if (!base) - return BuiltType(); + if (base.isError()) + return base; auto assocTypeChild = Node->getChild(1); auto member = assocTypeChild->getFirstChild()->getText(); if (assocTypeChild->getNumChildren() < 2) - return Builder.createDependentMemberType(member.str(), base); + return Builder.createDependentMemberType(member.str(), base.getType()); auto protocol = decodeMangledProtocolType(assocTypeChild->getChild(1)); if (!protocol) return BuiltType(); - return Builder.createDependentMemberType(member.str(), base, protocol); + return Builder.createDependentMemberType(member.str(), base.getType(), + protocol); } case NodeKind::DependentAssociatedTypeRef: { if (Node->getNumChildren() < 2) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR(Node, + "fewer children (%u) than required (2)", + Node->getNumChildren()); return decodeMangledType(Node->getChild(1)); } case NodeKind::Unowned: { if (Node->getNumChildren() < 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children"); auto base = decodeMangledType(Node->getChild(0)); - if (!base) - return BuiltType(); - return Builder.createUnownedStorageType(base); + if (base.isError()) + return base; + return Builder.createUnownedStorageType(base.getType()); } case NodeKind::Unmanaged: { if (Node->getNumChildren() < 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children"); auto base = decodeMangledType(Node->getChild(0)); - if (!base) - return BuiltType(); - return Builder.createUnmanagedStorageType(base); + if (base.isError()) + return base; + return Builder.createUnmanagedStorageType(base.getType()); } case NodeKind::Weak: { if (Node->getNumChildren() < 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children"); auto base = decodeMangledType(Node->getChild(0)); - if (!base) - return BuiltType(); - return Builder.createWeakStorageType(base); + if (base.isError()) + return base; + return Builder.createWeakStorageType(base.getType()); } case NodeKind::SILBoxType: { if (Node->getNumChildren() < 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children"); auto base = decodeMangledType(Node->getChild(0)); - if (!base) - return BuiltType(); - return Builder.createSILBoxType(base); + if (base.isError()) + return base; + return Builder.createSILBoxType(base.getType()); } case NodeKind::SILBoxTypeWithLayout: { // TODO: Implement SILBoxTypeRefs with layout. As a stopgap, specify the @@ -842,57 +897,62 @@ class TypeDecoder { } case NodeKind::SugaredOptional: { if (Node->getNumChildren() < 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children"); auto base = decodeMangledType(Node->getChild(0)); - if (!base) - return BuiltType(); + if (base.isError()) + return base; - return Builder.createOptionalType(base); + return Builder.createOptionalType(base.getType()); } case NodeKind::SugaredArray: { if (Node->getNumChildren() < 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children"); auto base = decodeMangledType(Node->getChild(0)); - if (!base) - return BuiltType(); + if (base.isError()) + return base; - return Builder.createArrayType(base); + return Builder.createArrayType(base.getType()); } case NodeKind::SugaredDictionary: { if (Node->getNumChildren() < 2) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR(Node, + "fewer children (%u) than required (2)", + Node->getNumChildren()); auto key = decodeMangledType(Node->getChild(0)); - if (!key) - return BuiltType(); + if (key.isError()) + return key; auto value = decodeMangledType(Node->getChild(1)); - if (!key) - return BuiltType(); + if (value.isError()) + return value; - return Builder.createDictionaryType(key, value); + return Builder.createDictionaryType(key.getType(), value.getType()); } case NodeKind::SugaredParen: { if (Node->getNumChildren() < 1) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "no children"); auto base = decodeMangledType(Node->getChild(0)); - if (!base) - return BuiltType(); + if (base.isError()) + return base; - return Builder.createParenType(base); + return Builder.createParenType(base.getType()); } case NodeKind::OpaqueType: { if (Node->getNumChildren() < 3) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR(Node, + "fewer children (%u) than required (3)", + Node->getNumChildren()); auto descriptor = Node->getChild(0); auto ordinalNode = Node->getChild(1); if (ordinalNode->getKind() != NodeKind::Index || !ordinalNode->hasIndex()) - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(ordinalNode, + "unexpected kind or no index"); auto ordinal = ordinalNode->getIndex(); std::vector genericArgsBuf; @@ -905,9 +965,9 @@ class TypeDecoder { break; for (auto argNode : *genericsNode) { auto arg = decodeMangledType(argNode); - if (!arg) - return BuiltType(); - genericArgsBuf.push_back(arg); + if (arg.isError()) + return arg; + genericArgsBuf.push_back(arg.getType()); } } genericArgsLevels.push_back(genericArgsBuf.size()); @@ -923,7 +983,7 @@ class TypeDecoder { // TODO: Handle OpaqueReturnType, when we're in the middle of reconstructing // the defining decl default: - return BuiltType(); + return MAKE_NODE_TYPE_ERROR0(Node, "unexpected kind"); } } @@ -943,11 +1003,11 @@ class TypeDecoder { T::getConventionFromString(conventionString); if (!convention) return true; - BuiltType type = decodeMangledType(node->getChild(1)); - if (!type) + auto type = decodeMangledType(node->getChild(1)); + if (type.isError()) return true; - results.emplace_back(type, *convention); + results.emplace_back(type.getType(), *convention); return false; } @@ -968,8 +1028,8 @@ class TypeDecoder { auto convention = T::getConventionFromString(conventionString); if (!convention) return true; - BuiltType type = decodeMangledType(typeNode); - if (!type) + auto result = decodeMangledType(typeNode); + if (result.isError()) return true; auto diffKind = T::DifferentiabilityType::DifferentiableOrNotApplicable; @@ -984,14 +1044,13 @@ class TypeDecoder { diffKind = *optDiffKind; } - results.emplace_back(type, *convention, diffKind); + results.emplace_back(result.getType(), *convention, diffKind); return false; } - bool decodeMangledTypeDecl(Demangle::NodePointer node, - BuiltTypeDecl &typeDecl, - BuiltType &parent, - bool &typeAlias) { + llvm::Optional + decodeMangledTypeDecl(Demangle::NodePointer node, BuiltTypeDecl &typeDecl, + BuiltType &parent, bool &typeAlias) { if (node->getKind() == NodeKind::Type) return decodeMangledTypeDecl(node->getChild(0), typeDecl, parent, typeAlias); @@ -1002,7 +1061,9 @@ class TypeDecoder { declNode = node; } else { if (node->getNumChildren() < 2) - return false; + return MAKE_NODE_TYPE_ERROR( + node, "Number of node children (%u) less than required (2)", + node->getNumChildren()); auto parentContext = node->getChild(0); @@ -1018,11 +1079,14 @@ class TypeDecoder { case Node::Kind::Extension: // Decode the type being extended. if (parentContext->getNumChildren() < 2) - return false; + return MAKE_NODE_TYPE_ERROR(parentContext, + "Number of parentContext children (%u) " + "less than required (2)", + node->getNumChildren()); parentContext = parentContext->getChild(1); LLVM_FALLTHROUGH; default: - parent = decodeMangledType(parentContext); + parent = decodeMangledType(parentContext).getType(); // Remove any generic arguments from the context node, producing a // node that references the nominal type declaration. declNode = Demangle::getUnspecialized(node, Builder.getNodeFactory()); @@ -1030,9 +1094,10 @@ class TypeDecoder { } } typeDecl = Builder.createTypeDecl(declNode, typeAlias); - if (!typeDecl) return false; + if (!typeDecl) + return TypeLookupError("Failed to create type decl"); - return true; + return llvm::None; } BuiltProtocolDecl decodeMangledProtocolType(Demangle::NodePointer node) { @@ -1097,10 +1162,10 @@ class TypeDecoder { } auto paramType = decodeMangledType(node); - if (!paramType) + if (paramType.isError()) return false; - param.setType(paramType); + param.setType(paramType.getType()); return true; }; @@ -1158,14 +1223,12 @@ class TypeDecoder { } }; -template -inline typename BuilderType::BuiltType -decodeMangledType(BuilderType &Builder, - NodePointer Node) { +template +inline TypeLookupErrorOr +decodeMangledType(BuilderType &Builder, NodePointer Node) { return TypeDecoder(Builder).decodeMangledType(Node); } - SWIFT_END_INLINE_NAMESPACE } // end namespace Demangle } // end namespace swift diff --git a/include/swift/Demangling/TypeLookupError.h b/include/swift/Demangling/TypeLookupError.h new file mode 100644 index 0000000000000..c67fc35598be8 --- /dev/null +++ b/include/swift/Demangling/TypeLookupError.h @@ -0,0 +1,198 @@ +//===--- TypeLookupError.h - Type lookup error value. -----------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// Provides the TypeLookupError class, which represents errors when demangling +// or looking up types. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_DEMANGLING_TypeLookupError_H +#define SWIFT_DEMANGLING_TypeLookupError_H + +#include "swift/Basic/TaggedUnion.h" +#include "swift/Runtime/Portability.h" + +namespace swift { + +/// An error that occurred while looking up a type at runtime from a mangled +/// name. +/// /// +/// This ultimately just provides a string, but is built to take up minimal +/// space when passed around, and perform as much work lazily as possible. We +/// don't want to spend a lot of time building strings when the caller is going +/// to handle the error gracefully and try a fallback. We only want to waste +/// time/space on that when the error message is actually relevant, so build it +/// as late as possible. +/// /// +/// To be as compact as possible, this type holds a context pointer and a +/// callback function. The callback function uses the context pointer to return +/// an error string when requested. The callback function also does quadruple +/// duty to copy/destroy the context as needed, and free the returned error +/// string if needed. Commands are passed to the callback to request the +/// different operations, which means we only have to store one function pointer +/// instead of four. +class TypeLookupError { +public: + /// The commands that can be passed to the callback function. + enum class Command { + /// Return the error string to the caller, as a char *. + CopyErrorString, + + /// Destroy the error string returned from CopyErrorString, if necessary. + /// The return value is ignored. + DestroyErrorString, + + /// Return a copy of the context pointer (used for copying TypeLookupError + /// objects.) + CopyContext, + + /// Destroy the context pointer. The return value is ignored. + DestroyContext, + }; + + /// The callback used to respond to the commands. The parameters are: + /// - `context`: the context that the value was initialized with, or the + /// context returned from a CopyContext call + /// - `command`: the command to respond to + /// - `param`: when `command` is `DestroyErrorString`, the string pointer to + /// destroy, otherwise NULL + using Callback = void *(*)(void *context, Command command, void *param); + +private: + void *Context; + Callback Fn; + + /// A no-op callback used to avoid a bunch of `if (Fn)` checks. + static void *nop(void *context, Command command, void *param) { + return nullptr; + } + + /// Helper functions for getting a C string from a lambda. These allow us to + /// wrap lambdas returning `char *` or `std::string` and standardize them on + /// `char *`. + static char *getCString(char *str) { return str; } + + static char *getCString(const std::string &str) { + return strdup(str.c_str()); + } + +public: + TypeLookupError(const TypeLookupError &other) { + Fn = other.Fn; + Context = other.Fn(other.Context, Command::CopyContext, nullptr); + } + + TypeLookupError(TypeLookupError &&other) { + Fn = other.Fn; + Context = other.Context; + + other.Fn = nop; + other.Context = nullptr; + } + + ~TypeLookupError() { Fn(Context, Command::DestroyContext, nullptr); } + + TypeLookupError(void *context, Callback fn) : Context(context), Fn(fn ? fn : nop) {} + + TypeLookupError &operator=(const TypeLookupError &other) { + if (this == &other) + return *this; + + Fn(Context, Command::DestroyContext, nullptr); + Fn = other.Fn; + Context = Fn(Context, Command::CopyContext, nullptr); + + return *this; + } + + /// Construct a TypeLookupError that just returns a constant C string. + TypeLookupError(const char *str) + : TypeLookupError([=] { return const_cast(str); }) {} + + /// Construct a TypeLookupError that creates a string using asprintf. The passed-in + /// format string and arguments are passed directly to swift_asprintf when + /// the string is requested. The arguments are captured and the string is only + /// formatted when needed. + template + TypeLookupError(const char *fmt, Args... args) + : TypeLookupError([=] { + char *str; + swift_asprintf(&str, fmt, args...); + return str; + }) {} + + /// Construct a TypeLookupError that wraps a function returning a string. The + /// passed-in function can return either a `std::string` or `char *`. If it + /// returns `char *` then the string will be destroyed with `free()`. + template TypeLookupError(const F &fn) { + Context = new F(fn); + Fn = [](void *context, Command command, void *param) -> void * { + auto castContext = reinterpret_cast(context); + switch (command) { + case Command::CopyErrorString: { + return TypeLookupError::getCString((*castContext)()); + } + case Command::DestroyErrorString: + free(param); + return nullptr; + case Command::CopyContext: + return new F(*castContext); + case Command::DestroyContext: + delete castContext; + return nullptr; + } + }; + } + + /// Get the error string from the error value. The value must be passed to + /// `freeErrorString` when done. (Unless you're just calling a `fatalError` + /// in which case there's no point.) + char *copyErrorString() { + return reinterpret_cast( + Fn(Context, Command::CopyErrorString, nullptr)); + } + + /// Free an error string previously obtained from `copyErrorString`. + void freeErrorString(char *str) { + Fn(Context, Command::DestroyErrorString, str); + } +}; + +/// A value that's either a `TypeLookupError` or some parameterized type value `T`. A +/// convenience wrapper around `TaggedUnion`. +template class TypeLookupErrorOr { + TaggedUnion Value; + +public: + TypeLookupErrorOr(const T &t) : Value(t) { + if (!t) + Value = TypeLookupError("unknown error"); + } + + TypeLookupErrorOr(const TypeLookupError &te) : Value(te) {} + + T getType() { + if (auto *ptr = Value.template dyn_cast()) + return *ptr; + return T(); + } + + TypeLookupError *getError() { + return Value.template dyn_cast(); + } + + bool isError() { return getError() != nullptr; } +}; + +} // namespace swift + +#endif // SWIFT_DEMANGLING_TypeLookupError_H diff --git a/include/swift/Driver/Action.h b/include/swift/Driver/Action.h index 02801d8aece66..7fee378225a2a 100644 --- a/include/swift/Driver/Action.h +++ b/include/swift/Driver/Action.h @@ -51,9 +51,10 @@ class Action { GenerateDSYMJob, VerifyDebugInfoJob, GeneratePCHJob, + VerifyModuleInterfaceJob, JobFirst = CompileJob, - JobLast = GeneratePCHJob + JobLast = VerifyModuleInterfaceJob }; static const char *getClassName(Kind AC); @@ -148,7 +149,7 @@ class CompileJobAction : public JobAction { }; private: - virtual void anchor(); + virtual void anchor() override; InputInfo inputInfo; public: @@ -191,7 +192,7 @@ class CompileJobAction : public JobAction { class InterpretJobAction : public JobAction { private: - virtual void anchor(); + virtual void anchor() override; public: explicit InterpretJobAction() @@ -205,7 +206,7 @@ class InterpretJobAction : public JobAction { class BackendJobAction : public JobAction { private: - virtual void anchor(); + virtual void anchor() override; // In case of multi-threaded compilation, the compile-action produces multiple // output bitcode-files. For each bitcode-file a BackendJobAction is created. @@ -220,7 +221,7 @@ class BackendJobAction : public JobAction { return A->getKind() == Action::Kind::BackendJob; } - virtual size_t getInputIndex() const { return InputIndex; } + virtual size_t getInputIndex() const override { return InputIndex; } }; class REPLJobAction : public JobAction { @@ -231,7 +232,7 @@ class REPLJobAction : public JobAction { RequireLLDB }; private: - virtual void anchor(); + virtual void anchor() override; Mode RequestedMode; public: REPLJobAction(Mode mode) @@ -247,7 +248,7 @@ class REPLJobAction : public JobAction { }; class MergeModuleJobAction : public JobAction { - virtual void anchor(); + virtual void anchor() override; public: MergeModuleJobAction(ArrayRef Inputs) : JobAction(Action::Kind::MergeModuleJob, Inputs, @@ -259,7 +260,7 @@ class MergeModuleJobAction : public JobAction { }; class ModuleWrapJobAction : public JobAction { - virtual void anchor(); + virtual void anchor() override; public: ModuleWrapJobAction(ArrayRef Inputs) : JobAction(Action::Kind::ModuleWrapJob, Inputs, @@ -271,7 +272,7 @@ class ModuleWrapJobAction : public JobAction { }; class AutolinkExtractJobAction : public JobAction { - virtual void anchor(); + virtual void anchor() override; public: AutolinkExtractJobAction(ArrayRef Inputs) : JobAction(Action::Kind::AutolinkExtractJob, Inputs, @@ -283,7 +284,7 @@ class AutolinkExtractJobAction : public JobAction { }; class GenerateDSYMJobAction : public JobAction { - virtual void anchor(); + virtual void anchor() override; public: explicit GenerateDSYMJobAction(const Action *Input) : JobAction(Action::Kind::GenerateDSYMJob, Input, @@ -295,7 +296,7 @@ class GenerateDSYMJobAction : public JobAction { }; class VerifyDebugInfoJobAction : public JobAction { - virtual void anchor(); + virtual void anchor() override; public: explicit VerifyDebugInfoJobAction(const Action *Input) : JobAction(Action::Kind::VerifyDebugInfoJob, Input, @@ -309,7 +310,7 @@ class VerifyDebugInfoJobAction : public JobAction { class GeneratePCHJobAction : public JobAction { std::string PersistentPCHDir; - virtual void anchor(); + virtual void anchor() override; public: GeneratePCHJobAction(const Action *Input, StringRef persistentPCHDir) : JobAction(Action::Kind::GeneratePCHJob, Input, @@ -326,7 +327,7 @@ class GeneratePCHJobAction : public JobAction { }; class DynamicLinkJobAction : public JobAction { - virtual void anchor(); + virtual void anchor() override; LinkKind Kind; public: @@ -344,7 +345,7 @@ class DynamicLinkJobAction : public JobAction { }; class StaticLinkJobAction : public JobAction { - virtual void anchor(); + virtual void anchor() override; public: StaticLinkJobAction(ArrayRef Inputs, LinkKind K) @@ -357,6 +358,26 @@ class StaticLinkJobAction : public JobAction { } }; +class VerifyModuleInterfaceJobAction : public JobAction { + virtual void anchor(); + file_types::ID inputType; + +public: + VerifyModuleInterfaceJobAction(const Action * ModuleEmitter, + file_types::ID inputType) + : JobAction(Action::Kind::VerifyModuleInterfaceJob, { ModuleEmitter }, + file_types::TY_Nothing), inputType(inputType) { + assert(inputType == file_types::TY_SwiftModuleInterfaceFile || + inputType == file_types::TY_PrivateSwiftModuleInterfaceFile); + } + + file_types::ID getInputType() const { return inputType; } + + static bool classof(const Action *A) { + return A->getKind() == Action::Kind::VerifyModuleInterfaceJob; + } +}; + } // end namespace driver } // end namespace swift diff --git a/include/swift/Driver/ToolChain.h b/include/swift/Driver/ToolChain.h index cd55451a01c8b..7be6dffbe37cf 100644 --- a/include/swift/Driver/ToolChain.h +++ b/include/swift/Driver/ToolChain.h @@ -162,6 +162,9 @@ class ToolChain { virtual InvocationInfo constructInvocation(const VerifyDebugInfoJobAction &job, const JobContext &context) const; + virtual InvocationInfo + constructInvocation(const VerifyModuleInterfaceJobAction &job, + const JobContext &context) const; virtual InvocationInfo constructInvocation(const GeneratePCHJobAction &job, const JobContext &context) const; virtual InvocationInfo diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h index f5f75f13e7694..39ab041dbcc1b 100644 --- a/include/swift/Frontend/Frontend.h +++ b/include/swift/Frontend/Frontend.h @@ -621,7 +621,7 @@ class CompilerInstance { /// /// This is similar to a parse-only invocation, but module imports will also /// be processed. - void performParseAndResolveImportsOnly(); + bool performParseAndResolveImportsOnly(); /// Performs mandatory, diagnostic, and optimization passes over the SIL. /// \param silModule The SIL module that was generated during SILGen. diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index aef89085fb34b..c961794d35582 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -116,6 +116,8 @@ class FrontendOptions { /// Build from a swiftinterface, as close to `import` as possible CompileModuleFromInterface, + /// Same as CompileModuleFromInterface, but stopping after typechecking + TypecheckModuleFromInterface, EmitSIBGen, ///< Emit serialized AST + raw SIL EmitSIB, ///< Emit serialized AST + canonical SIL @@ -133,7 +135,8 @@ class FrontendOptions { EmitPCM, ///< Emit precompiled Clang module from a module map DumpPCM, ///< Dump information about a precompiled Clang module - ScanDependencies, ///< Scan dependencies of Swift source files + ScanDependencies, ///< Scan dependencies of Swift source files + ScanClangDependencies, ///< Scan dependencies of a Clang module PrintVersion, ///< Print version information. }; @@ -291,9 +294,16 @@ class FrontendOptions { /// '.../lib/swift', otherwise '.../lib/swift_static'. bool UseSharedResourceFolder = true; - /// \return true if action only parses without doing other compilation steps. + /// \return true if the given action only parses without doing other compilation steps. static bool shouldActionOnlyParse(ActionType); + /// \return true if the given action requires the standard library to be + /// loaded before it is run. + static bool doesActionRequireSwiftStandardLibrary(ActionType); + + /// \return true if the given action requires input files to be provided. + static bool doesActionRequireInputs(ActionType action); + /// Return a hash code of any components from these options that should /// contribute to a Swift Bridging PCH hash. llvm::hash_code getPCHHashComponents() const { diff --git a/include/swift/Frontend/ModuleInterfaceLoader.h b/include/swift/Frontend/ModuleInterfaceLoader.h index 78116f109a8e8..787829882c82b 100644 --- a/include/swift/Frontend/ModuleInterfaceLoader.h +++ b/include/swift/Frontend/ModuleInterfaceLoader.h @@ -133,13 +133,22 @@ class ExplicitSwiftModuleLoader: public SerializedModuleLoaderBase { explicit ExplicitSwiftModuleLoader(ASTContext &ctx, DependencyTracker *tracker, ModuleLoadingMode loadMode, bool IgnoreSwiftSourceInfoFile); + + bool findModule(AccessPathElem moduleID, + SmallVectorImpl *moduleInterfacePath, + std::unique_ptr *moduleBuffer, + std::unique_ptr *moduleDocBuffer, + std::unique_ptr *moduleSourceInfoBuffer, + bool &isFramework, bool &isSystemModule) override; + std::error_code findModuleFilesInDirectory( - AccessPathElem ModuleID, - const SerializedModuleBaseName &BaseName, - SmallVectorImpl *ModuleInterfacePath, - std::unique_ptr *ModuleBuffer, - std::unique_ptr *ModuleDocBuffer, - std::unique_ptr *ModuleSourceInfoBuffer) override; + AccessPathElem ModuleID, + const SerializedModuleBaseName &BaseName, + SmallVectorImpl *ModuleInterfacePath, + std::unique_ptr *ModuleBuffer, + std::unique_ptr *ModuleDocBuffer, + std::unique_ptr *ModuleSourceInfoBuffer, + bool IsFramework) override; bool canImportModule(Located mID) override; @@ -172,6 +181,8 @@ struct ExplicitModuleInfo { std::string moduleSourceInfoPath; // Opened buffer for the .swiftmodule file. std::unique_ptr moduleBuffer; + // A flag that indicates whether this module is a framework + bool isFramework; }; /// Parser of explicit module maps passed into the compiler. @@ -181,12 +192,14 @@ struct ExplicitModuleInfo { // "modulePath": "A.swiftmodule", // "docPath": "A.swiftdoc", // "sourceInfoPath": "A.swiftsourceinfo" +// "isFramework": false // }, // { // "moduleName": "B", // "modulePath": "B.swiftmodule", // "docPath": "B.swiftdoc", // "sourceInfoPath": "B.swiftsourceinfo" +// "isFramework": false // } // ] class ExplicitModuleMapParser { @@ -248,6 +261,15 @@ class ExplicitModuleMapParser { result.moduleDocPath = val.str(); } else if (key == "sourceInfoPath") { result.moduleSourceInfoPath = val.str(); + } else if (key == "isFramework") { + auto valStr = val.str(); + valStr.erase(std::remove(valStr.begin(), valStr.end(), '\n'), valStr.end()); + if (valStr.compare("true") == 0) + result.isFramework = true; + else if (valStr.compare("false") == 0) + result.isFramework = false; + else + llvm_unreachable("Unexpected JSON value for isFramework"); } else { // Being forgiving for future fields. continue; @@ -263,6 +285,8 @@ class ExplicitModuleMapParser { }; struct ModuleInterfaceLoaderOptions { + FrontendOptions::ActionType requestedAction = + FrontendOptions::ActionType::EmitModuleOnly; bool remarkOnRebuildFromInterface = false; bool disableInterfaceLock = false; bool disableImplicitSwiftModule = false; @@ -271,7 +295,17 @@ struct ModuleInterfaceLoaderOptions { remarkOnRebuildFromInterface(Opts.RemarkOnRebuildFromModuleInterface), disableInterfaceLock(Opts.DisableInterfaceFileLock), disableImplicitSwiftModule(Opts.DisableImplicitModules), - mainExecutablePath(Opts.MainExecutablePath) {} + mainExecutablePath(Opts.MainExecutablePath) + { + switch (Opts.RequestedAction) { + case FrontendOptions::ActionType::TypecheckModuleFromInterface: + requestedAction = FrontendOptions::ActionType::Typecheck; + break; + default: + requestedAction = FrontendOptions::ActionType::EmitModuleOnly; + break; + } + } ModuleInterfaceLoaderOptions() = default; }; @@ -298,12 +332,13 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { ModuleInterfaceLoaderOptions Opts; std::error_code findModuleFilesInDirectory( - AccessPathElem ModuleID, - const SerializedModuleBaseName &BaseName, - SmallVectorImpl *ModuleInterfacePath, - std::unique_ptr *ModuleBuffer, - std::unique_ptr *ModuleDocBuffer, - std::unique_ptr *ModuleSourceInfoBuffer) override; + AccessPathElem ModuleID, + const SerializedModuleBaseName &BaseName, + SmallVectorImpl *ModuleInterfacePath, + std::unique_ptr *ModuleBuffer, + std::unique_ptr *ModuleDocBuffer, + std::unique_ptr *ModuleSourceInfoBuffer, + bool IsFramework) override; bool isCached(StringRef DepPath) override; public: @@ -392,17 +427,18 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { StringRef prebuiltCachePath, bool serializeDependencyHashes, bool trackSystemDependencies); - bool runInSubContext(StringRef moduleName, - StringRef interfacePath, - StringRef outputPath, - SourceLoc diagLoc, - llvm::function_ref, - ArrayRef, StringRef)> action) override; - bool runInSubCompilerInstance(StringRef moduleName, - StringRef interfacePath, - StringRef outputPath, - SourceLoc diagLoc, - llvm::function_ref action) override; + std::error_code runInSubContext(StringRef moduleName, + StringRef interfacePath, + StringRef outputPath, + SourceLoc diagLoc, + llvm::function_ref, ArrayRef, + StringRef)> action) override; + std::error_code runInSubCompilerInstance(StringRef moduleName, + StringRef interfacePath, + StringRef outputPath, + SourceLoc diagLoc, + llvm::function_ref action) override; ~InterfaceSubContextDelegateImpl() = default; diff --git a/include/swift/Frontend/ModuleInterfaceSupport.h b/include/swift/Frontend/ModuleInterfaceSupport.h index df576eb26d19a..f4c97c66c8f62 100644 --- a/include/swift/Frontend/ModuleInterfaceSupport.h +++ b/include/swift/Frontend/ModuleInterfaceSupport.h @@ -41,12 +41,15 @@ struct ModuleInterfaceOptions { /// back .swiftinterface and reconstructing .swiftmodule. std::string Flags; - // Print SPI decls and attributes. + /// Print SPI decls and attributes. bool PrintSPIs = false; /// Print imports with both @_implementationOnly and @_spi, only applies /// when PrintSPIs is true. bool ExperimentalSPIImports = false; + + /// Intentionally print invalid syntax into the file. + bool DebugPrintInvalidSyntax = false; }; extern version::Version InterfaceFormatVersion; diff --git a/include/swift/IDE/CodeCompletionResultPrinter.h b/include/swift/IDE/CodeCompletionResultPrinter.h index 717d6282a4309..86e1233246dc9 100644 --- a/include/swift/IDE/CodeCompletionResultPrinter.h +++ b/include/swift/IDE/CodeCompletionResultPrinter.h @@ -34,6 +34,12 @@ void printCodeCompletionResultTypeName( void printCodeCompletionResultTypeNameAnnotated( const CodeCompletionResult &Result, llvm::raw_ostream &OS); +void printCodeCompletionResultSourceText( + const CodeCompletionResult &Result, llvm::raw_ostream &OS); + +void printCodeCompletionResultFilterName( + const CodeCompletionResult &Result, llvm::raw_ostream &OS); + } // namespace ide } // namespace swift diff --git a/tools/SourceKit/include/SourceKit/Support/FuzzyStringMatcher.h b/include/swift/IDE/FuzzyStringMatcher.h similarity index 83% rename from tools/SourceKit/include/SourceKit/Support/FuzzyStringMatcher.h rename to include/swift/IDE/FuzzyStringMatcher.h index cb53e962de0d7..af80647e37c3e 100644 --- a/tools/SourceKit/include/SourceKit/Support/FuzzyStringMatcher.h +++ b/include/swift/IDE/FuzzyStringMatcher.h @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information @@ -10,14 +10,15 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SOURCEKIT_LIB_SUPPORT_FUZZYSTRINGMATCHER_H -#define LLVM_SOURCEKIT_LIB_SUPPORT_FUZZYSTRINGMATCHER_H +#ifndef SWIFT_IDE_FUZZYSTRINGMATCHER_H +#define SWIFT_IDE_FUZZYSTRINGMATCHER_H -#include "SourceKit/Core/LLVM.h" +#include "swift/Basic/LLVM.h" #include "llvm/ADT/BitVector.h" #include -namespace SourceKit { +namespace swift { +namespace ide { /// FuzzyStringMatcher compares candidate strings against a pattern /// string using a fuzzy matching algorithm and provides a numerical @@ -49,6 +50,7 @@ class FuzzyStringMatcher { double scoreCandidate(StringRef candidate) const; }; -} // end namespace SourceKit +} // namespace ide +} // namespace swift -#endif // LLVM_SOURCEKIT_LIB_SUPPORT_FUZZYSTRINGMATCHER_H +#endif // SWIFT_IDE_FUZZYSTRINGMATCHER_H diff --git a/include/swift/IDE/Utils.h b/include/swift/IDE/Utils.h index f847b188f1b42..8eaf34a69b5e7 100644 --- a/include/swift/IDE/Utils.h +++ b/include/swift/IDE/Utils.h @@ -81,6 +81,14 @@ SourceCompleteResult isSourceInputComplete(std::unique_ptr MemBuf, SourceFileKind SFKind); SourceCompleteResult isSourceInputComplete(StringRef Text, SourceFileKind SFKind); +bool initCompilerInvocation( + CompilerInvocation &Invocation, ArrayRef OrigArgs, + DiagnosticEngine &Diags, StringRef UnresolvedPrimaryFile, + llvm::IntrusiveRefCntPtr FileSystem, + const std::string &runtimeResourcePath, + const std::string &diagnosticDocumentationPath, + bool shouldOptimizeForIDE, time_t sessionTimestamp, std::string &Error); + bool initInvocationByClangArguments(ArrayRef ArgList, CompilerInvocation &Invok, std::string &Error); diff --git a/include/swift/IRGen/Linking.h b/include/swift/IRGen/Linking.h index 3232e0e6881e9..8eb4145bb76b6 100644 --- a/include/swift/IRGen/Linking.h +++ b/include/swift/IRGen/Linking.h @@ -1231,7 +1231,7 @@ class ApplyIRLinkage { IRLinkage IRL; public: ApplyIRLinkage(IRLinkage IRL) : IRL(IRL) {} - void to(llvm::GlobalValue *GV) const { + void to(llvm::GlobalValue *GV, bool definition = true) const { llvm::Module *M = GV->getParent(); const llvm::Triple Triple(M->getTargetTriple()); @@ -1253,11 +1253,14 @@ class ApplyIRLinkage { return; } - if (IRL.Linkage == llvm::GlobalValue::LinkOnceODRLinkage || - IRL.Linkage == llvm::GlobalValue::WeakODRLinkage) - if (Triple.supportsCOMDAT()) - if (llvm::GlobalObject *GO = dyn_cast(GV)) - GO->setComdat(M->getOrInsertComdat(GV->getName())); + // COMDATs cannot be applied to declarations. If we have a definition, + // apply the COMDAT. + if (definition) + if (IRL.Linkage == llvm::GlobalValue::LinkOnceODRLinkage || + IRL.Linkage == llvm::GlobalValue::WeakODRLinkage) + if (Triple.supportsCOMDAT()) + if (llvm::GlobalObject *GO = dyn_cast(GV)) + GO->setComdat(M->getOrInsertComdat(GV->getName())); } }; diff --git a/include/swift/AST/LocalizationFormat.h b/include/swift/Localization/LocalizationFormat.h similarity index 100% rename from include/swift/AST/LocalizationFormat.h rename to include/swift/Localization/LocalizationFormat.h diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 5bd693d2ffe7d..8996c6119e5d3 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -228,6 +228,10 @@ def explict_swift_module_map def placeholder_dependency_module_map : Separate<["-"], "placeholder-dependency-module-map-file">, MetaVarName<"">, HelpText<"Specify a JSON file containing information of external Swift module dependencies">; + +def batch_scan_input_file + : Separate<["-"], "batch-scan-input-file">, MetaVarName<"">, + HelpText<"Specify a JSON file containing modules to perform batch dependencies scanning">; } @@ -256,6 +260,9 @@ def debug_forbid_typecheck_prefix : Separate<["-"], "debug-forbid-typecheck-pref HelpText<"Triggers llvm fatal_error if typechecker tries to typecheck a decl " "with the provided prefix name">; +def debug_emit_invalid_swiftinterface_syntax : Flag<["-"], "debug-emit-invalid-swiftinterface-syntax">, + HelpText<"Write an invalid declaration into swiftinterface files">; + def debug_cycles : Flag<["-"], "debug-cycles">, HelpText<"Print out debug dumps when cycles are detected in evaluation">; def build_request_dependency_graph : Flag<["-"], "build-request-dependency-graph">, @@ -641,6 +648,11 @@ def build_module_from_parseable_interface : Alias, ModeOpt; +def typecheck_module_from_interface : + Flag<["-"], "typecheck-module-from-interface">, + HelpText<"Treat the (single) input as a swiftinterface and typecheck it">, + ModeOpt; + def module_interface_preserve_types_as_written : Flag<["-"], "module-interface-preserve-types-as-written">, HelpText<"When emitting a module interface, preserve types as they were " diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 01017c43315eb..8273359fcb97c 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -460,6 +460,15 @@ def emit_private_module_interface_path : DoesNotAffectIncrementalBuild, ArgumentIsPath, SupplementaryOutput]>, MetaVarName<"">, HelpText<"Output private module interface file to ">; +def verify_emitted_module_interface : + Flag<["-"], "verify-emitted-module-interface">, + Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>, + HelpText<"Check that module interfaces emitted during compilation typecheck">; +def no_verify_emitted_module_interface : + Flag<["-"], "no-verify-emitted-module-interface">, + Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>, + HelpText<"Don't check that module interfaces emitted during compilation typecheck">; + def avoid_emit_module_source_info : Flag<["-"], "avoid-emit-module-source-info">, Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>, @@ -1094,6 +1103,10 @@ def scan_dependencies : Flag<["-"], "scan-dependencies">, HelpText<"Scan dependencies of the given Swift sources">, ModeOpt, Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; +def scan_clang_dependencies : Flag<["-"], "scan-clang-dependencies">, + HelpText<"Scan dependencies of the given Clang module">, ModeOpt, + Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; + def enable_astscope_lookup : Flag<["-"], "enable-astscope-lookup">, Flags<[FrontendOption]>, HelpText<"Enable ASTScope-based unqualified name lookup">; diff --git a/include/swift/Parse/Lexer.h b/include/swift/Parse/Lexer.h index 8cd9b75a415c7..68663f19a3c4e 100644 --- a/include/swift/Parse/Lexer.h +++ b/include/swift/Parse/Lexer.h @@ -352,7 +352,7 @@ class Lexer { static SourceLoc getLocForStartOfLine(SourceManager &SM, SourceLoc Loc); /// Retrieve the source location for the end of the line containing the - /// given token, which is the location of the start of the next line. + /// given location, which is the location of the start of the next line. static SourceLoc getLocForEndOfLine(SourceManager &SM, SourceLoc Loc); /// Retrieve the string used to indent the line that contains the given diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index 625092e4a3ba3..7f1b3ddba9249 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -688,6 +688,14 @@ class Parser { Optional getStringLiteralIfNotInterpolated(SourceLoc Loc, StringRef DiagText); + /// Returns true to indicate that experimental concurrency syntax should be + /// parsed if the parser is generating only a syntax tree or if the user has + /// passed the `-enable-experimental-concurrency` flag to the frontend. + bool shouldParseExperimentalConcurrency() const { + return Context.LangOpts.EnableExperimentalConcurrency || + Context.LangOpts.ParseForSyntaxTreeOnly; + } + public: InFlightDiagnostic diagnose(SourceLoc Loc, Diagnostic Diag) { if (Diags.isDiagnosticPointsToFirstBadToken(Diag.getID()) && @@ -1125,8 +1133,7 @@ class Parser { ParseDeclOptions Flags, DeclAttributes &Attributes, bool HasFuncKeyword = true); - ParserResult - parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD); + BraceStmt *parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD); void parseAbstractFunctionBody(AbstractFunctionDecl *AFD); BraceStmt *parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD); ParserResult parseDeclProtocol(ParseDeclOptions Flags, @@ -1572,6 +1579,7 @@ class Parser { SmallVectorImpl &captureList, VarDecl *&capturedSelfParamDecl, ParameterList *¶ms, + SourceLoc &asyncLoc, SourceLoc &throwsLoc, SourceLoc &arrowLoc, TypeExpr *&explicitResultType, diff --git a/include/swift/Reflection/ReflectionContext.h b/include/swift/Reflection/ReflectionContext.h index 08915aa090b73..6fc3df0882f5f 100644 --- a/include/swift/Reflection/ReflectionContext.h +++ b/include/swift/Reflection/ReflectionContext.h @@ -22,8 +22,10 @@ #include "llvm/BinaryFormat/MachO.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/Object/COFF.h" +#include "llvm/Support/Memory.h" #include "swift/ABI/Enum.h" +#include "swift/ABI/ObjectFile.h" #include "swift/Remote/MemoryReader.h" #include "swift/Remote/MetadataReader.h" #include "swift/Reflection/Records.h" @@ -210,12 +212,12 @@ class ReflectionContext auto SectBuf = this->getReader().readBytes(RemoteAddress(RangeStart), RangeEnd - RangeStart); - auto findMachOSectionByName = [&](std::string Name) + auto findMachOSectionByName = [&](llvm::StringRef Name) -> std::pair, uint64_t> { for (unsigned I = 0; I < NumSect; ++I) { auto S = reinterpret_cast( SectionsBuf + (I * sizeof(typename T::Section))); - if (strncmp(S->sectname, Name.c_str(), strlen(Name.c_str())) != 0) + if (strncmp(S->sectname, Name.data(), strlen(Name.data())) != 0) continue; auto RemoteSecStart = S->addr + Slide; auto SectBufData = reinterpret_cast(SectBuf.get()); @@ -228,12 +230,19 @@ class ReflectionContext return {nullptr, 0}; }; - auto FieldMdSec = findMachOSectionByName("__swift5_fieldmd"); - auto AssocTySec = findMachOSectionByName("__swift5_assocty"); - auto BuiltinTySec = findMachOSectionByName("__swift5_builtin"); - auto CaptureSec = findMachOSectionByName("__swift5_capture"); - auto TypeRefMdSec = findMachOSectionByName("__swift5_typeref"); - auto ReflStrMdSec = findMachOSectionByName("__swift5_reflstr"); + SwiftObjectFileFormatMachO ObjectFileFormat; + auto FieldMdSec = findMachOSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::fieldmd)); + auto AssocTySec = findMachOSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::assocty)); + auto BuiltinTySec = findMachOSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::builtin)); + auto CaptureSec = findMachOSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::capture)); + auto TypeRefMdSec = findMachOSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::typeref)); + auto ReflStrMdSec = findMachOSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr)); if (FieldMdSec.first == nullptr && AssocTySec.first == nullptr && @@ -330,12 +339,19 @@ class ReflectionContext return {nullptr, 0}; }; - auto CaptureSec = findCOFFSectionByName(".sw5cptr"); - auto TypeRefMdSec = findCOFFSectionByName(".sw5tyrf"); - auto FieldMdSec = findCOFFSectionByName(".sw5flmd"); - auto AssocTySec = findCOFFSectionByName(".sw5asty"); - auto BuiltinTySec = findCOFFSectionByName(".sw5bltn"); - auto ReflStrMdSec = findCOFFSectionByName(".sw5rfst"); + SwiftObjectFileFormatCOFF ObjectFileFormat; + auto FieldMdSec = findCOFFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::fieldmd)); + auto AssocTySec = findCOFFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::assocty)); + auto BuiltinTySec = findCOFFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::builtin)); + auto CaptureSec = findCOFFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::capture)); + auto TypeRefMdSec = findCOFFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::typeref)); + auto ReflStrMdSec = findCOFFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr)); if (FieldMdSec.first == nullptr && AssocTySec.first == nullptr && @@ -378,29 +394,60 @@ class ReflectionContext return readPECOFFSections(ImageStart); } - template bool readELFSections(RemoteAddress ImageStart) { - auto Buf = - this->getReader().readBytes(ImageStart, sizeof(typename T::Header)); + template + bool readELFSections(RemoteAddress ImageStart, + llvm::Optional FileBuffer) { + // When reading from the FileBuffer we can simply return a pointer to + // the underlying data. + // When reading from the process, we need to keep the memory around + // until the end of the function, so we store it inside ReadDataBuffer. + // We do this so in both cases we can return a simple pointer. + std::vector ReadDataBuffer; + auto readData = [&](uint64_t Offset, uint64_t Size) -> const void * { + if (FileBuffer.hasValue()) { + auto Buffer = FileBuffer.getValue(); + if (Offset + Size > Buffer.allocatedSize()) + return nullptr; + return (const void *)((uint64_t)Buffer.base() + Offset); + } else { + MemoryReader::ReadBytesResult Buf = + this->getReader().readBytes(ImageStart + Offset, Size); + if (!Buf) + return nullptr; + ReadDataBuffer.push_back(std::move(Buf)); + return ReadDataBuffer.back().get(); + } + }; - auto Hdr = reinterpret_cast(Buf.get()); + const void *Buf = readData(0, sizeof(typename T::Header)); + if (!Buf) + return false; + auto Hdr = reinterpret_cast(Buf); assert(Hdr->getFileClass() == T::ELFClass && "invalid ELF file class"); - // From the header, grab informations about the section header table. - auto SectionHdrAddress = ImageStart.getAddressData() + Hdr->e_shoff; - auto SectionHdrNumEntries = Hdr->e_shnum; - auto SectionEntrySize = Hdr->e_shentsize; + // From the header, grab information about the section header table. + uint64_t SectionHdrAddress = Hdr->e_shoff; + uint16_t SectionHdrNumEntries = Hdr->e_shnum; + uint16_t SectionEntrySize = Hdr->e_shentsize; + + if (sizeof(typename T::Section) > SectionEntrySize) + return false; + if (SectionHdrNumEntries == 0) + return false; // Collect all the section headers, we need them to look up the // reflection sections (by name) and the string table. + // We read the section headers from the FileBuffer, since they are + // not mapped in the child process. std::vector SecHdrVec; for (unsigned I = 0; I < SectionHdrNumEntries; ++I) { - auto SecBuf = this->getReader().readBytes( - RemoteAddress(SectionHdrAddress + (I * SectionEntrySize)), - SectionEntrySize); + uint64_t Offset = SectionHdrAddress + (I * SectionEntrySize); + auto SecBuf = readData(Offset, sizeof(typename T::Section)); if (!SecBuf) return false; - auto SecHdr = - reinterpret_cast(SecBuf.get()); + const typename T::Section *SecHdr = + reinterpret_cast(SecBuf); + SecHdrVec.push_back(SecHdr); } @@ -419,37 +466,72 @@ class ReflectionContext typename T::Offset StrTabOffset = SecHdrStrTab->sh_offset; typename T::Size StrTabSize = SecHdrStrTab->sh_size; - auto StrTabStart = - RemoteAddress(ImageStart.getAddressData() + StrTabOffset); - auto StrTabBuf = this->getReader().readBytes(StrTabStart, StrTabSize); - auto StrTab = reinterpret_cast(StrTabBuf.get()); - - auto findELFSectionByName = [&](std::string Name) - -> std::pair, uint64_t> { - // Now for all the sections, find their name. - for (const typename T::Section *Hdr : SecHdrVec) { - uint32_t Offset = Hdr->sh_name; - auto SecName = std::string(StrTab + Offset); - if (SecName != Name) - continue; - auto SecStart = - RemoteAddress(ImageStart.getAddressData() + Hdr->sh_addr); - auto SecSize = Hdr->sh_size; - auto SecBuf = this->getReader().readBytes(SecStart, SecSize); - auto SecContents = RemoteRef(SecStart.getAddressData(), - SecBuf.get()); - savedBuffers.push_back(std::move(SecBuf)); - return {SecContents, SecSize}; - } - return {nullptr, 0}; - }; + auto StrTabBuf = readData(StrTabOffset, StrTabSize); + if (!StrTabBuf) + return false; + auto StrTab = reinterpret_cast(StrTabBuf); + bool Error = false; + auto findELFSectionByName = + [&](llvm::StringRef Name) -> std::pair, uint64_t> { + if (Error) + return {nullptr, 0}; + // Now for all the sections, find their name. + for (const typename T::Section *Hdr : SecHdrVec) { + uint32_t Offset = Hdr->sh_name; + const char *Start = (const char *)StrTab + Offset; + uint64_t StringSize = strnlen(Start, StrTabSize - Offset); + if (StringSize > StrTabSize - Offset) { + Error = true; + break; + } + std::string SecName(Start, StringSize); + if (SecName != Name) + continue; + RemoteAddress SecStart = + RemoteAddress(ImageStart.getAddressData() + Hdr->sh_addr); + auto SecSize = Hdr->sh_size; + MemoryReader::ReadBytesResult SecBuf; + if (FileBuffer.hasValue()) { + // sh_offset gives us the offset to the section in the file, + // while sh_addr gives us the offset in the process. + auto Offset = Hdr->sh_offset; + if (FileBuffer->allocatedSize() < Offset + SecSize) { + Error = true; + break; + } + auto *Buf = malloc(SecSize); + SecBuf = MemoryReader::ReadBytesResult( + Buf, [](const void *ptr) { free(const_cast(ptr)); }); + memcpy((void *)Buf, + (const void *)((uint64_t)FileBuffer->base() + Offset), + SecSize); + } else { + SecBuf = this->getReader().readBytes(SecStart, SecSize); + } + auto SecContents = + RemoteRef(SecStart.getAddressData(), SecBuf.get()); + savedBuffers.push_back(std::move(SecBuf)); + return {SecContents, SecSize}; + } + return {nullptr, 0}; + }; - auto FieldMdSec = findELFSectionByName("swift5_fieldmd"); - auto AssocTySec = findELFSectionByName("swift5_assocty"); - auto BuiltinTySec = findELFSectionByName("swift5_builtin"); - auto CaptureSec = findELFSectionByName("swift5_capture"); - auto TypeRefMdSec = findELFSectionByName("swift5_typeref"); - auto ReflStrMdSec = findELFSectionByName("swift5_reflstr"); + SwiftObjectFileFormatELF ObjectFileFormat; + auto FieldMdSec = findELFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::fieldmd)); + auto AssocTySec = findELFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::assocty)); + auto BuiltinTySec = findELFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::builtin)); + auto CaptureSec = findELFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::capture)); + auto TypeRefMdSec = findELFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::typeref)); + auto ReflStrMdSec = findELFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr)); + + if (Error) + return false; // We succeed if at least one of the sections is present in the // ELF executable. @@ -470,12 +552,28 @@ class ReflectionContext {ReflStrMdSec.first, ReflStrMdSec.second}}; this->addReflectionInfo(info); - - savedBuffers.push_back(std::move(Buf)); return true; } - - bool readELF(RemoteAddress ImageStart) { + + /// Parses metadata information from an ELF image. Because the Section + /// Header Table maybe be missing (for example, when reading from a + /// process) this method optionally receives a buffer with the contents + /// of the image's file, from where it will the necessary information. + /// + /// + /// \param[in] ImageStart + /// A remote address pointing to the start of the image in the running + /// process. + /// + /// \param[in] FileBuffer + /// A buffer which contains the contents of the image's file + /// in disk. If missing, all the information will be read using the + /// instance's memory reader. + /// + /// \return + /// /b True if the metadata information was parsed successfully, + /// /b false otherwise. + bool readELF(RemoteAddress ImageStart, llvm::Optional FileBuffer) { auto Buf = this->getReader().readBytes(ImageStart, sizeof(llvm::ELF::Elf64_Ehdr)); @@ -488,9 +586,11 @@ class ReflectionContext // Check if we have a ELFCLASS32 or ELFCLASS64 unsigned char FileClass = Hdr->getFileClass(); if (FileClass == llvm::ELF::ELFCLASS64) { - return readELFSections>(ImageStart); + return readELFSections>( + ImageStart, FileBuffer); } else if (FileClass == llvm::ELF::ELFCLASS32) { - return readELFSections>(ImageStart); + return readELFSections>( + ImageStart, FileBuffer); } else { return false; } @@ -520,15 +620,16 @@ class ReflectionContext if (MagicBytes[0] == 'M' && MagicBytes[1] == 'Z') { return readPECOFF(ImageStart); } - + + // ELF. if (MagicBytes[0] == llvm::ELF::ElfMagic[0] && MagicBytes[1] == llvm::ELF::ElfMagic[1] && MagicBytes[2] == llvm::ELF::ElfMagic[2] && MagicBytes[3] == llvm::ELF::ElfMagic[3]) { - return readELF(ImageStart); + return readELF(ImageStart, llvm::Optional()); } - + // We don't recognize the format. return false; } @@ -778,7 +879,8 @@ class ReflectionContext std::function Call) { if (!NodePtr) return; - auto NodeBytes = getReader().readBytes(RemoteAddress(NodePtr), sizeof(Node)); + auto NodeBytes = getReader().readBytes(RemoteAddress(NodePtr), + sizeof(ConformanceNode)); auto NodeData = reinterpret_cast *>(NodeBytes.get()); if (!NodeData) @@ -788,6 +890,33 @@ class ReflectionContext iterateConformanceTree(NodeData->Right, Call); } + void IterateConformanceTable( + RemoteAddress ConformancesPtr, + std::function Call) { + auto MapBytes = getReader().readBytes(RemoteAddress(ConformancesPtr), + sizeof(ConcurrentHashMap)); + auto MapData = + reinterpret_cast *>(MapBytes.get()); + if (!MapData) + return; + + auto Count = MapData->ElementCount; + auto Size = Count * sizeof(ConformanceCacheEntry); + + auto ElementsBytes = + getReader().readBytes(RemoteAddress(MapData->Elements), Size); + auto ElementsData = + reinterpret_cast *>( + ElementsBytes.get()); + if (!ElementsData) + return; + + for (StoredSize i = 0; i < Count; i++) { + auto &Element = ElementsData[i]; + Call(Element.Type, Element.Proto); + } + } + /// Iterate the protocol conformance cache in the target process, calling Call /// with the type and protocol of each conformance. Returns None on success, /// and a string describing the error on failure. @@ -807,7 +936,26 @@ class ReflectionContext auto Root = getReader().readPointer(ConformancesAddr->getResolvedAddress(), sizeof(StoredPointer)); - iterateConformanceTree(Root->getResolvedAddress().getAddressData(), Call); + auto ReaderCount = Root->getResolvedAddress().getAddressData(); + + // ReaderCount will be the root pointer if the conformance cache is a + // ConcurrentMap. It's very unlikely that there would ever be more readers + // than the least valid pointer value, so compare with that to distinguish. + // TODO: once the old conformance cache is gone for good, remove that code. + uint64_t LeastValidPointerValue; + if (!getReader().queryDataLayout( + DataLayoutQueryType::DLQ_GetLeastValidPointerValue, nullptr, + &LeastValidPointerValue)) { + return std::string("unable to query least valid pointer value"); + } + + if (ReaderCount < LeastValidPointerValue) + IterateConformanceTable(ConformancesAddr->getResolvedAddress(), Call); + else { + // The old code has the root address at this location. + auto RootAddr = ReaderCount; + iterateConformanceTree(RootAddr, Call); + } return llvm::None; } diff --git a/include/swift/Reflection/RuntimeInternals.h b/include/swift/Reflection/RuntimeInternals.h index 11b6027242aaf..30ec8827c8515 100644 --- a/include/swift/Reflection/RuntimeInternals.h +++ b/include/swift/Reflection/RuntimeInternals.h @@ -46,6 +46,20 @@ template struct MetadataCacheNode { typename Runtime::StoredPointer Right; }; +template struct ConcurrentHashMap { + typename Runtime::StoredSize ReaderCount; + typename Runtime::StoredSize ElementCount; + typename Runtime::StoredPointer Elements; + typename Runtime::StoredPointer Indices; + // We'll ignore the remaining fields for now.... +}; + +template struct ConformanceCacheEntry { + typename Runtime::StoredPointer Type; + typename Runtime::StoredPointer Proto; + typename Runtime::StoredPointer Witness; +}; + } // end namespace reflection } // end namespace swift diff --git a/include/swift/Reflection/TypeLowering.h b/include/swift/Reflection/TypeLowering.h index 13eda217e1510..f3e59d14ac8b3 100644 --- a/include/swift/Reflection/TypeLowering.h +++ b/include/swift/Reflection/TypeLowering.h @@ -181,7 +181,7 @@ class BuiltinTypeInfo : public TypeInfo { bool readExtraInhabitantIndex(remote::MemoryReader &reader, remote::RemoteAddress address, - int *extraInhabitantIndex) const; + int *extraInhabitantIndex) const override; static bool classof(const TypeInfo *TI) { return TI->getKind() == TypeInfoKind::Builtin; @@ -208,7 +208,7 @@ class RecordTypeInfo : public TypeInfo { bool readExtraInhabitantIndex(remote::MemoryReader &reader, remote::RemoteAddress address, - int *index) const; + int *index) const override; static bool classof(const TypeInfo *TI) { return TI->getKind() == TypeInfoKind::Record; @@ -299,7 +299,7 @@ class ReferenceTypeInfo : public TypeInfo { bool readExtraInhabitantIndex(remote::MemoryReader &reader, remote::RemoteAddress address, - int *extraInhabitantIndex) const { + int *extraInhabitantIndex) const override { if (getNumExtraInhabitants() == 0) { *extraInhabitantIndex = -1; return true; diff --git a/include/swift/Reflection/TypeRefBuilder.h b/include/swift/Reflection/TypeRefBuilder.h index f375918a5ff5d..3914810cbfd8f 100644 --- a/include/swift/Reflection/TypeRefBuilder.h +++ b/include/swift/Reflection/TypeRefBuilder.h @@ -618,8 +618,8 @@ class TypeRefBuilder { }), OpaqueUnderlyingTypeReader( [&reader](uint64_t descriptorAddr, unsigned ordinal) -> const TypeRef* { - return reader.readUnderlyingTypeForOpaqueTypeDescriptor(descriptorAddr, - ordinal); + return reader.readUnderlyingTypeForOpaqueTypeDescriptor( + descriptorAddr, ordinal).getType(); }) {} diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index 4450066283afc..0090ae0746ed6 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -463,7 +463,8 @@ class MetadataReader { } /// Given a demangle tree, attempt to turn it into a type. - BuiltType decodeMangledType(NodePointer Node) { + TypeLookupErrorOr + decodeMangledType(NodePointer Node) { return swift::Demangle::decodeMangledType(Builder, Node); } @@ -925,8 +926,8 @@ class MetadataReader { swift_runtime_unreachable("Unhandled MetadataKind in switch"); } - BuiltType readTypeFromMangledName(const char *MangledTypeName, - size_t Length) { + TypeLookupErrorOr + readTypeFromMangledName(const char *MangledTypeName, size_t Length) { Demangle::Demangler Dem; Demangle::NodePointer Demangled = Dem.demangleSymbol(StringRef(MangledTypeName, Length)); @@ -1183,14 +1184,14 @@ class MetadataReader { MangledNameKind::Type, Dem); } - BuiltType + TypeLookupErrorOr readUnderlyingTypeForOpaqueTypeDescriptor(StoredPointer contextAddr, unsigned ordinal) { Demangle::Demangler Dem; auto node = readUnderlyingTypeManglingForOpaqueTypeDescriptor(contextAddr, ordinal, Dem); if (!node) - return BuiltType(); + return TypeLookupError("Failed to read type mangling for descriptor."); return decodeMangledType(node); } diff --git a/include/swift/Runtime/Concurrent.h b/include/swift/Runtime/Concurrent.h index 7e4ed718b131b..e634fbc25660d 100644 --- a/include/swift/Runtime/Concurrent.h +++ b/include/swift/Runtime/Concurrent.h @@ -17,6 +17,7 @@ #include #include #include +#include "llvm/ADT/Hashing.h" #include "llvm/Support/Allocator.h" #include "Atomic.h" #include "Debug.h" @@ -26,6 +27,10 @@ #include #endif +#if defined(__APPLE__) && defined(__MACH__) +#include +#endif + namespace swift { /// This is a node in a concurrent linked list. @@ -488,8 +493,8 @@ template struct ConcurrentReadableArray { const ElemTy *end() { return Start + Count; } size_t count() { return Count; } }; - - // This type cannot be safely copied, moved, or deleted. + + // This type cannot be safely copied or moved. ConcurrentReadableArray(const ConcurrentReadableArray &) = delete; ConcurrentReadableArray(ConcurrentReadableArray &&) = delete; ConcurrentReadableArray &operator=(const ConcurrentReadableArray &) = delete; @@ -512,7 +517,7 @@ template struct ConcurrentReadableArray { auto *newStorage = Storage::allocate(newCapacity); if (storage) { std::copy(storage->data(), storage->data() + count, newStorage->data()); - newStorage->Count.store(count, std::memory_order_relaxed); + newStorage->Count.store(count, std::memory_order_release); FreeList.push_back(storage); } @@ -527,7 +532,7 @@ template struct ConcurrentReadableArray { if (ReaderCount.load(std::memory_order_acquire) == 0) deallocateFreeList(); } - + Snapshot snapshot() { incrementReaders(); auto *storage = Elements.load(SWIFT_MEMORY_ORDER_CONSUME); @@ -541,6 +546,416 @@ template struct ConcurrentReadableArray { } }; +using llvm::hash_value; + +/// A hash table that can be queried without taking any locks. Writes are still +/// locked and serialized, but only with respect to other locks. Writers can add +/// elements and clear the table, but they cannot remove individual elements. +/// Readers work by taking a snapshot of the table and then querying that +/// snapshot. +/// +/// The basic structure of the table consists of two arrays. Elements are stored +/// in a contiguous array, with new elements appended to the end. The second +/// array is the actual hash table, and it contains indices into the elements +/// array. This scheme cuts down on wasted space when the elements are larger +/// than a few bytes: instead of wasting `(1 - loadFactor) * sizeof(element)` +/// bytes on unused space in the hash table, we only waste `(1 - loadFactor) * +/// sizeof(index)`. This scheme also avoids readers seeing partially constructed +/// elements. +/// +/// Reader/writer synchronization for new elements is handled by keeping an +/// element count which is only incremented when the element has been fully +/// constructed. A reader which sees an index beyond its view of the current +/// count will ignore it and treat that as if there was no entry. +/// +/// Reader/writer synchronization for resizing the arrays is handled by tracking +/// the current number of active readers. When resizing, the new array is +/// allocated, the data copied, and then the old array is placed in a free list. +/// The free list is only deallocated if there are no readers, otherwise freeing +/// is deferred. +/// +/// Reader/writer synchronization for clearing the table is a combination of the +/// above. By keeping the old arrays around until all readers are finished, we +/// ensure that readers which started before the clear see valid (pre-clear) +/// data. Readers which see any array as empty will produce no results, thus +/// providing valid post-clear data. +template struct ConcurrentReadableHashMap { + // We use memcpy and don't call destructors. Make sure the elements will put + // up with this. + static_assert(std::is_trivially_copyable::value, + "Elements must be trivially copyable."); + static_assert(std::is_trivially_destructible::value, + "Elements must not have destructors (they won't be called)."); + +private: + /// The type of the elements of the indices array. TODO: use one or two byte + /// indices for smaller tables to save more memory. + using Index = unsigned; + + /// The reciprocal of the load factor at which we expand the table. A value of + /// 4 means that we resize at 1/4 = 75% load factor. + static const size_t ResizeProportion = 4; + + /// Get the "good size" for a given allocation size. When available, this + /// rounds up to the next allocation quantum by calling `malloc_good_size`. + /// Otherwise, just return the passed-in size, which is always valid even if + /// not necessarily optimal. + size_t goodSize(size_t size) { +#if defined(__APPLE__) && defined(__MACH__) + return malloc_good_size(size); +#else + return size; +#endif + } + + /// A private class representing the storage of the indices. In order to + /// ensure that readers can get a consistent view of the indices with a single + /// atomic read, we store the size of the indices array inline, as the first + /// element in the array. + /// + /// We want the number of indices to be a power of two so that we can use a + /// bitwise AND to convert a hash code to an index. We want the entire array + /// to be a power of two in size to be friendly to the allocator, but the size + /// is stored inline. We work around this contradiction by considering the + /// first index to always be occupied with a value that never matches any key. + struct IndexStorage { + std::atomic Mask; + + static IndexStorage *allocate(size_t capacity) { + assert((capacity & (capacity - 1)) == 0 && + "Capacity must be a power of 2"); + auto *ptr = + reinterpret_cast(calloc(capacity, sizeof(Mask))); + if (!ptr) + swift::crash("Could not allocate memory."); + ptr->Mask.store(capacity - 1, std::memory_order_relaxed); + return ptr; + } + + std::atomic &at(size_t i) { return (&Mask)[i]; } + }; + + /// A simple linked list representing pointers that need to be freed. + struct FreeListNode { + FreeListNode *Next; + void *Ptr; + + static void add(FreeListNode **head, void *ptr) { + auto *newNode = new FreeListNode{*head, ptr}; + *head = newNode; + } + + static void freeAll(FreeListNode **head) { + auto *node = *head; + while (node) { + auto *next = node->Next; + free(node->Ptr); + delete node; + node = next; + } + *head = nullptr; + } + }; + + /// The number of readers currently active, equal to the number of snapshot + /// objects currently alive. + std::atomic ReaderCount{0}; + + /// The number of elements in the elements array. + std::atomic ElementCount{0}; + + /// The array of elements. + std::atomic Elements{nullptr}; + + /// The array of indices. + std::atomic Indices{nullptr}; + + /// The writer lock, which must be taken before any mutation of the table. + Mutex WriterLock; + + /// The maximum number of elements that the current elements array can hold. + uint32_t ElementCapacity{0}; + + /// The list of pointers to be freed once no readers are active. + FreeListNode *FreeList{nullptr}; + + void incrementReaders() { + ReaderCount.fetch_add(1, std::memory_order_acquire); + } + + void decrementReaders() { + ReaderCount.fetch_sub(1, std::memory_order_release); + } + + /// Free all the arrays in the free lists if there are no active readers. If + /// there are active readers, do nothing. + void deallocateFreeListIfSafe() { + if (ReaderCount.load(std::memory_order_acquire) == 0) + FreeListNode::freeAll(&FreeList); + } + + /// Grow the elements array, adding the old array to the free list and + /// returning the new array with all existing elements copied into it. + ElemTy *resize(ElemTy *elements, size_t elementCount) { + // Grow capacity by 25%, making sure we grow by at least 1. + size_t newCapacity = + std::max(elementCount + (elementCount >> 2), elementCount + 1); + size_t newSize = newCapacity * sizeof(ElemTy); + + newSize = goodSize(newSize); + newCapacity = newSize / sizeof(ElemTy); + + ElemTy *newElements = static_cast(malloc(newSize)); + if (elements) { + memcpy(newElements, elements, elementCount * sizeof(ElemTy)); + FreeListNode::add(&FreeList, elements); + } + + ElementCapacity = newCapacity; + Elements.store(newElements, std::memory_order_release); + return newElements; + } + + /// Grow the indices array, adding the old array to the free list and + /// returning the new array with all existing indices copied into it. This + /// operation performs a rehash, so that the indices are in the correct + /// location in the new array. + IndexStorage *resize(IndexStorage *indices, Index indicesMask, + ElemTy *elements) { + // Mask is size - 1. Double the size. Start with 4 (fits into 16-byte malloc + // bucket). + size_t newCount = indices ? 2 * (indicesMask + 1) : 4; + size_t newMask = newCount - 1; + + IndexStorage *newIndices = IndexStorage::allocate(newCount); + + for (size_t i = 1; i <= indicesMask; i++) { + Index index = indices->at(i).load(std::memory_order_relaxed); + if (index == 0) + continue; + + auto *element = &elements[index - 1]; + auto hash = hash_value(*element); + + size_t newI = hash & newMask; + while (newIndices->at(newI) != 0) + newI = (newI + 1) & newMask; + newIndices->at(newI).store(index, std::memory_order_relaxed); + } + + Indices.store(newIndices, std::memory_order_release); + + FreeListNode::add(&FreeList, indices); + + return newIndices; + } + + /// Search for the given key within the given indices and elements arrays. If + /// an entry already exists for that key, return a pointer to the element. If + /// no entry exists, return a pointer to the location in the indices array + /// where the index of the new element would be stored. + template + static std::pair *> + find(const KeyTy &key, IndexStorage *indices, size_t elementCount, + ElemTy *elements) { + if (!indices) + return {nullptr, nullptr}; + auto hash = hash_value(key); + auto indicesMask = indices->Mask.load(std::memory_order_relaxed); + + auto i = hash & indicesMask; + while (true) { + // Index 0 is used for the mask and is not actually an index. + if (i == 0) + i++; + + auto *indexPtr = &indices->at(i); + auto index = indexPtr->load(std::memory_order_acquire); + // Element indices are 1-based, 0 means no entry. + if (index == 0) + return {nullptr, indexPtr}; + if (index - 1 < elementCount) { + auto *candidate = &elements[index - 1]; + if (candidate->matchesKey(key)) + return {candidate, nullptr}; + } + + i = (i + 1) & indicesMask; + } + } + +public: + // This type cannot be safely copied or moved. + ConcurrentReadableHashMap(const ConcurrentReadableHashMap &) = delete; + ConcurrentReadableHashMap(ConcurrentReadableHashMap &&) = delete; + ConcurrentReadableHashMap & + operator=(const ConcurrentReadableHashMap &) = delete; + + ConcurrentReadableHashMap() + : ReaderCount(0), ElementCount(0), Elements(nullptr), Indices(nullptr), + ElementCapacity(0) {} + + ~ConcurrentReadableHashMap() { + assert(ReaderCount.load(std::memory_order_acquire) == 0 && + "deallocating ConcurrentReadableHashMap with outstanding snapshots"); + FreeListNode::freeAll(&FreeList); + } + + /// Readers take a snapshot of the hash map, then work with the snapshot. + class Snapshot { + ConcurrentReadableHashMap *Map; + IndexStorage *Indices; + ElemTy *Elements; + size_t ElementCount; + + public: + Snapshot(ConcurrentReadableHashMap *map, IndexStorage *indices, + ElemTy *elements, size_t elementCount) + : Map(map), Indices(indices), Elements(elements), + ElementCount(elementCount) {} + + Snapshot(const Snapshot &other) + : Map(other.Map), Indices(other.Indices), Elements(other.Elements), + ElementCount(other.ElementCount) { + Map->incrementReaders(); + } + + ~Snapshot() { Map->decrementReaders(); } + + /// Search for an element matching the given key. Returns a pointer to the + /// found element, or nullptr if no matching element exists. + template const ElemTy *find(const KeyTy &key) { + if (!Indices || !ElementCount || !Elements) + return nullptr; + return ConcurrentReadableHashMap::find(key, Indices, ElementCount, + Elements) + .first; + } + }; + + /// Take a snapshot of the current state of the hash map. + Snapshot snapshot() { + incrementReaders(); + + // Carefully loading the indices, element count, and elements pointer in + // order ensures a consistent view of the table with respect to concurrent + // inserts. However, this is not sufficient to avoid an inconsistent view + // with respect to concurrent clears. The danger scenario is: + // + // 1. Read indices and elementCount from a table with N entries. + // 2. Another thread clears the table. + // 3. Another thread inserts M entries, where M < N. + // 4. The reader thread reads elements. + // 5. The reader thread performs a find. The key's hash leads us to an index + // I, where > M. + // 6. The reader thread reads from element I, which is off the end of the + // elements array. + // + // To avoid this, read the elements pointer twice, at the beginning and end. + // If the values are not the same then there may have been a clear in the + // middle, so we retry. This will have false positives: a new element + // pointer can just mean a concurrent insert that triggered a resize of the + // elements array. This is harmless aside from a small performance hit, and + // should not happen often. + IndexStorage *indices; + size_t elementCount; + ElemTy *elements; + ElemTy *elements2; + do { + elements = Elements.load(std::memory_order_acquire); + indices = Indices.load(std::memory_order_acquire); + elementCount = ElementCount.load(std::memory_order_acquire); + elements2 = Elements.load(std::memory_order_acquire); + } while (elements != elements2); + + return Snapshot(this, indices, elements, elementCount); + } + + /// Get an element by key, or insert a new element for that key if one is not + /// already present. Invoke `call` with the pointer to the element. BEWARE: + /// `call` is invoked with the internal writer lock held, keep work to a + /// minimum. + /// + /// `call` is passed the following parameters: + /// - `element`: the pointer to the element corresponding to `key` + /// - `created`: true if the element is newly created, false if it already + /// exists + /// `call` returns a `bool`. When `created` is `true`, the return values mean: + /// - `true` the new entry is to be kept + /// - `false` indicates that the new entry is discarded + /// If the new entry is kept, then the new element MUST be initialized, and + /// have a hash value that matches the hash value of `key`. + /// + /// The return value is ignored when `created` is `false`. + template + void getOrInsert(KeyTy key, const Call &call) { + ScopedLock guard(WriterLock); + + auto *indices = Indices.load(std::memory_order_relaxed); + if (!indices) + indices = resize(indices, 0, nullptr); + + auto indicesMask = indices->Mask.load(std::memory_order_relaxed); + auto elementCount = ElementCount.load(std::memory_order_relaxed); + auto *elements = Elements.load(std::memory_order_relaxed); + + auto found = find(key, indices, elementCount, elements); + if (found.first) { + call(found.first, false); + deallocateFreeListIfSafe(); + return; + } + + // The actual capacity is indicesMask + 1. The number of slots in use is + // elementCount + 1, since the mask also takes a slot. + auto emptyCount = (indicesMask + 1) - (elementCount + 1); + auto proportion = (indicesMask + 1) / emptyCount; + if (proportion >= ResizeProportion) { + indices = resize(indices, indicesMask, elements); + found = find(key, indices, elementCount, elements); + assert(!found.first && "Shouldn't suddenly find the key after rehashing"); + } + + if (elementCount >= ElementCapacity) { + elements = resize(elements, elementCount); + } + auto *element = &elements[elementCount]; + + // Order matters: fill out the element, then update the count, + // then update the index. + bool keep = call(element, true); + if (keep) { + assert(hash_value(key) == hash_value(*element) && + "Element must have the same hash code as its key."); + ElementCount.store(elementCount + 1, std::memory_order_release); + found.second->store(elementCount + 1, std::memory_order_release); + } + + deallocateFreeListIfSafe(); + } + + /// Clear the hash table, freeing (when safe) all memory currently used for + /// indices and elements. + void clear() { + ScopedLock guard(WriterLock); + + auto *indices = Indices.load(std::memory_order_relaxed); + auto *elements = Elements.load(std::memory_order_relaxed); + + // Order doesn't matter here, snapshots will gracefully handle any field + // being NULL/0 while the others are not. + Indices.store(nullptr, std::memory_order_relaxed); + ElementCount.store(0, std::memory_order_relaxed); + Elements.store(nullptr, std::memory_order_relaxed); + ElementCapacity = 0; + + FreeListNode::add(&FreeList, indices); + FreeListNode::add(&FreeList, elements); + + deallocateFreeListIfSafe(); + } +}; + } // end namespace swift #endif // SWIFT_RUNTIME_CONCURRENTUTILS_H diff --git a/include/swift/Runtime/Debug.h b/include/swift/Runtime/Debug.h index 86e19642e51a7..f14e8d16f1554 100644 --- a/include/swift/Runtime/Debug.h +++ b/include/swift/Runtime/Debug.h @@ -21,7 +21,6 @@ #include "swift/Runtime/Unreachable.h" #include #include -#include #include #include @@ -248,39 +247,6 @@ std::atomic _swift_debug_metadataAllocationBacktraceList; SWIFT_RUNTIME_STDLIB_SPI const void * const _swift_debug_protocolConformanceStatePointer; -SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE -inline static int swift_asprintf(char **strp, const char *fmt, ...) { - va_list args; - va_start(args, fmt); -#if defined(_WIN32) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wuninitialized" - int len = _vscprintf(fmt, args); -#pragma GCC diagnostic pop - if (len < 0) { - va_end(args); - return -1; - } - char *buffer = static_cast(malloc(len + 1)); - if (!buffer) { - va_end(args); - return -1; - } - int result = vsprintf(buffer, fmt, args); - if (result < 0) { - va_end(args); - free(buffer); - return -1; - } - *strp = buffer; -#else - int result = vasprintf(strp, fmt, args); -#endif - va_end(args); - return result; -} - - // namespace swift } diff --git a/include/swift/Runtime/Mutex.h b/include/swift/Runtime/Mutex.h index 019bd5b3b913a..aff2005d87514 100644 --- a/include/swift/Runtime/Mutex.h +++ b/include/swift/Runtime/Mutex.h @@ -20,12 +20,18 @@ #include -#if (defined(__APPLE__) || defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)) +#if __has_include() +#include +#endif + +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME +#include "swift/Runtime/MutexSingleThreaded.h" +#elif defined(_POSIX_THREADS) #include "swift/Runtime/MutexPThread.h" #elif defined(_WIN32) #include "swift/Runtime/MutexWin32.h" #elif defined(__wasi__) -#include "swift/Runtime/MutexWASI.h" +#include "swift/Runtime/MutexSingleThreaded.h" #else #error "Implement equivalent of MutexPThread.h/cpp for your platform." #endif diff --git a/include/swift/Runtime/MutexWASI.h b/include/swift/Runtime/MutexSingleThreaded.h similarity index 82% rename from include/swift/Runtime/MutexWASI.h rename to include/swift/Runtime/MutexSingleThreaded.h index 153a5f87b11dd..4a25e9091b3d5 100644 --- a/include/swift/Runtime/MutexWASI.h +++ b/include/swift/Runtime/MutexSingleThreaded.h @@ -1,4 +1,4 @@ -//===--- MutexWASI.h - -----------------------------------------*- C++ -*-===// +//===--- MutexSingleThreaded.h - --------------------------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // @@ -10,16 +10,12 @@ // //===----------------------------------------------------------------------===// // -// No-op implementation of locks for the WebAssembly System Interface. The -// implementation does not need to perform locking, because as of January 2020 -// WebAssembly does not support threads. -// See the current status at https://github.com/WebAssembly/proposals and -// https://github.com/webassembly/threads +// No-op implementation of locks for single-threaded environments. // //===----------------------------------------------------------------------===// -#ifndef SWIFT_RUNTIME_MUTEX_WASI_H -#define SWIFT_RUNTIME_MUTEX_WASI_H +#ifndef SWIFT_RUNTIME_MUTEX_SINGLE_THREADED_H +#define SWIFT_RUNTIME_MUTEX_SINGLE_THREADED_H namespace swift { diff --git a/include/swift/Runtime/Once.h b/include/swift/Runtime/Once.h index 95265cfcda794..190d74654b256 100644 --- a/include/swift/Runtime/Once.h +++ b/include/swift/Runtime/Once.h @@ -22,7 +22,11 @@ namespace swift { -#ifdef __APPLE__ +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + +typedef bool swift_once_t; + +#elif defined(__APPLE__) // On OS X and iOS, swift_once_t matches dispatch_once_t. typedef long swift_once_t; diff --git a/include/swift/Runtime/Portability.h b/include/swift/Runtime/Portability.h index 9e4fc418e162f..cd19b2c4193ba 100644 --- a/include/swift/Runtime/Portability.h +++ b/include/swift/Runtime/Portability.h @@ -16,8 +16,47 @@ #ifndef SWIFT_RUNTIME_PORTABILITY_H #define SWIFT_RUNTIME_PORTABILITY_H + +#include #include +#include +#include size_t _swift_strlcpy(char *dst, const char *src, size_t maxlen); +// Skip the attribute when included by the compiler. +#ifdef SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE +SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE +#endif +inline static int swift_asprintf(char **strp, const char *fmt, ...) { + va_list args; + va_start(args, fmt); +#if defined(_WIN32) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuninitialized" + int len = _vscprintf(fmt, args); +#pragma GCC diagnostic pop + if (len < 0) { + va_end(args); + return -1; + } + char *buffer = static_cast(malloc(len + 1)); + if (!buffer) { + va_end(args); + return -1; + } + int result = vsprintf(buffer, fmt, args); + if (result < 0) { + va_end(args); + free(buffer); + return -1; + } + *strp = buffer; +#else + int result = vasprintf(strp, fmt, args); +#endif + va_end(args); + return result; +} + #endif diff --git a/include/swift/SIL/LoopInfo.h b/include/swift/SIL/LoopInfo.h index 4bcdc47d253c6..200797c1a76d4 100644 --- a/include/swift/SIL/LoopInfo.h +++ b/include/swift/SIL/LoopInfo.h @@ -50,6 +50,16 @@ class SILLoop : public llvm::LoopBase { /// this loop by unrolling or versioning. bool canDuplicate(SILInstruction *Inst) const; + void getExitingAndLatchBlocks( + SmallVectorImpl &ExitingAndLatchBlocks) const { + this->getExitingBlocks(ExitingAndLatchBlocks); + SILBasicBlock *header = getHeader(); + for (auto *predBB : header->getPredecessorBlocks()) { + if (contains(predBB) && !this->isLoopExiting(predBB)) + ExitingAndLatchBlocks.push_back(predBB); + } + } + private: friend class llvm::LoopInfoBase; diff --git a/include/swift/SIL/OptimizationRemark.h b/include/swift/SIL/OptimizationRemark.h index 47318c4cc6765..32842dabb5543 100644 --- a/include/swift/SIL/OptimizationRemark.h +++ b/include/swift/SIL/OptimizationRemark.h @@ -57,7 +57,6 @@ struct ArgumentKeyKind { InnerTy innerValue; ArgumentKeyKind(InnerTy value) : innerValue(value) {} - ArgumentKeyKind(const ArgumentKeyKind &kind) : innerValue(kind.innerValue) {} operator InnerTy() const { return innerValue; } diff --git a/include/swift/SIL/PrettyStackTrace.h b/include/swift/SIL/PrettyStackTrace.h index 7b62b3d6ec8ac..1b35d3ebf3c7f 100644 --- a/include/swift/SIL/PrettyStackTrace.h +++ b/include/swift/SIL/PrettyStackTrace.h @@ -39,7 +39,7 @@ class PrettyStackTraceSILLocation : public llvm::PrettyStackTraceEntry { PrettyStackTraceSILLocation(const char *action, SILLocation loc, ASTContext &C) : Loc(loc), Action(action), Context(C) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; @@ -62,7 +62,7 @@ class PrettyStackTraceSILFunction : public llvm::PrettyStackTraceEntry { PrettyStackTraceSILFunction(llvm::Twine &&twine, const SILFunction *func) : func(func), data(), action(twine.toNullTerminatedStringRef(data)) {} - virtual void print(llvm::raw_ostream &os) const; + virtual void print(llvm::raw_ostream &os) const override; protected: void printFunctionInfo(llvm::raw_ostream &out) const; @@ -77,7 +77,7 @@ class PrettyStackTraceSILNode : public llvm::PrettyStackTraceEntry { PrettyStackTraceSILNode(const char *action, const SILNode *node) : Node(node), Action(action) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; } // end namespace swift diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index e7c544992dddc..c27d345ee8ae2 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -2905,10 +2905,10 @@ template void SILCloner:: visitLinearFunctionExtractInst(LinearFunctionExtractInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - recordClonedInstruction( - Inst, getBuilder().createLinearFunctionExtract( - getOpLocation(Inst->getLoc()), Inst->getExtractee(), - getOpValue(Inst->getFunctionOperand()))); + recordClonedInstruction(Inst, getBuilder().createLinearFunctionExtract( + getOpLocation(Inst->getLoc()), + Inst->getExtractee(), + getOpValue(Inst->getOperand()))); } template diff --git a/include/swift/SIL/SILConstants.h b/include/swift/SIL/SILConstants.h index 4e04f3e8044e7..eb53bad64701f 100644 --- a/include/swift/SIL/SILConstants.h +++ b/include/swift/SIL/SILConstants.h @@ -73,7 +73,7 @@ class SymbolicValueBumpAllocator : public SymbolicValueAllocator { SymbolicValueBumpAllocator() {} ~SymbolicValueBumpAllocator() {} - void *allocate(unsigned long byteSize, unsigned alignment) { + void *allocate(unsigned long byteSize, unsigned alignment) override { return bumpAllocator.Allocate(byteSize, alignment); } }; diff --git a/include/swift/SIL/SILDebugScope.h b/include/swift/SIL/SILDebugScope.h index ce9ad200ac77e..0349ed6dbffc8 100644 --- a/include/swift/SIL/SILDebugScope.h +++ b/include/swift/SIL/SILDebugScope.h @@ -66,6 +66,28 @@ class SILDebugScope : public SILAllocated { /// into. SILFunction *getParentFunction() const; + /// If this is a debug scope associated with an inlined call site, return the + /// SILLocation associated with the call site resulting from the final + /// inlining. + /// + /// This allows one to emit diagnostics based off of inlined code's final + /// location in the function that was inlined into. + SILLocation getOutermostInlineLocation() const { + if (!InlinedCallSite) + return SILLocation::invalid(); + + auto *scope = this; + do { + scope = scope->InlinedCallSite; + } while (scope->InlinedCallSite); + + SILLocation callSite = scope->Loc; + if (callSite.isNull() || !callSite.isASTNode()) + return SILLocation::invalid(); + + return callSite; + } + void print(SourceManager &SM, llvm::raw_ostream &OS = llvm::errs(), unsigned Indent = 0) const; diff --git a/include/swift/SIL/SILDebuggerClient.h b/include/swift/SIL/SILDebuggerClient.h index e6c2bf7a2bd27..1f8af82d78fb1 100644 --- a/include/swift/SIL/SILDebuggerClient.h +++ b/include/swift/SIL/SILDebuggerClient.h @@ -38,11 +38,11 @@ class SILDebuggerClient : public DebuggerClient { virtual SILValue emitLValueForVariable(VarDecl *var, SILBuilder &builder) = 0; - inline SILDebuggerClient *getAsSILDebuggerClient() { + inline SILDebuggerClient *getAsSILDebuggerClient() override { return this; } private: - virtual void anchor(); + virtual void anchor() override; }; } // namespace swift diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h index 8125736fc391f..ec81558ab3179 100644 --- a/include/swift/SIL/SILFunction.h +++ b/include/swift/SIL/SILFunction.h @@ -121,6 +121,7 @@ class SILFunction enum class Purpose : uint8_t { None, GlobalInit, + GlobalInitOnceFunction, LazyPropertyGetter }; @@ -274,9 +275,6 @@ class SILFunction /// that it may have unboxed capture (i.e. @inout_aliasable parameters). unsigned IsWithoutActuallyEscapingThunk : 1; - /// True if this function is an async function. - unsigned IsAsync : 1; - /// If != OptimizationMode::NotSet, the optimization mode specified with an /// function attribute. unsigned OptMode : NumOptimizationModeBits; @@ -504,9 +502,7 @@ class SILFunction IsWithoutActuallyEscapingThunk = val; } - bool isAsync() const { return IsAsync; } - - void setAsync(bool val = true) { IsAsync = val; } + bool isAsync() const { return LoweredType->isAsync(); } /// Returns the calling convention used by this entry point. SILFunctionTypeRepresentation getRepresentation() const { @@ -837,6 +833,10 @@ class SILFunction /// function itself does not need this attribute. It is private and only /// called within the addressor. bool isGlobalInit() const { return specialPurpose == Purpose::GlobalInit; } + + bool isGlobalInitOnceFunction() const { + return specialPurpose == Purpose::GlobalInitOnceFunction; + } bool isLazyPropertyGetter() const { return specialPurpose == Purpose::LazyPropertyGetter; diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h index d504f37085831..36ebd2ef858da 100644 --- a/include/swift/SIL/SILInstruction.h +++ b/include/swift/SIL/SILInstruction.h @@ -8364,14 +8364,11 @@ class DifferentiableFunctionExtractInst /// representing a bundle of the original function and the transpose function, /// extract the specified function. class LinearFunctionExtractInst - : public InstructionBase< - SILInstructionKind::LinearFunctionExtractInst, - SingleValueInstruction> { + : public UnaryInstructionBase { private: /// The extractee. LinearDifferentiableFunctionTypeComponent extractee; - /// The list containing the `@differentiable(linear)` function operand. - FixedOperandList<1> operands; static SILType getExtracteeType(SILValue function, @@ -8387,10 +8384,6 @@ class LinearFunctionExtractInst LinearDifferentiableFunctionTypeComponent getExtractee() const { return extractee; } - - SILValue getFunctionOperand() const { return operands[0].get(); } - ArrayRef getAllOperands() const { return operands.asArray(); } - MutableArrayRef getAllOperands() { return operands.asArray(); } }; /// DifferentiabilityWitnessFunctionInst - Looks up a differentiability witness diff --git a/include/swift/SIL/SILInstructionWorklist.h b/include/swift/SIL/SILInstructionWorklist.h index 9f4b399b60f4a..6df8e06cc0d5b 100644 --- a/include/swift/SIL/SILInstructionWorklist.h +++ b/include/swift/SIL/SILInstructionWorklist.h @@ -30,6 +30,9 @@ /// //===----------------------------------------------------------------------===// +#ifndef SWIFT_SIL_SILINSTRUCTIONWORKLIST_H +#define SWIFT_SIL_SILINSTRUCTIONWORKLIST_H + #include "swift/Basic/BlotSetVector.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILValue.h" @@ -342,3 +345,5 @@ class SmallSILInstructionWorklist final }; } // end namespace swift + +#endif // SWIFT_SIL_SILINSTRUCTIONWORKLIST_H diff --git a/include/swift/SIL/SILOpenedArchetypesTracker.h b/include/swift/SIL/SILOpenedArchetypesTracker.h index 508eb366cdcf9..6c89487ceb4b9 100644 --- a/include/swift/SIL/SILOpenedArchetypesTracker.h +++ b/include/swift/SIL/SILOpenedArchetypesTracker.h @@ -99,10 +99,10 @@ class SILOpenedArchetypesTracker : public DeleteNotificationHandler { bool hasUnresolvedOpenedArchetypeDefinitions(); // Handling of instruction removal notifications. - bool needsNotifications() { return true; } + bool needsNotifications() override { return true; } // Handle notifications about removals of instructions. - void handleDeleteNotification(SILNode *node); + void handleDeleteNotification(SILNode *node) override; // Dump the contents. void dump() const; diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h index aba919ee0090c..344087f0a1aaf 100644 --- a/include/swift/SIL/TypeLowering.h +++ b/include/swift/SIL/TypeLowering.h @@ -992,7 +992,6 @@ class TypeConverter { /// Given a function type, yield its bridged formal type. CanAnyFunctionType getBridgedFunctionType(AbstractionPattern fnPattern, CanAnyFunctionType fnType, - AnyFunctionType::ExtInfo extInfo, Bridgeability bridging); /// Given a referenced value and the substituted formal type of a diff --git a/include/swift/SILOptimizer/Analysis/LoopRegionAnalysis.h b/include/swift/SILOptimizer/Analysis/LoopRegionAnalysis.h index 285e694723617..4975c4bf09787 100644 --- a/include/swift/SILOptimizer/Analysis/LoopRegionAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/LoopRegionAnalysis.h @@ -726,8 +726,9 @@ class LoopRegion { return getSubregionData().RPONumOfHeaderBlock; } - void dump() const; - void print(llvm::raw_ostream &os, bool insertSpaces = false) const; + void dump(bool isVerbose = false) const; + void print(llvm::raw_ostream &os, bool isShort = false, + bool isVerbose = false) const; void dumpName() const; void printName(llvm::raw_ostream &os) const; diff --git a/include/swift/SILOptimizer/Differentiation/Common.h b/include/swift/SILOptimizer/Differentiation/Common.h index 2f996740b08b6..90e3c26690928 100644 --- a/include/swift/SILOptimizer/Differentiation/Common.h +++ b/include/swift/SILOptimizer/Differentiation/Common.h @@ -271,59 +271,6 @@ inline void createEntryArguments(SILFunction *f) { } } -/// Helper class for visiting basic blocks in post-order post-dominance order, -/// based on a worklist algorithm. -class PostOrderPostDominanceOrder { - SmallVector buffer; - PostOrderFunctionInfo *postOrderInfo; - size_t srcIdx = 0; - -public: - /// Constructor. - /// \p root The root of the post-dominator tree. - /// \p postOrderInfo The post-order info of the function. - /// \p capacity Should be the number of basic blocks in the dominator tree to - /// reduce memory allocation. - PostOrderPostDominanceOrder(DominanceInfoNode *root, - PostOrderFunctionInfo *postOrderInfo, - int capacity = 0) - : postOrderInfo(postOrderInfo) { - buffer.reserve(capacity); - buffer.push_back(root); - } - - /// Get the next block from the worklist. - DominanceInfoNode *getNext() { - if (srcIdx == buffer.size()) - return nullptr; - return buffer[srcIdx++]; - } - - /// Pushes the dominator children of a block onto the worklist in post-order. - void pushChildren(DominanceInfoNode *node) { - pushChildrenIf(node, [](SILBasicBlock *) { return true; }); - } - - /// Conditionally pushes the dominator children of a block onto the worklist - /// in post-order. - template - void pushChildrenIf(DominanceInfoNode *node, Pred pred) { - SmallVector children; - for (auto *child : *node) - children.push_back(child); - llvm::sort(children.begin(), children.end(), - [&](DominanceInfoNode *n1, DominanceInfoNode *n2) { - return postOrderInfo->getPONumber(n1->getBlock()) < - postOrderInfo->getPONumber(n2->getBlock()); - }); - for (auto *child : children) { - SILBasicBlock *childBB = child->getBlock(); - if (pred(childBB)) - buffer.push_back(child); - } - } -}; - /// Cloner that remaps types using the target function's generic environment. class BasicTypeSubstCloner final : public TypeSubstCloner { diff --git a/include/swift/SILOptimizer/PassManager/PrettyStackTrace.h b/include/swift/SILOptimizer/PassManager/PrettyStackTrace.h index f00bba619e533..1ebae9671d7da 100644 --- a/include/swift/SILOptimizer/PassManager/PrettyStackTrace.h +++ b/include/swift/SILOptimizer/PassManager/PrettyStackTrace.h @@ -30,7 +30,7 @@ class PrettyStackTraceSILFunctionTransform PrettyStackTraceSILFunctionTransform(SILFunctionTransform *SFT, unsigned PassNumber); - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; class PrettyStackTraceSILModuleTransform : public llvm::PrettyStackTraceEntry { @@ -41,7 +41,7 @@ class PrettyStackTraceSILModuleTransform : public llvm::PrettyStackTraceEntry { PrettyStackTraceSILModuleTransform(SILModuleTransform *SMT, unsigned PassNumber) : SMT(SMT), PassNumber(PassNumber) {} - virtual void print(llvm::raw_ostream &OS) const; + virtual void print(llvm::raw_ostream &OS) const override; }; } // end namespace swift diff --git a/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h b/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h index 39b3c6ffa9ad1..cee8fd7ed8bc1 100644 --- a/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h +++ b/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h @@ -236,7 +236,7 @@ class LSValue : public LSBase { } /// Returns whether the LSValue has been initialized properly. - bool isValid() const { + bool isValid() const override { if (CoveringValue) return true; return LSBase::isValid(); @@ -261,7 +261,7 @@ class LSValue : public LSBase { return Path.getValue().createExtract(Base, Inst, true); } - void print(llvm::raw_ostream &os) { + void print(llvm::raw_ostream &os) override { if (CoveringValue) { os << "Covering Value"; return; diff --git a/include/swift/SILOptimizer/Utils/ValueLifetime.h b/include/swift/SILOptimizer/Utils/ValueLifetime.h index d4e5bb5b1ba53..92af2083ef62f 100644 --- a/include/swift/SILOptimizer/Utils/ValueLifetime.h +++ b/include/swift/SILOptimizer/Utils/ValueLifetime.h @@ -28,6 +28,24 @@ namespace swift { /// of the analysis and can be a super set of the uses of the SILValue /// e.g. it can be the set of transitive uses of the SILValue. class ValueLifetimeAnalysis { + /// The instruction or argument that define the value. + PointerUnion defValue; + + /// The set of blocks where the value is live. + llvm::SmallSetVector liveBlocks; + + /// The set of instructions where the value is used, or the users-list + /// provided with the constructor. + llvm::SmallPtrSet userSet; + + /// Indicates whether the basic block containing def has users of def that + /// precede def. This field is initialized by propagateLiveness. + bool hasUsersBeforeDef; + + /// Critical edges that couldn't be split to compute the frontier. This could + /// be non-empty when the analysis is invoked with DontModifyCFG mode. + llvm::SmallVector, 16> criticalEdges; + public: /// The lifetime frontier for the value. It is the list of instructions @@ -35,13 +53,13 @@ class ValueLifetimeAnalysis { /// end the value's lifetime. using Frontier = SmallVector; - /// Constructor for the value \p Def with a specific range of users. + /// Constructor for the value \p def with a specific range of users. /// /// We templatize over the RangeTy so that we can initialize /// ValueLifetimeAnalysis with misc iterators including transform /// iterators. template - ValueLifetimeAnalysis(SILInstruction *def, const RangeTy &userRange) + ValueLifetimeAnalysis(decltype(defValue) def, const RangeTy &userRange) : defValue(def), userSet(userRange.begin(), userRange.end()) { propagateLiveness(); } @@ -102,7 +120,7 @@ class ValueLifetimeAnalysis { /// Returns true if the value is alive at the begin of block \p bb. bool isAliveAtBeginOfBlock(SILBasicBlock *bb) { return liveBlocks.count(bb) && - (bb != defValue->getParent() || hasUsersBeforeDef); + (hasUsersBeforeDef || bb != getDefValueParentBlock()); } /// Checks if there is a dealloc_ref inside the value's live range. @@ -112,24 +130,19 @@ class ValueLifetimeAnalysis { void dump() const; private: + SILFunction *getFunction() const { + if (auto *inst = defValue.dyn_cast()) { + return inst->getFunction(); + } + return defValue.get()->getFunction(); + } - /// The value. - SILInstruction *defValue; - - /// The set of blocks where the value is live. - llvm::SmallSetVector liveBlocks; - - /// The set of instructions where the value is used, or the users-list - /// provided with the constructor. - llvm::SmallPtrSet userSet; - - /// Indicates whether the basic block containing def has users of def that - /// precede def. This field is initialized by propagateLiveness. - bool hasUsersBeforeDef; - - /// Critical edges that couldn't be split to compute the frontier. This could - /// be non-empty when the analysis is invoked with DontModifyCFG mode. - llvm::SmallVector, 16> criticalEdges; + SILBasicBlock *getDefValueParentBlock() const { + if (auto *inst = defValue.dyn_cast()) { + return inst->getParent(); + } + return defValue.get()->getParent(); + } /// Propagates the liveness information up the control flow graph. void propagateLiveness(); diff --git a/include/swift/Serialization/ModuleDependencyScanner.h b/include/swift/Serialization/ModuleDependencyScanner.h new file mode 100644 index 0000000000000..07006770d8f49 --- /dev/null +++ b/include/swift/Serialization/ModuleDependencyScanner.h @@ -0,0 +1,110 @@ +//===--- ModuleDependencyScanner.h - Import Swift modules --------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#include "swift/AST/ASTContext.h" +#include "swift/Frontend/ModuleInterfaceLoader.h" +#include "swift/Serialization/SerializedModuleLoader.h" + +namespace swift { + /// A module "loader" that looks for .swiftinterface and .swiftmodule files + /// for the purpose of determining dependencies, but does not attempt to + /// load the module files. + class ModuleDependencyScanner : public SerializedModuleLoaderBase { + /// The module we're scanning dependencies of. + Identifier moduleName; + + /// Scan the given interface file to determine dependencies. + llvm::ErrorOr scanInterfaceFile( + Twine moduleInterfacePath, bool isFramework); + + InterfaceSubContextDelegate &astDelegate; + public: + Optional dependencies; + + /// Describes the kind of dependencies this scanner is able to identify + ModuleDependenciesKind dependencyKind; + + ModuleDependencyScanner( + ASTContext &ctx, ModuleLoadingMode LoadMode, Identifier moduleName, + InterfaceSubContextDelegate &astDelegate, + ModuleDependenciesKind dependencyKind = ModuleDependenciesKind::Swift) + : SerializedModuleLoaderBase(ctx, nullptr, LoadMode, + /*IgnoreSwiftSourceInfoFile=*/true), + moduleName(moduleName), astDelegate(astDelegate), + dependencyKind(dependencyKind) {} + + std::error_code findModuleFilesInDirectory( + AccessPathElem ModuleID, + const SerializedModuleBaseName &BaseName, + SmallVectorImpl *ModuleInterfacePath, + std::unique_ptr *ModuleBuffer, + std::unique_ptr *ModuleDocBuffer, + std::unique_ptr *ModuleSourceInfoBuffer, + bool IsFramework) override; + + virtual void collectVisibleTopLevelModuleNames( + SmallVectorImpl &names) const override { + llvm_unreachable("Not used"); + } + }; + + /// A ModuleLoader that loads placeholder dependency module stubs specified in + /// -placeholder-dependency-module-map-file + /// This loader is used only in dependency scanning to inform the scanner that a + /// set of modules constitute placeholder dependencies that are not visible to the + /// scanner but will nevertheless be provided by the scanner's clients. + /// This "loader" will not attempt to load any module files. + class PlaceholderSwiftModuleScanner : public ModuleDependencyScanner { + /// Scan the given placeholder module map + void parsePlaceholderModuleMap(StringRef fileName) { + ExplicitModuleMapParser parser(Allocator); + auto result = + parser.parseSwiftExplicitModuleMap(fileName, PlaceholderDependencyModuleMap); + if (result == std::errc::invalid_argument) { + Ctx.Diags.diagnose(SourceLoc(), + diag::placeholder_dependency_module_map_corrupted, + fileName); + } + else if (result == std::errc::no_such_file_or_directory) { + Ctx.Diags.diagnose(SourceLoc(), + diag::placeholder_dependency_module_map_missing, + fileName); + } + } + + llvm::StringMap PlaceholderDependencyModuleMap; + llvm::BumpPtrAllocator Allocator; + + public: + PlaceholderSwiftModuleScanner(ASTContext &ctx, ModuleLoadingMode LoadMode, + Identifier moduleName, + StringRef PlaceholderDependencyModuleMap, + InterfaceSubContextDelegate &astDelegate) + : ModuleDependencyScanner(ctx, LoadMode, moduleName, astDelegate, + ModuleDependenciesKind::SwiftPlaceholder) { + + // FIXME: Find a better place for this map to live, to avoid + // doing the parsing on every module. + if (!PlaceholderDependencyModuleMap.empty()) { + parsePlaceholderModuleMap(PlaceholderDependencyModuleMap); + } + } + + std::error_code findModuleFilesInDirectory( + AccessPathElem ModuleID, const SerializedModuleBaseName &BaseName, + SmallVectorImpl *ModuleInterfacePath, + std::unique_ptr *ModuleBuffer, + std::unique_ptr *ModuleDocBuffer, + std::unique_ptr *ModuleSourceInfoBuffer, + bool IsFramework) override; + }; +} diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h index ec2ad4a8a29ab..1cda5272cbb7a 100644 --- a/include/swift/Serialization/SerializedModuleLoader.h +++ b/include/swift/Serialization/SerializedModuleLoader.h @@ -73,12 +73,12 @@ class SerializedModuleLoaderBase : public ModuleLoader { StringRef extension) const; using AccessPathElem = Located; - bool findModule(AccessPathElem moduleID, - SmallVectorImpl *moduleInterfacePath, - std::unique_ptr *moduleBuffer, - std::unique_ptr *moduleDocBuffer, - std::unique_ptr *moduleSourceInfoBuffer, - bool &isFramework, bool &isSystemModule); + virtual bool findModule(AccessPathElem moduleID, + SmallVectorImpl *moduleInterfacePath, + std::unique_ptr *moduleBuffer, + std::unique_ptr *moduleDocBuffer, + std::unique_ptr *moduleSourceInfoBuffer, + bool &isFramework, bool &isSystemModule); /// Attempts to search the provided directory for a loadable serialized /// .swiftmodule with the provided `ModuleFilename`. Subclasses must @@ -98,7 +98,8 @@ class SerializedModuleLoaderBase : public ModuleLoader { SmallVectorImpl *ModuleInterfacePath, std::unique_ptr *ModuleBuffer, std::unique_ptr *ModuleDocBuffer, - std::unique_ptr *ModuleSourceInfoBuffer) = 0; + std::unique_ptr *ModuleSourceInfoBuffer, + bool IsFramework) = 0; std::error_code openModuleFile( @@ -229,7 +230,8 @@ class ImplicitSerializedModuleLoader : public SerializedModuleLoaderBase { SmallVectorImpl *ModuleInterfacePath, std::unique_ptr *ModuleBuffer, std::unique_ptr *ModuleDocBuffer, - std::unique_ptr *ModuleSourceInfoBuffer) override; + std::unique_ptr *ModuleSourceInfoBuffer, + bool IsFramework) override; bool maybeDiagnoseTargetMismatch( SourceLoc sourceLocation, @@ -274,7 +276,8 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase { SmallVectorImpl *ModuleInterfacePath, std::unique_ptr *ModuleBuffer, std::unique_ptr *ModuleDocBuffer, - std::unique_ptr *ModuleSourceInfoBuffer) override; + std::unique_ptr *ModuleSourceInfoBuffer, + bool IsFramework) override; bool maybeDiagnoseTargetMismatch( SourceLoc sourceLocation, diff --git a/include/swift/Strings.h b/include/swift/Strings.h index 32a7bb2d0072c..69b29ff4a52b9 100644 --- a/include/swift/Strings.h +++ b/include/swift/Strings.h @@ -38,6 +38,10 @@ constexpr static const StringLiteral MANGLING_MODULE_OBJC = "__C"; constexpr static const StringLiteral MANGLING_MODULE_CLANG_IMPORTER = "__C_Synthesized"; +/// The name prefix for C++ template instantiation imported as a Swift struct. +constexpr static const StringLiteral CXX_TEMPLATE_INST_PREFIX = + "__CxxTemplateInst"; + constexpr static const StringLiteral SEMANTICS_PROGRAMTERMINATION_POINT = "programtermination_point"; diff --git a/include/swift/TBDGen/TBDGen.h b/include/swift/TBDGen/TBDGen.h index 72229a63707cc..b3d798f2c7d38 100644 --- a/include/swift/TBDGen/TBDGen.h +++ b/include/swift/TBDGen/TBDGen.h @@ -14,7 +14,6 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringSet.h" -#include "swift/AST/TBDGenRequests.h" #include "swift/Basic/Version.h" #include @@ -25,6 +24,7 @@ class raw_ostream; namespace swift { class FileUnit; class ModuleDecl; +class TBDGenDescriptor; /// Options for controlling the exact set of symbols included in the TBD /// output. @@ -38,6 +38,9 @@ struct TBDGenOptions { /// Only collect linker directive symbols. bool LinkerDirectivesOnly = false; + /// Whether to include only symbols with public linkage. + bool PublicSymbolsOnly = true; + /// The install_name to use in the TBD file. std::string InstallName; @@ -66,6 +69,7 @@ struct TBDGenOptions { return lhs.HasMultipleIGMs == rhs.HasMultipleIGMs && lhs.IsInstallAPI == rhs.IsInstallAPI && lhs.LinkerDirectivesOnly == rhs.LinkerDirectivesOnly && + lhs.PublicSymbolsOnly == rhs.PublicSymbolsOnly && lhs.InstallName == rhs.InstallName && lhs.ModuleLinkName == rhs.ModuleLinkName && lhs.CurrentVersion == rhs.CurrentVersion && @@ -82,8 +86,9 @@ struct TBDGenOptions { using namespace llvm; return hash_combine( opts.HasMultipleIGMs, opts.IsInstallAPI, opts.LinkerDirectivesOnly, - opts.InstallName, opts.ModuleLinkName, opts.CurrentVersion, - opts.CompatibilityVersion, opts.ModuleInstallNameMapPath, + opts.PublicSymbolsOnly, opts.InstallName, opts.ModuleLinkName, + opts.CurrentVersion, opts.CompatibilityVersion, + opts.ModuleInstallNameMapPath, hash_combine_range(opts.embedSymbolsFromModules.begin(), opts.embedSymbolsFromModules.end())); } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index f95561eb4befd..7a4648f45a459 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -18,6 +18,7 @@ #include "ClangTypeConverter.h" #include "ForeignRepresentationInfo.h" #include "SubstitutionMapStorage.h" +#include "swift/AST/ForeignAsyncConvention.h" #include "swift/AST/ClangModuleLoader.h" #include "swift/AST/ConcreteDeclRef.h" #include "swift/AST/DiagnosticEngine.h" @@ -281,6 +282,10 @@ struct ASTContext::Implementation { llvm::DenseMap ForeignErrorConventions; + /// Map from declarations to foreign async conventions. + llvm::DenseMap ForeignAsyncConventions; + /// Cache of previously looked-up precedence queries. AssociativityCacheType AssociativityCache; @@ -339,6 +344,10 @@ struct ASTContext::Implementation { /// LiteralExprs in fully-checked AST. llvm::DenseMap BuiltinInitWitness; + /// Mapping from the function decl to its original body's source range. This + /// is populated if the body is reparsed from other source buffers. + llvm::DenseMap OriginalBodySourceRanges; + /// Structure that captures data that is segregated into different /// arenas. struct Arena { @@ -1462,8 +1471,9 @@ bool ASTContext::hadError() const { /// Retrieve the arena from which we should allocate storage for a type. static AllocationArena getArena(RecursiveTypeProperties properties) { bool hasTypeVariable = properties.hasTypeVariable(); - return hasTypeVariable? AllocationArena::ConstraintSolver - : AllocationArena::Permanent; + bool hasHole = properties.hasTypeHole(); + return hasTypeVariable || hasHole ? AllocationArena::ConstraintSolver + : AllocationArena::Permanent; } void ASTContext::addSearchPath(StringRef searchPath, bool isFramework, @@ -1512,6 +1522,21 @@ Optional ASTContext::getModuleDependencies( return None; } +Optional +ASTContext::getSwiftModuleDependencies(StringRef moduleName, + ModuleDependenciesCache &cache, + InterfaceSubContextDelegate &delegate) { + for (auto &loader : getImpl().ModuleLoaders) { + if (loader.get() == getImpl().TheClangModuleLoader) + continue; + + if (auto dependencies = loader->getModuleDependencies(moduleName, cache, + delegate)) + return dependencies; + } + return None; +} + void ASTContext::loadExtensions(NominalTypeDecl *nominal, unsigned previousGeneration) { PrettyStackTraceDecl stackTrace("loading extensions for", nominal); @@ -2219,6 +2244,24 @@ AbstractFunctionDecl::getForeignErrorConvention() const { return it->second; } +void AbstractFunctionDecl::setForeignAsyncConvention( + const ForeignAsyncConvention &conv) { + assert(hasAsync() && "setting error convention on non-throwing decl"); + auto &conventionsMap = getASTContext().getImpl().ForeignAsyncConventions; + assert(!conventionsMap.count(this) && "error convention already set"); + conventionsMap.insert({this, conv}); +} + +Optional +AbstractFunctionDecl::getForeignAsyncConvention() const { + if (!hasAsync()) + return None; + auto &conventionsMap = getASTContext().getImpl().ForeignAsyncConventions; + auto it = conventionsMap.find(this); + if (it == conventionsMap.end()) return None; + return it->second; +} + Optional swift::getKnownFoundationEntity(StringRef name){ return llvm::StringSwitch>(name) #define FOUNDATION_ENTITY(Name) .Case(#Name, KnownFoundationEntity::Name) @@ -2339,6 +2382,17 @@ Type ErrorType::get(Type originalType) { return entry = new (mem) ErrorType(ctx, originalType, properties); } +Type HoleType::get(ASTContext &ctx, OriginatorType originator) { + assert(originator); + auto properties = reinterpret_cast(originator.getOpaqueValue()) + ->getRecursiveProperties(); + properties |= RecursiveTypeProperties::HasTypeHole; + + auto arena = getArena(properties); + return new (ctx, arena) + HoleType(ctx, originator, RecursiveTypeProperties::HasTypeHole); +} + BuiltinIntegerType *BuiltinIntegerType::get(BuiltinIntegerWidth BitWidth, const ASTContext &C) { assert(!BitWidth.isArbitraryWidth()); @@ -2780,6 +2834,7 @@ ReferenceStorageType *ReferenceStorageType::get(Type T, ReferenceOwnership ownership, const ASTContext &C) { assert(!T->hasTypeVariable()); // not meaningful in type-checker + assert(!T->hasHole()); switch (optionalityOf(ownership)) { case ReferenceOwnershipOptionality::Disallowed: assert(!T->getOptionalObjectType() && "optional type is disallowed"); @@ -2938,7 +2993,7 @@ isFunctionTypeCanonical(ArrayRef params, static RecursiveTypeProperties getGenericFunctionRecursiveProperties(ArrayRef params, Type result) { - static_assert(RecursiveTypeProperties::BitWidth == 11, + static_assert(RecursiveTypeProperties::BitWidth == 12, "revisit this if you add new recursive type properties"); RecursiveTypeProperties properties; @@ -3112,16 +3167,16 @@ FunctionType *FunctionType::get(ArrayRef params, return funcTy; } - Optional clangTypeInfo = info.getClangTypeInfo(); + auto clangTypeInfo = info.getClangTypeInfo(); size_t allocSize = totalSizeToAlloc( - params.size(), clangTypeInfo.hasValue() ? 1 : 0); + params.size(), clangTypeInfo.empty() ? 0 : 1); void *mem = ctx.Allocate(allocSize, alignof(FunctionType), arena); bool isCanonical = isFunctionTypeCanonical(params, result); - if (clangTypeInfo.hasValue()) { + if (!clangTypeInfo.empty()) { if (ctx.LangOpts.UseClangFunctionTypes) - isCanonical &= clangTypeInfo->type->isCanonicalUnqualified(); + isCanonical &= clangTypeInfo.getType()->isCanonicalUnqualified(); else isCanonical = false; } @@ -3143,8 +3198,8 @@ FunctionType::FunctionType(ArrayRef params, std::uninitialized_copy(params.begin(), params.end(), getTrailingObjects()); auto clangTypeInfo = info.getClangTypeInfo(); - if (clangTypeInfo.hasValue()) - *getTrailingObjects() = clangTypeInfo.getValue(); + if (!clangTypeInfo.empty()) + *getTrailingObjects() = clangTypeInfo; } void GenericFunctionType::Profile(llvm::FoldingSetNodeID &ID, @@ -3166,6 +3221,7 @@ GenericFunctionType *GenericFunctionType::get(GenericSignature sig, ExtInfo info) { assert(sig && "no generic signature for generic function type?!"); assert(!result->hasTypeVariable()); + assert(!result->hasHole()); llvm::FoldingSetNodeID id; GenericFunctionType::Profile(id, sig, params, result, info); @@ -3490,7 +3546,7 @@ CanSILFunctionType SILFunctionType::get( void *mem = ctx.Allocate(bytes, alignof(SILFunctionType)); RecursiveTypeProperties properties; - static_assert(RecursiveTypeProperties::BitWidth == 11, + static_assert(RecursiveTypeProperties::BitWidth == 12, "revisit this if you add new recursive type properties"); for (auto ¶m : params) properties |= param.getInterfaceType()->getRecursiveProperties(); @@ -3831,6 +3887,11 @@ CanOpenedArchetypeType OpenedArchetypeType::get(Type existential, protos.push_back(proto->getDecl()); auto layoutConstraint = layout.getLayoutConstraint(); + if (!layoutConstraint && layout.requiresClass()) { + layoutConstraint = LayoutConstraint::getLayoutConstraint( + LayoutConstraintKind::Class); + } + auto layoutSuperclass = layout.getSuperclass(); auto arena = AllocationArena::Permanent; @@ -3877,10 +3938,6 @@ CanType OpenedArchetypeType::getAny(Type existential) { return OpenedArchetypeType::get(existential); } -void TypeLoc::setInvalidType(ASTContext &C) { - Ty = ErrorType::get(C); -} - void SubstitutionMap::Storage::Profile( llvm::FoldingSetNodeID &id, GenericSignature genericSig, @@ -4437,16 +4494,29 @@ Type ASTContext::getBridgedToObjC(const DeclContext *dc, Type type, return Type(); } -const clang::Type * -ASTContext::getClangFunctionType(ArrayRef params, - Type resultTy, - FunctionTypeRepresentation trueRep) { +ClangTypeConverter &ASTContext::getClangTypeConverter() { auto &impl = getImpl(); if (!impl.Converter) { auto *cml = getClangModuleLoader(); impl.Converter.emplace(*this, cml->getClangASTContext(), LangOpts.Target); } - return impl.Converter.getValue().getFunctionType(params, resultTy, trueRep); + return impl.Converter.getValue(); +} + +const clang::Type * +ASTContext::getClangFunctionType(ArrayRef params, + Type resultTy, + FunctionTypeRepresentation trueRep) { + return getClangTypeConverter().getFunctionType(params, resultTy, trueRep); +} + +const clang::Type * +ASTContext::getCanonicalClangFunctionType( + ArrayRef params, + Optional result, + SILFunctionType::Representation trueRep) { + auto *ty = getClangTypeConverter().getFunctionType(params, result, trueRep); + return ty ? ty->getCanonicalTypeInternal().getTypePtr() : nullptr; } const Decl * @@ -4778,6 +4848,36 @@ void VarDecl::setOriginalWrappedProperty(VarDecl *originalProperty) { ctx.getImpl().OriginalWrappedProperties[this] = originalProperty; } +#ifndef NDEBUG +static bool isSourceLocInOrignalBuffer(const Decl *D, SourceLoc Loc) { + assert(Loc.isValid()); + auto bufferID = D->getDeclContext()->getParentSourceFile()->getBufferID(); + assert(bufferID.hasValue() && "Source buffer ID must be set"); + auto &SM = D->getASTContext().SourceMgr; + return SM.getRangeForBuffer(*bufferID).contains(Loc); +} +#endif + +void AbstractFunctionDecl::keepOriginalBodySourceRange() { + auto &impl = getASTContext().getImpl(); + auto result = + impl.OriginalBodySourceRanges.insert({this, getBodySourceRange()}); + assert((!result.second || + isSourceLocInOrignalBuffer(this, result.first->getSecond().Start)) && + "This function must be called before setting new body range"); + (void)result; +} + +SourceRange AbstractFunctionDecl::getOriginalBodySourceRange() const { + auto &impl = getASTContext().getImpl(); + auto found = impl.OriginalBodySourceRanges.find(this); + if (found != impl.OriginalBodySourceRanges.end()) { + return found->getSecond(); + } else { + return getBodySourceRange(); + } +} + IndexSubset * IndexSubset::get(ASTContext &ctx, const SmallBitVector &indices) { auto &foldingSet = ctx.getImpl().IndexSubsets; diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 44d32c84a7a7d..bf72c01eae702 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -44,7 +44,7 @@ Type swift::Demangle::getTypeForMangling(ASTContext &ctx, return Type(); ASTBuilder builder(ctx); - return swift::Demangle::decodeMangledType(builder, node); + return swift::Demangle::decodeMangledType(builder, node).getType(); } TypeDecl *swift::Demangle::getTypeDeclForMangling(ASTContext &ctx, @@ -530,7 +530,7 @@ Type ASTBuilder::createImplFunctionType( // [TODO: Store-SIL-Clang-type] auto einfo = SILExtInfoBuilder(representation, flags.isPseudogeneric(), - !flags.isEscaping(), diffKind, + !flags.isEscaping(), flags.isAsync(), diffKind, /*clangFunctionType*/ nullptr) .build(); @@ -846,8 +846,8 @@ CanGenericSignature ASTBuilder::demangleGenericSignature( if (child->getNumChildren() != 2) return CanGenericSignature(); - auto subjectType = swift::Demangle::decodeMangledType( - *this, child->getChild(0)); + auto subjectType = + swift::Demangle::decodeMangledType(*this, child->getChild(0)).getType(); if (!subjectType) return CanGenericSignature(); @@ -856,8 +856,9 @@ CanGenericSignature ASTBuilder::demangleGenericSignature( Demangle::Node::Kind::DependentGenericConformanceRequirement || child->getKind() == Demangle::Node::Kind::DependentGenericSameTypeRequirement) { - constraintType = swift::Demangle::decodeMangledType( - *this, child->getChild(1)); + constraintType = + swift::Demangle::decodeMangledType(*this, child->getChild(1)) + .getType(); if (!constraintType) return CanGenericSignature(); } diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 532790cc94f3b..16fd1f6141eba 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -1074,13 +1074,13 @@ namespace { Indent -= 2; if (auto FD = dyn_cast(D)) { - if (FD->getBodyResultTypeLoc().getTypeRepr()) { + if (FD->getResultTypeRepr()) { OS << '\n'; Indent += 2; OS.indent(Indent); PrintWithColorRAII(OS, ParenthesisColor) << '('; OS << "result\n"; - printRec(FD->getBodyResultTypeLoc().getTypeRepr()); + printRec(FD->getResultTypeRepr()); PrintWithColorRAII(OS, ParenthesisColor) << ')'; if (auto opaque = FD->getOpaqueResultTypeDecl()) { OS << '\n'; @@ -2108,11 +2108,8 @@ class PrintExpr : public ExprVisitor { void visitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { printCommon(E, "unresolved_member_expr") << " name='" << E->getName() << "'"; - printArgumentLabels(E->getArgumentLabels()); - if (E->getArgument()) { - OS << '\n'; - printRec(E->getArgument()); - } + PrintWithColorRAII(OS, ExprModifierColor) + << " function_ref=" << getFunctionRefKindStr(E->getFunctionRefKind()); PrintWithColorRAII(OS, ParenthesisColor) << ')'; } void visitDotSelfExpr(DotSelfExpr *E) { @@ -2135,7 +2132,12 @@ class PrintExpr : public ExprVisitor { printRec(E->getSubExpr()); PrintWithColorRAII(OS, ParenthesisColor) << ')'; } - + void visitUnresolvedMemberChainResultExpr(UnresolvedMemberChainResultExpr *E){ + printCommon(E, "unresolved_member_chain_expr"); + OS << '\n'; + printRec(E->getSubExpr()); + PrintWithColorRAII(OS, ParenthesisColor) << ')'; + } void visitTupleExpr(TupleExpr *E) { printCommon(E, "tuple_expr"); if (E->hasTrailingClosure()) @@ -3496,6 +3498,18 @@ namespace { TRIVIAL_TYPE_PRINTER(Unresolved, unresolved) + void visitHoleType(HoleType *T, StringRef label) { + printCommon(label, "hole_type"); + auto originatorTy = T->getOriginatorType(); + if (auto *typeVar = originatorTy.dyn_cast()) { + printRec("type_variable", typeVar); + } else { + printRec("dependent_member_type", + originatorTy.get()); + } + PrintWithColorRAII(OS, ParenthesisColor) << ')'; + } + void visitBuiltinIntegerType(BuiltinIntegerType *T, StringRef label) { printCommon(label, "builtin_integer_type"); if (T->isFixedWidth()) diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index e013ad5db8b3c..8da9843183986 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -39,6 +39,7 @@ #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Mangle.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" @@ -335,21 +336,29 @@ std::string ASTMangler::mangleKeyPathHashHelper(ArrayRef indices, return finalize(); } -std::string ASTMangler::mangleGlobalInit(const VarDecl *decl, int counter, +std::string ASTMangler::mangleGlobalInit(const PatternBindingDecl *pd, + unsigned pbdEntry, bool isInitFunc) { - auto topLevelContext = decl->getDeclContext()->getModuleScopeContext(); - auto fileUnit = cast(topLevelContext); - Identifier discriminator = fileUnit->getDiscriminatorForPrivateValue(decl); - assert(!discriminator.empty()); - assert(!isNonAscii(discriminator.str()) && - "discriminator contains non-ASCII characters"); - assert(!clang::isDigit(discriminator.str().front()) && - "not a valid identifier"); - - Buffer << "globalinit_"; - appendIdentifier(discriminator.str()); - Buffer << (isInitFunc ? "_func" : "_token"); - Buffer << counter; + beginMangling(); + + Pattern *pattern = pd->getPattern(pbdEntry); + bool first = true; + pattern->forEachVariable([&](VarDecl *D) { + if (first) { + appendContextOf(D); + first = false; + } + appendDeclName(D); + appendListSeparator(); + }); + assert(!first && "no variables in pattern binding?!"); + + if (isInitFunc) { + appendOperator("WZ"); + } else { + appendOperator("Wz"); + } + return finalize(); } @@ -914,6 +923,7 @@ void ASTMangler::appendType(Type type, const ValueDecl *forDecl) { TypeBase *tybase = type.getPointer(); switch (type->getKind()) { case TypeKind::TypeVariable: + case TypeKind::Hole: llvm_unreachable("mangling type variable"); case TypeKind::Module: @@ -2114,6 +2124,7 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) { // Always use Clang names for imported Clang declarations, unless they don't // have one. auto tryAppendClangName = [this, decl]() -> bool { + auto *nominal = dyn_cast(decl); auto namedDecl = getClangDeclForMangling(decl); if (!namedDecl) return false; @@ -2126,6 +2137,13 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) { appendIdentifier(interface->getObjCRuntimeNameAsString()); } else if (UseObjCRuntimeNames && protocol) { appendIdentifier(protocol->getObjCRuntimeNameAsString()); + } else if (auto ctsd = dyn_cast(namedDecl)) { + // If this is a `ClassTemplateSpecializationDecl`, it was + // imported as a Swift decl with `__CxxTemplateInst...` name. + // `ClassTemplateSpecializationDecl`'s name does not include information about + // template arguments, and in order to prevent name clashes we use the + // name of the Swift decl which does include template arguments. + appendIdentifier(nominal->getName().str()); } else { appendIdentifier(namedDecl->getName()); } diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 49305518234fc..eca53f2a0c0e9 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -24,7 +24,7 @@ #include "swift/AST/Decl.h" #include "swift/AST/Expr.h" #include "swift/AST/FileUnit.h" -#include "swift/AST/GenericEnvironment.h" +#include "swift/AST/GenericSignature.h" #include "swift/AST/Module.h" #include "swift/AST/NameLookup.h" #include "swift/AST/ParameterList.h" @@ -169,6 +169,24 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(bool preferTypeRepr, if (auto *ED = dyn_cast(D)) { if (!shouldPrint(ED->getExtendedNominal(), options)) return false; + + // Skip extensions to implementation-only imported types that have + // no public members. + auto localModule = ED->getParentModule(); + auto nominalModule = ED->getExtendedNominal()->getParentModule(); + if (localModule != nominalModule && + localModule->isImportedImplementationOnly(nominalModule)) { + + bool shouldPrintMembers = llvm::any_of( + ED->getMembers(), + [&](const Decl *member) -> bool { + return shouldPrint(member, options); + }); + + if (!shouldPrintMembers) + return false; + } + for (const Requirement &req : ED->getGenericRequirements()) { if (!isPublicOrUsableFromInline(req.getFirstType())) return false; @@ -1297,9 +1315,9 @@ bestRequirementPrintLocation(ProtocolDecl *proto, const Requirement &req) { bool inWhereClause; switch (req.getKind()) { + case RequirementKind::Layout: case RequirementKind::Conformance: - case RequirementKind::Superclass: - case RequirementKind::Layout: { + case RequirementKind::Superclass: { auto subject = req.getFirstType(); auto result = findRelevantDeclAndDirectUse(subject); @@ -1351,6 +1369,15 @@ void PrintAST::printInheritedFromRequirementSignature(ProtocolDecl *proto, proto->getRequirementSignature()), PrintInherited, [&](const Requirement &req) { + // Skip the inferred 'Self : AnyObject' constraint if this is an + // @objc protocol. + if (req.getKind() == RequirementKind::Layout && + req.getFirstType()->isEqual(proto->getProtocolSelfType()) && + req.getLayoutConstraint()->getKind() == LayoutConstraintKind::Class && + proto->isObjC()) { + return false; + } + auto location = bestRequirementPrintLocation(proto, req); return location.AttachedTo == attachingTo && !location.InWhereClause; }); @@ -2461,14 +2488,14 @@ void PrintAST::visitTypeAliasDecl(TypeAliasDecl *decl) { Printer << " = "; // FIXME: An inferred associated type witness type alias may reference // an opaque type, but OpaqueTypeArchetypes are always canonicalized - // so lose type sugar for generic params. Bind the generic environment so - // we can map params back into the generic environment and print them + // so lose type sugar for generic params. Bind the generic signature so + // we can map params back into the generic signature and print them // correctly. // // Remove this when we have a way to represent non-canonical archetypes // preserving sugar. - llvm::SaveAndRestore setGenericEnv(Options.GenericEnv, - decl->getGenericEnvironment()); + llvm::SaveAndRestore setGenericSig( + Options.GenericSig, decl->getGenericSignature().getPointer()); printTypeLoc(TypeLoc(decl->getUnderlyingTypeRepr(), Ty)); printDeclGenericRequirements(decl); } @@ -2939,8 +2966,8 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) { if (Options.PrintOriginalSourceText && decl->getStartLoc().isValid()) { SourceLoc StartLoc = decl->getStartLoc(); SourceLoc EndLoc; - if (!decl->getBodyResultTypeLoc().isNull()) { - EndLoc = decl->getBodyResultTypeLoc().getSourceRange().End; + if (decl->getResultTypeRepr()) { + EndLoc = decl->getResultTypeSourceRange().End; } else { EndLoc = decl->getSignatureSourceRange().End; } @@ -2977,7 +3004,7 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) { Type ResultTy = decl->getResultInterfaceType(); if (ResultTy && !ResultTy->isVoid()) { - TypeLoc ResultTyLoc = decl->getBodyResultTypeLoc(); + TypeLoc ResultTyLoc(decl->getResultTypeRepr(), ResultTy); // When printing a protocol requirement with types substituted for a // conforming class, replace occurrences of the 'Self' generic parameter @@ -3157,9 +3184,8 @@ void PrintAST::visitSubscriptDecl(SubscriptDecl *decl) { }); Printer << " -> "; - TypeLoc elementTy = decl->getElementTypeLoc(); - if (!elementTy.getTypeRepr()) - elementTy = TypeLoc::withoutLoc(decl->getElementInterfaceType()); + TypeLoc elementTy(decl->getElementTypeRepr(), + decl->getElementInterfaceType()); Printer.printDeclResultTypePre(decl, elementTy); Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType); @@ -3603,7 +3629,7 @@ void printCType(ASTContext &Ctx, ASTPrinter &Printer, ExtInfo &info) { auto *cml = Ctx.getClangModuleLoader(); SmallString<64> buf; llvm::raw_svector_ostream os(buf); - info.getClangTypeInfo().getValue().printType(cml, os); + info.getClangTypeInfo().printType(cml, os); Printer << ", cType: " << QuotedString(os.str()); } @@ -3771,8 +3797,11 @@ class TypePrinter : public TypeVisitor { } void visitErrorType(ErrorType *T) { - if (auto originalType = T->getOriginalType()) + if (auto originalType = T->getOriginalType()) { + if (Options.PrintInSILBody) + Printer << "@error_type "; visit(originalType); + } else Printer << "<>"; } @@ -3784,6 +3813,17 @@ class TypePrinter : public TypeVisitor { Printer << "_"; } + void visitHoleType(HoleType *T) { + if (Options.PrintTypesForDebugging) { + Printer << "<getOriginatorType(); + visit(Type(reinterpret_cast(originatorTy.getOpaqueValue()))); + Printer << ">>"; + } else { + Printer << "<>"; + } + } + #ifdef ASTPRINTER_HANDLE_BUILTINTYPE #error "ASTPRINTER_HANDLE_BUILTINTYPE should not be defined?!" #endif @@ -4025,7 +4065,7 @@ class TypePrinter : public TypeVisitor { case SILFunctionType::Representation::CFunctionPointer: Printer << "c"; // [TODO: Clang-type-plumbing] Remove the second check. - if (printNameOnly || !info.getClangTypeInfo().hasValue()) + if (printNameOnly || info.getClangTypeInfo().empty()) break; printCType(Ctx, Printer, info); break; @@ -4091,7 +4131,7 @@ class TypePrinter : public TypeVisitor { case SILFunctionType::Representation::CFunctionPointer: Printer << "c"; // [TODO: Clang-type-plumbing] Remove the second check. - if (printNameOnly || !info.getClangTypeInfo().hasValue()) + if (printNameOnly || info.getClangTypeInfo().empty()) break; printCType(Ctx, Printer, info); break; @@ -4122,6 +4162,9 @@ class TypePrinter : public TypeVisitor { if (info.isNoEscape()) { Printer.printSimpleAttr("@noescape") << " "; } + if (info.isAsync()) { + Printer.printSimpleAttr("@async") << " "; + } } void visitAnyFunctionTypeParams(ArrayRef Params, @@ -4238,6 +4281,12 @@ class TypePrinter : public TypeVisitor { llvm_unreachable("bad convention"); } + void printSILAsyncAttr(bool isAsync) { + if (isAsync) { + Printer << "@async "; + } + } + void printCalleeConvention(ParameterConvention conv) { switch (conv) { case ParameterConvention::Direct_Unowned: @@ -4283,7 +4332,7 @@ class TypePrinter : public TypeVisitor { Optional subBuffer; PrintOptions subOptions = Options; if (auto substitutions = T->getPatternSubstitutions()) { - subOptions.GenericEnv = nullptr; + subOptions.GenericSig = nullptr; subBuffer.emplace(Printer, subOptions); sub = &*subBuffer; @@ -4375,7 +4424,7 @@ class TypePrinter : public TypeVisitor { // A box layout has its own independent generic environment. Don't try // to print it with the environment's generic params. PrintOptions subOptions = Options; - subOptions.GenericEnv = nullptr; + subOptions.GenericSig = nullptr; TypePrinter sub(Printer, subOptions); // Capture list used here to ensure we don't print anything using `this` @@ -4558,10 +4607,10 @@ class TypePrinter : public TypeVisitor { } } - // When printing SIL types, use a generic environment to map them from + // When printing SIL types, use a generic signature to map them from // canonical types to sugared types. - if (Options.GenericEnv) - T = Options.GenericEnv->getSugaredType(T); + if (Options.GenericSig) + T = Options.GenericSig->getSugaredType(T); } auto Name = T->getName(); diff --git a/lib/AST/ASTScopeCreation.cpp b/lib/AST/ASTScopeCreation.cpp index e2b30ed302bb6..4623e38970ea3 100644 --- a/lib/AST/ASTScopeCreation.cpp +++ b/lib/AST/ASTScopeCreation.cpp @@ -479,23 +479,6 @@ class ScopeCreator final { } public: - /// When ASTScopes are enabled for code completion, - /// IfConfigs will pose a challenge because we may need to field lookups into - /// the inactive clauses, but the AST contains redundancy: the active clause's - /// elements are present in the members or elements of an IterableTypeDecl or - /// BraceStmt alongside of the IfConfigDecl. In addition there are two more - /// complications: - /// - /// 1. The active clause's elements may be nested inside an init self - /// rebinding decl (as in StringObject.self). - /// - /// 2. The active clause may be before or after the inactive ones - /// - /// So, when encountering an IfConfigDecl, we will expand the inactive - /// elements. Also, always sort members or elements so that the child scopes - /// are in source order (Just one of several reasons we need to sort.) - /// - static const bool includeInactiveIfConfigClauses = false; private: static std::vector expandIfConfigClauses(ArrayRef input) { @@ -526,9 +509,6 @@ class ScopeCreator final { if (isa(d)) expandIfConfigClausesInto(expansion, {d}, true); } - } else if (includeInactiveIfConfigClauses) { - expandIfConfigClausesInto(expansion, clause.Elements, - /*isInAnActiveNode=*/false); } } } @@ -762,10 +742,6 @@ void ASTScope:: impl->buildEnoughOfTreeForTopLevelExpressionsButDontRequestGenericsOrExtendedNominals(); } -bool ASTScope::areInactiveIfConfigClausesSupported() { - return ScopeCreator::includeInactiveIfConfigClauses; -} - void ASTScope::expandFunctionBody(AbstractFunctionDecl *AFD) { auto *const SF = AFD->getParentSourceFile(); SF->getScope().expandFunctionBodyImpl(AFD); @@ -795,7 +771,7 @@ void ASTSourceFileScope:: void ASTSourceFileScope::expandFunctionBody(AbstractFunctionDecl *AFD) { if (!AFD) return; - auto sr = AFD->getBodySourceRange(); + auto sr = AFD->getOriginalBodySourceRange(); if (sr.isInvalid()) return; ASTScopeImpl *bodyScope = findInnermostEnclosingScope(sr.Start, nullptr); @@ -1596,11 +1572,6 @@ ASTScopeImpl *GenericTypeOrExtensionWholePortion::expandScope( // Get now in case recursion emancipates scope auto *const ip = scope->getParent().get(); - // Prevent circular request bugs caused by illegal input and - // doing lookups that getExtendedNominal in the midst of getExtendedNominal. - if (scope->shouldHaveABody() && !scope->doesDeclHaveABody()) - return ip; - auto *context = scope->getGenericContext(); auto *genericParams = (isa(context) ? context->getParsedGenericParams() @@ -1609,6 +1580,12 @@ ASTScopeImpl *GenericTypeOrExtensionWholePortion::expandScope( scope->getDecl(), genericParams, scope); if (context->getTrailingWhereClause()) scope->createTrailingWhereClauseScope(deepestScope, scopeCreator); + + // Prevent circular request bugs caused by illegal input and + // doing lookups that getExtendedNominal in the midst of getExtendedNominal. + if (scope->shouldHaveABody() && !scope->doesDeclHaveABody()) + return ip; + scope->createBodyScope(deepestScope, scopeCreator); return ip; } @@ -2082,10 +2059,8 @@ class LocalizableDeclContextCollector : public ASTWalker { // catchForDebugging(D, "DictionaryBridging.swift", 694); if (const auto *dc = dyn_cast(D)) record(dc); - if (auto *icd = dyn_cast(D)) { - walkToClauses(icd); + if (isa(D)) return false; - } if (auto *pd = dyn_cast(D)) record(pd->getDefaultArgumentInitContext()); else if (auto *pbd = dyn_cast(D)) @@ -2103,18 +2078,6 @@ class LocalizableDeclContextCollector : public ASTWalker { } private: - void walkToClauses(IfConfigDecl *icd) { - for (auto &clause : icd->getClauses()) { - // Generate scopes for any closures in the condition - if (ScopeCreator::includeInactiveIfConfigClauses && clause.isActive) { - if (clause.Cond) - clause.Cond->walk(*this); - for (auto n : clause.Elements) - n.walk(*this); - } - } - } - void recordInitializers(PatternBindingDecl *pbd) { for (auto idx : range(pbd->getNumPatternEntries())) record(pbd->getInitContext(idx)); diff --git a/lib/AST/ASTScopeLookup.cpp b/lib/AST/ASTScopeLookup.cpp index 13ab5b86a3177..7896e009534a2 100644 --- a/lib/AST/ASTScopeLookup.cpp +++ b/lib/AST/ASTScopeLookup.cpp @@ -30,7 +30,6 @@ #include "swift/AST/TypeRepr.h" #include "swift/Basic/STLExtras.h" #include "llvm/Support/Compiler.h" -#include using namespace swift; using namespace namelookup; @@ -82,6 +81,15 @@ const ASTScopeImpl *ASTScopeImpl::findStartingScopeForLookup( // Someday, just use the assertion below. For now, print out lots of info for // debugging. if (!startingScope) { + + // Be lenient in code completion mode. There are cases where the decl + // context doesn't match with the ASTScope. e.g. dangling attributes. + // FIXME: Create ASTScope tree even for invalid code. + if (innermost && + startingContext->getASTContext().SourceMgr.hasCodeCompletionBuffer()) { + return innermost; + } + llvm::errs() << "ASTScopeImpl: resorting to startingScope hack, file: " << sourceFile->getFilename() << "\n"; // The check is costly, and inactive lookups will end up here, so don't @@ -143,33 +151,40 @@ bool ASTScopeImpl::checkSourceRangeOfThisASTNode() const { return true; } +/// If the \p loc is in a new buffer but \p range is not, consider the location +/// is at the start of replaced range. Otherwise, returns \p loc as is. +static SourceLoc translateLocForReplacedRange(SourceManager &sourceMgr, + SourceRange range, + SourceLoc loc) { + if (const auto &replacedRange = sourceMgr.getReplacedRange()) { + if (sourceMgr.rangeContainsTokenLoc(replacedRange.New, loc) && + !sourceMgr.rangeContains(replacedRange.New, range)) { + return replacedRange.Original.Start; + } + } + return loc; +} + NullablePtr ASTScopeImpl::findChildContaining(SourceLoc loc, SourceManager &sourceMgr) const { // Use binary search to find the child that contains this location. - struct CompareLocs { - SourceManager &sourceMgr; - - bool operator()(const ASTScopeImpl *scope, SourceLoc loc) { - ASTScopeAssert(scope->checkSourceRangeOfThisASTNode(), "Bad range."); - return -1 == ASTScopeImpl::compare(scope->getSourceRangeOfScope(), loc, - sourceMgr, - /*ensureDisjoint=*/false); - } - bool operator()(SourceLoc loc, const ASTScopeImpl *scope) { - ASTScopeAssert(scope->checkSourceRangeOfThisASTNode(), "Bad range."); - // Alternatively, we could check that loc < start-of-scope - return 0 >= ASTScopeImpl::compare(loc, scope->getSourceRangeOfScope(), - sourceMgr, - /*ensureDisjoint=*/false); - } - }; - auto *const *child = std::lower_bound( - getChildren().begin(), getChildren().end(), loc, CompareLocs{sourceMgr}); - - if (child != getChildren().end() && - sourceMgr.rangeContainsTokenLoc((*child)->getSourceRangeOfScope(), loc)) - return *child; + auto *const *child = llvm::lower_bound( + getChildren(), loc, + [&sourceMgr](const ASTScopeImpl *scope, SourceLoc loc) { + ASTScopeAssert(scope->checkSourceRangeOfThisASTNode(), "Bad range."); + auto rangeOfScope = scope->getSourceRangeOfScope(); + loc = translateLocForReplacedRange(sourceMgr, rangeOfScope, loc); + return -1 == ASTScopeImpl::compare(rangeOfScope, loc, sourceMgr, + /*ensureDisjoint=*/false); + }); + + if (child != getChildren().end()) { + auto rangeOfScope = (*child)->getSourceRangeOfScope(); + loc = translateLocForReplacedRange(sourceMgr, rangeOfScope, loc); + if (sourceMgr.rangeContainsTokenLoc(rangeOfScope, loc)) + return *child; + } return nullptr; } @@ -504,7 +519,7 @@ bool BraceStmtScope::lookupLocalsOrMembers(ArrayRef, bool PatternEntryInitializerScope::lookupLocalsOrMembers( ArrayRef, DeclConsumer consumer) const { // 'self' is available within the pattern initializer of a 'lazy' variable. - auto *initContext = cast_or_null( + auto *initContext = dyn_cast_or_null( decl->getInitContext(0)); if (initContext) { if (auto *selfParam = initContext->getImplicitSelfDecl()) { @@ -801,7 +816,7 @@ Optional ClosureBodyScope::resolveIsCascadingUseForThisScope( Optional PatternEntryInitializerScope::resolveIsCascadingUseForThisScope( Optional isCascadingUse) const { auto *const initContext = getPatternEntry().getInitContext(); - auto *PBI = cast_or_null(initContext); + auto *PBI = dyn_cast_or_null(initContext); auto *isd = PBI ? PBI->getImplicitSelfDecl() : nullptr; // 'self' is available within the pattern initializer of a 'lazy' variable. diff --git a/lib/AST/ASTScopeSourceRange.cpp b/lib/AST/ASTScopeSourceRange.cpp index 731826ad5f6a3..cecd970590cc6 100644 --- a/lib/AST/ASTScopeSourceRange.cpp +++ b/lib/AST/ASTScopeSourceRange.cpp @@ -67,6 +67,14 @@ ASTScopeImpl::widenSourceRangeForChildren(const SourceRange range, if (range.isInvalid()) return childRange; auto r = range; + + // HACK: For code completion. If the range of the child is from another + // source buffer, don't widen using that range. + if (const auto &replacedRange = getSourceManager().getReplacedRange()) { + if (getSourceManager().rangeContains(replacedRange.Original, range) && + getSourceManager().rangeContains(replacedRange.New, childRange)) + return r; + } r.widen(childRange); return r; } @@ -114,6 +122,14 @@ bool ASTScopeImpl::verifyThatChildrenAreContainedWithin( getChildren().back()->getSourceRangeOfScope().End); if (getSourceManager().rangeContains(range, rangeOfChildren)) return true; + + // HACK: For code completion. Handle replaced range. + if (const auto &replacedRange = getSourceManager().getReplacedRange()) { + if (getSourceManager().rangeContains(replacedRange.Original, range) && + getSourceManager().rangeContains(replacedRange.New, rangeOfChildren)) + return true; + } + auto &out = verificationError() << "children not contained in its parent\n"; if (getChildren().size() == 1) { out << "\n***Only Child node***\n"; @@ -200,7 +216,7 @@ SourceRange DifferentiableAttributeScope::getSourceRangeOfThisASTNode( SourceRange AbstractFunctionBodyScope::getSourceRangeOfThisASTNode( const bool omitAssertions) const { - return decl->getBodySourceRange(); + return decl->getOriginalBodySourceRange(); } SourceRange TopLevelCodeScope::getSourceRangeOfThisASTNode( @@ -357,7 +373,7 @@ SourceRange AbstractFunctionDeclScope::getSourceRangeOfThisASTNode( ASTScopeAssert(r.End.isValid(), "Start valid imples end valid."); return r; } - return decl->getBodySourceRange(); + return decl->getOriginalBodySourceRange(); } SourceRange ParameterListScope::getSourceRangeOfThisASTNode( @@ -609,7 +625,7 @@ SourceRange IterableTypeScope::sourceRangeForDeferredExpansion() const { return portion->sourceRangeForDeferredExpansion(this); } SourceRange AbstractFunctionBodyScope::sourceRangeForDeferredExpansion() const { - const auto bsr = decl->getBodySourceRange(); + const auto bsr = decl->getOriginalBodySourceRange(); const SourceLoc endEvenIfNoCloseBraceAndEndsWithInterpolatedStringLiteral = getLocEncompassingPotentialLookups(getSourceManager(), bsr.End); return SourceRange(bsr.Start, diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp index 3641f7c807627..ef2ba5afb7cbf 100644 --- a/lib/AST/ASTWalker.cpp +++ b/lib/AST/ASTWalker.cpp @@ -358,7 +358,7 @@ class Traversal : public ASTVisitorgetIndices()); - if (auto *const TyR = SD->getElementTypeLoc().getTypeRepr()) + if (auto *const TyR = SD->getElementTypeRepr()) if (doIt(TyR)) return true; @@ -394,7 +394,7 @@ class Traversal : public ASTVisitor(AFD)) { if (!isa(FD)) - if (auto *const TyR = FD->getBodyResultTypeLoc().getTypeRepr()) + if (auto *const TyR = FD->getResultTypeRepr()) if (doIt(TyR)) return true; } @@ -504,17 +504,7 @@ class Traversal : public ASTVisitorgetArgument()) { - if (auto arg = doIt(E->getArgument())) { - E->setArgument(arg); - return E; - } - - return nullptr; - } - return E; - } + Expr *visitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { return E; } Expr *visitOpaqueValueExpr(OpaqueValueExpr *E) { return E; } diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp index 69719bfb62ce6..70a1ec3429409 100644 --- a/lib/AST/Attr.cpp +++ b/lib/AST/Attr.cpp @@ -589,32 +589,11 @@ static void printDifferentiableAttrArguments( if (!isLeadingClause) stream << ' '; stream << "where "; - std::function getInterfaceType; - if (!original || !original->getGenericEnvironment()) { - getInterfaceType = [](Type Ty) -> Type { return Ty; }; - } else { - // Use GenericEnvironment to produce user-friendly - // names instead of something like 't_0_0'. - auto *genericEnv = original->getGenericEnvironment(); - assert(genericEnv); - getInterfaceType = [=](Type Ty) -> Type { - return genericEnv->getSugaredType(Ty); - }; - } interleave(requirementsToPrint, [&](Requirement req) { if (const auto &originalGenSig = original->getGenericSignature()) if (originalGenSig->isRequirementSatisfied(req)) return; - auto FirstTy = getInterfaceType(req.getFirstType()); - if (req.getKind() != RequirementKind::Layout) { - auto SecondTy = getInterfaceType(req.getSecondType()); - Requirement ReqWithDecls(req.getKind(), FirstTy, SecondTy); - ReqWithDecls.print(stream, Options); - } else { - Requirement ReqWithDecls(req.getKind(), FirstTy, - req.getLayoutConstraint()); - ReqWithDecls.print(stream, Options); - } + req.print(stream, Options); }, [&] { stream << ", "; }); @@ -928,25 +907,16 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options, Printer << "kind: " << kind << ", "; SmallVector requirementsScratch; ArrayRef requirements; - if (auto sig = attr->getSpecializedSgnature()) + if (auto sig = attr->getSpecializedSignature()) requirements = sig->getRequirements(); - std::function GetInterfaceType; auto *FnDecl = dyn_cast_or_null(D); - if (!FnDecl || !FnDecl->getGenericEnvironment()) - GetInterfaceType = [](Type Ty) -> Type { return Ty; }; - else { - // Use GenericEnvironment to produce user-friendly - // names instead of something like t_0_0. - auto *GenericEnv = FnDecl->getGenericEnvironment(); - assert(GenericEnv); - GetInterfaceType = [=](Type Ty) -> Type { - return GenericEnv->getSugaredType(Ty); - }; - - if (auto sig = attr->getSpecializedSgnature()) { + if (FnDecl && FnDecl->getGenericSignature()) { + auto genericSig = FnDecl->getGenericSignature(); + + if (auto sig = attr->getSpecializedSignature()) { requirementsScratch = sig->requirementsNotSatisfiedBy( - GenericEnv->getGenericSignature()); + genericSig); requirements = requirementsScratch; } } @@ -957,16 +927,7 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options, interleave(requirements, [&](Requirement req) { - auto FirstTy = GetInterfaceType(req.getFirstType()); - if (req.getKind() != RequirementKind::Layout) { - auto SecondTy = GetInterfaceType(req.getSecondType()); - Requirement ReqWithDecls(req.getKind(), FirstTy, SecondTy); - ReqWithDecls.print(Printer, Options); - } else { - Requirement ReqWithDecls(req.getKind(), FirstTy, - req.getLayoutConstraint()); - ReqWithDecls.print(Printer, Options); - } + req.print(Printer, Options); }, [&] { Printer << ", "; }); diff --git a/lib/AST/Availability.cpp b/lib/AST/Availability.cpp index a28946dc49bc4..743d3f80c69fb 100644 --- a/lib/AST/Availability.cpp +++ b/lib/AST/Availability.cpp @@ -306,21 +306,21 @@ AvailabilityContext ASTContext::getTypesInAbstractMetadataStateAvailability() { } AvailabilityContext ASTContext::getPrespecializedGenericMetadataAvailability() { - return getSwift53Availability(); + return getSwift54Availability(); } AvailabilityContext ASTContext::getCompareTypeContextDescriptorsAvailability() { - return getSwiftFutureAvailability(); + return getSwift54Availability(); } AvailabilityContext ASTContext::getCompareProtocolConformanceDescriptorsAvailability() { - return getSwiftFutureAvailability(); + return getSwift54Availability(); } AvailabilityContext ASTContext::getIntermodulePrespecializedGenericMetadataAvailability() { - return getSwiftFutureAvailability(); + return getSwift54Availability(); } AvailabilityContext ASTContext::getSwift52Availability() { @@ -384,6 +384,10 @@ AvailabilityContext ASTContext::getSwift53Availability() { } } +AvailabilityContext ASTContext::getSwift54Availability() { + return getSwiftFutureAvailability(); +} + AvailabilityContext ASTContext::getSwiftFutureAvailability() { auto target = LangOpts.Target; diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index dde68fa9c1ea8..3a311ac116765 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -168,16 +168,10 @@ getBuiltinFunction(Identifier Id, ArrayRef argTypes, Type ResType) { auto *paramList = ParameterList::create(Context, params); DeclName Name(Context, Id, paramList); - auto FD = FuncDecl::create(Context, /*StaticLoc=*/SourceLoc(), - StaticSpellingKind::None, - /*FuncLoc=*/SourceLoc(), - Name, /*NameLoc=*/SourceLoc(), - /*Async-*/false, /*AsyncLoc=*/SourceLoc(), - /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), - /*GenericParams=*/nullptr, - paramList, - TypeLoc::withoutLoc(ResType), DC); - FD->setImplicit(); + auto *const FD = FuncDecl::createImplicit( + Context, StaticSpellingKind::None, Name, /*NameLoc=*/SourceLoc(), + /*Async=*/false, /*Throws=*/false, + /*GenericParams=*/nullptr, paramList, ResType, DC); FD->setAccess(AccessLevel::Public); return FD; } @@ -214,17 +208,11 @@ getBuiltinGenericFunction(Identifier Id, auto *paramList = ParameterList::create(Context, params); DeclName Name(Context, Id, paramList); - auto func = FuncDecl::create(Context, /*StaticLoc=*/SourceLoc(), - StaticSpellingKind::None, - /*FuncLoc=*/SourceLoc(), - Name, /*NameLoc=*/SourceLoc(), - /*Async-*/false, /*AsyncLoc=*/SourceLoc(), - /*Throws=*/ Rethrows, /*ThrowsLoc=*/SourceLoc(), - GenericParams, - paramList, - TypeLoc::withoutLoc(ResType), DC); - - func->setImplicit(); + auto *const func = FuncDecl::createImplicit( + Context, StaticSpellingKind::None, Name, /*NameLoc=*/SourceLoc(), + /*Async=*/false, + /*Throws=*/Rethrows, GenericParams, paramList, ResType, DC); + func->setAccess(AccessLevel::Public); func->setGenericSignature(Sig); if (Rethrows) diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 71a1cfa05c1ea..62993edae03ea 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -57,7 +57,6 @@ add_swift_host_library(swiftAST STATIC IndexSubset.cpp InlinableText.cpp LayoutConstraint.cpp - LocalizationFormat.cpp Module.cpp ModuleDependencies.cpp ModuleLoader.cpp diff --git a/lib/AST/ClangTypeConverter.cpp b/lib/AST/ClangTypeConverter.cpp index d4ccea512f069..9fd13f797798d 100644 --- a/lib/AST/ClangTypeConverter.cpp +++ b/lib/AST/ClangTypeConverter.cpp @@ -158,6 +158,57 @@ const clang::Type *ClangTypeConverter::getFunctionType( llvm_unreachable("invalid representation"); } +const clang::Type *ClangTypeConverter::getFunctionType( + ArrayRef params, Optional result, + SILFunctionType::Representation repr) { + + // Using the interface type is sufficient as type parameters get mapped to + // `id`, since ObjC lightweight generics use type erasure. (See also: SE-0057) + auto resultClangTy = result.hasValue() + ? convert(result.getValue().getInterfaceType()) + : ClangASTContext.VoidTy; + + if (resultClangTy.isNull()) + return nullptr; + + SmallVector extParamInfos; + SmallVector paramsClangTy; + bool someParamIsConsumed = false; + for (auto &p : params) { + auto pc = convert(p.getInterfaceType()); + if (pc.isNull()) + return nullptr; + clang::FunctionProtoType::ExtParameterInfo extParamInfo; + if (p.isConsumed()) { + someParamIsConsumed = true; + extParamInfo = extParamInfo.withIsConsumed(true); + } + extParamInfos.push_back(extParamInfo); + paramsClangTy.push_back(pc); + } + + clang::FunctionProtoType::ExtProtoInfo info(clang::CallingConv::CC_C); + if (someParamIsConsumed) + info.ExtParameterInfos = extParamInfos.begin(); + auto fn = ClangASTContext.getFunctionType(resultClangTy, paramsClangTy, info); + if (fn.isNull()) + return nullptr; + + switch (repr) { + case SILFunctionType::Representation::CFunctionPointer: + return ClangASTContext.getPointerType(fn).getTypePtr(); + case SILFunctionType::Representation::Block: + return ClangASTContext.getBlockPointerType(fn).getTypePtr(); + case SILFunctionType::Representation::Thick: + case SILFunctionType::Representation::Thin: + case SILFunctionType::Representation::Method: + case SILFunctionType::Representation::ObjCMethod: + case SILFunctionType::Representation::WitnessMethod: + case SILFunctionType::Representation::Closure: + llvm_unreachable("Expected a C-compatible representation."); + } +} + clang::QualType ClangTypeConverter::convertMemberType(NominalTypeDecl *DC, StringRef memberName) { auto memberTypeDecl = cast( @@ -576,12 +627,19 @@ clang::QualType ClangTypeConverter::visitFunctionType(FunctionType *type) { } clang::QualType ClangTypeConverter::visitSILFunctionType(SILFunctionType *type) { - llvm::report_fatal_error("Expected only AST types but found a SIL function."); + // We must've already computed it before if applicable. + return clang::QualType(type->getClangTypeInfo().getType(), 0); } clang::QualType ClangTypeConverter::visitSILBlockStorageType(SILBlockStorageType *type) { - llvm::report_fatal_error("Expected only AST types but found a SIL block."); + // We'll select (void)(^)(). This isn't correct for all blocks, but block + // storage type should only be converted for function signature lowering, + // where the parameter types do not matter. + auto &clangCtx = ClangASTContext; + auto fnTy = clangCtx.getFunctionNoProtoType(clangCtx.VoidTy); + auto blockTy = clangCtx.getBlockPointerType(fnTy); + return clangCtx.getCanonicalType(blockTy); } clang::QualType diff --git a/lib/AST/ClangTypeConverter.h b/lib/AST/ClangTypeConverter.h index 450b9e30cf19a..e41a824163312 100644 --- a/lib/AST/ClangTypeConverter.h +++ b/lib/AST/ClangTypeConverter.h @@ -74,6 +74,11 @@ class ClangTypeConverter : ArrayRef params, Type resultTy, AnyFunctionType::Representation repr); + /// Compute the C function type for a SIL function type. + const clang::Type *getFunctionType( + ArrayRef params, Optional result, + SILFunctionType::Representation repr); + /// Check whether the given Clang declaration is an export of a Swift /// declaration introduced by this converter, and if so, return the original /// Swift declaration. diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 0b0816acd18b0..f1f17cbf3c042 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -116,6 +116,17 @@ const clang::Module *ClangNode::getClangModule() const { return nullptr; } +void ClangNode::dump() const { + if (auto D = getAsDecl()) + D->dump(); + else if (auto M = getAsMacro()) + M->dump(); + else if (auto M = getAsModule()) + M->dump(); + else + llvm::errs() << "ClangNode contains nullptr\n"; +} + // Only allow allocation of Decls using the allocator in ASTContext. void *Decl::operator new(size_t Bytes, const ASTContext &C, unsigned Alignment) { @@ -2759,9 +2770,9 @@ OpaqueReturnTypeRepr *ValueDecl::getOpaqueResultTypeRepr() const { returnRepr = VD->getTypeReprOrParentPatternTypeRepr(); } } else if (auto *FD = dyn_cast(this)) { - returnRepr = FD->getBodyResultTypeLoc().getTypeRepr(); + returnRepr = FD->getResultTypeRepr(); } else if (auto *SD = dyn_cast(this)) { - returnRepr = SD->getElementTypeLoc().getTypeRepr(); + returnRepr = SD->getElementTypeRepr(); } return dyn_cast_or_null(returnRepr); @@ -6584,6 +6595,57 @@ ObjCSubscriptKind SubscriptDecl::getObjCSubscriptKind() const { return ObjCSubscriptKind::Keyed; } +void SubscriptDecl::setElementInterfaceType(Type type) { + getASTContext().evaluator.cacheOutput(ResultTypeRequest{this}, + std::move(type)); +} + +SubscriptDecl * +SubscriptDecl::createDeserialized(ASTContext &Context, DeclName Name, + StaticSpellingKind StaticSpelling, + Type ElementTy, DeclContext *Parent, + GenericParamList *GenericParams) { + assert(ElementTy && "Deserialized element type must not be null"); + auto *const SD = new (Context) + SubscriptDecl(Name, SourceLoc(), StaticSpelling, SourceLoc(), nullptr, + SourceLoc(), /*ElementTyR=*/nullptr, Parent, GenericParams); + SD->setElementInterfaceType(ElementTy); + return SD; +} + +SubscriptDecl *SubscriptDecl::create(ASTContext &Context, DeclName Name, + SourceLoc StaticLoc, + StaticSpellingKind StaticSpelling, + SourceLoc SubscriptLoc, + ParameterList *Indices, SourceLoc ArrowLoc, + TypeRepr *ElementTyR, DeclContext *Parent, + GenericParamList *GenericParams) { + assert(ElementTyR); + auto *const SD = new (Context) + SubscriptDecl(Name, StaticLoc, StaticSpelling, SubscriptLoc, Indices, + ArrowLoc, ElementTyR, Parent, GenericParams); + return SD; +} + +SubscriptDecl *SubscriptDecl::createImported(ASTContext &Context, DeclName Name, + SourceLoc SubscriptLoc, + ParameterList *Indices, + SourceLoc ArrowLoc, Type ElementTy, + DeclContext *Parent, + ClangNode ClangN) { + assert(ClangN && ElementTy); + auto *DeclPtr = allocateMemoryForDecl( + Context, sizeof(SubscriptDecl), /*includeSpaceForClangNode=*/true); + + auto *const SD = ::new (DeclPtr) + SubscriptDecl(Name, SourceLoc(), StaticSpellingKind::None, SubscriptLoc, + Indices, ArrowLoc, /*ElementTyR=*/nullptr, Parent, + /*GenericParams=*/nullptr); + SD->setElementInterfaceType(ElementTy); + SD->setClangNode(ClangN); + return SD; +} + SourceRange SubscriptDecl::getSourceRange() const { return {getSubscriptLoc(), getEndLoc()}; } @@ -6691,6 +6753,17 @@ bool AbstractFunctionDecl::argumentNameIsAPIByDefault() const { return false; } +bool AbstractFunctionDecl::isAsyncHandler() const { + auto func = dyn_cast(this); + if (!func) + return false; + + auto mutableFunc = const_cast(func); + return evaluateOrDefault(getASTContext().evaluator, + IsAsyncHandlerRequest{mutableFunc}, + false); +} + BraceStmt *AbstractFunctionDecl::getBody(bool canSynthesize) const { if ((getBodyKind() == BodyKind::Synthesize || getBodyKind() == BodyKind::Unparsed) && @@ -6726,6 +6799,20 @@ void AbstractFunctionDecl::setBody(BraceStmt *S, BodyKind NewBodyKind) { } } +void AbstractFunctionDecl::setBodyToBeReparsed(SourceRange bodyRange) { + assert(bodyRange.isValid()); + assert(getBodyKind() == BodyKind::Unparsed || + getBodyKind() == BodyKind::Parsed || + getBodyKind() == BodyKind::TypeChecked); + assert(getASTContext().SourceMgr.rangeContainsTokenLoc( + bodyRange, getASTContext().SourceMgr.getCodeCompletionLoc()) && + "This function is only intended to be used for code completion"); + + keepOriginalBodySourceRange(); + BodyRange = bodyRange; + setBodyKind(BodyKind::Unparsed); +} + SourceRange AbstractFunctionDecl::getBodySourceRange() const { switch (getBodyKind()) { case BodyKind::None: @@ -7088,6 +7175,11 @@ void AbstractFunctionDecl::addDerivativeFunctionConfiguration( DerivativeFunctionConfigs->insert(config); } +void FuncDecl::setResultInterfaceType(Type type) { + getASTContext().evaluator.cacheOutput(ResultTypeRequest{this}, + std::move(type)); +} + FuncDecl *FuncDecl::createImpl(ASTContext &Context, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, @@ -7117,39 +7209,66 @@ FuncDecl *FuncDecl::createImpl(ASTContext &Context, } FuncDecl *FuncDecl::createDeserialized(ASTContext &Context, - SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, - SourceLoc FuncLoc, - DeclName Name, SourceLoc NameLoc, - bool Async, SourceLoc AsyncLoc, - bool Throws, SourceLoc ThrowsLoc, + DeclName Name, bool Async, bool Throws, GenericParamList *GenericParams, - DeclContext *Parent) { - return createImpl(Context, StaticLoc, StaticSpelling, FuncLoc, - Name, NameLoc, Async, AsyncLoc, Throws, ThrowsLoc, - GenericParams, Parent, - ClangNode()); + Type FnRetType, DeclContext *Parent) { + assert(FnRetType && "Deserialized result type must not be null"); + auto *const FD = + FuncDecl::createImpl(Context, SourceLoc(), StaticSpelling, SourceLoc(), + Name, SourceLoc(), Async, SourceLoc(), Throws, + SourceLoc(), GenericParams, Parent, ClangNode()); + FD->setResultInterfaceType(FnRetType); + return FD; } FuncDecl *FuncDecl::create(ASTContext &Context, SourceLoc StaticLoc, - StaticSpellingKind StaticSpelling, - SourceLoc FuncLoc, - DeclName Name, SourceLoc NameLoc, - bool Async, SourceLoc AsyncLoc, - bool Throws, SourceLoc ThrowsLoc, + StaticSpellingKind StaticSpelling, SourceLoc FuncLoc, + DeclName Name, SourceLoc NameLoc, bool Async, + SourceLoc AsyncLoc, bool Throws, SourceLoc ThrowsLoc, GenericParamList *GenericParams, - ParameterList *BodyParams, - TypeLoc FnRetType, DeclContext *Parent, - ClangNode ClangN) { - auto *FD = FuncDecl::createImpl( - Context, StaticLoc, StaticSpelling, FuncLoc, - Name, NameLoc, Async, AsyncLoc, Throws, ThrowsLoc, - GenericParams, Parent, ClangN); + ParameterList *BodyParams, TypeRepr *ResultTyR, + DeclContext *Parent) { + auto *const FD = FuncDecl::createImpl( + Context, StaticLoc, StaticSpelling, FuncLoc, Name, NameLoc, Async, + AsyncLoc, Throws, ThrowsLoc, GenericParams, Parent, ClangNode()); FD->setParameters(BodyParams); - FD->getBodyResultTypeLoc() = FnRetType; + FD->FnRetType = TypeLoc(ResultTyR); return FD; } - + +FuncDecl *FuncDecl::createImplicit(ASTContext &Context, + StaticSpellingKind StaticSpelling, + DeclName Name, SourceLoc NameLoc, bool Async, + bool Throws, GenericParamList *GenericParams, + ParameterList *BodyParams, Type FnRetType, + DeclContext *Parent) { + assert(FnRetType); + auto *const FD = FuncDecl::createImpl( + Context, SourceLoc(), StaticSpelling, SourceLoc(), Name, NameLoc, Async, + SourceLoc(), Throws, SourceLoc(), GenericParams, Parent, ClangNode()); + FD->setImplicit(); + FD->setParameters(BodyParams); + FD->setResultInterfaceType(FnRetType); + return FD; +} + +FuncDecl *FuncDecl::createImported(ASTContext &Context, SourceLoc FuncLoc, + DeclName Name, SourceLoc NameLoc, + bool Async, bool Throws, + ParameterList *BodyParams, + Type FnRetType, DeclContext *Parent, + ClangNode ClangN) { + assert(ClangN && FnRetType); + auto *const FD = FuncDecl::createImpl( + Context, SourceLoc(), StaticSpellingKind::None, FuncLoc, Name, NameLoc, + Async, SourceLoc(), Throws, SourceLoc(), + /*GenericParams=*/nullptr, Parent, ClangN); + FD->setParameters(BodyParams); + FD->setResultInterfaceType(FnRetType); + return FD; +} + OperatorDecl *FuncDecl::getOperatorDecl() const { // Fast-path: Most functions are not operators. if (!isOperator()) { @@ -7198,20 +7317,18 @@ AccessorDecl *AccessorDecl::createImpl(ASTContext &ctx, return D; } -AccessorDecl *AccessorDecl::createDeserialized(ASTContext &ctx, - SourceLoc declLoc, - SourceLoc accessorKeywordLoc, - AccessorKind accessorKind, - AbstractStorageDecl *storage, - SourceLoc staticLoc, - StaticSpellingKind staticSpelling, - bool throws, SourceLoc throwsLoc, - GenericParamList *genericParams, - DeclContext *parent) { - return createImpl(ctx, declLoc, accessorKeywordLoc, accessorKind, - storage, staticLoc, staticSpelling, - throws, throwsLoc, genericParams, parent, - ClangNode()); +AccessorDecl * +AccessorDecl::createDeserialized(ASTContext &ctx, AccessorKind accessorKind, + AbstractStorageDecl *storage, + StaticSpellingKind staticSpelling, + bool throws, GenericParamList *genericParams, + Type fnRetType, DeclContext *parent) { + assert(fnRetType && "Deserialized result type must not be null"); + auto *const D = AccessorDecl::createImpl( + ctx, SourceLoc(), SourceLoc(), accessorKind, storage, SourceLoc(), + staticSpelling, throws, SourceLoc(), genericParams, parent, ClangNode()); + D->setResultInterfaceType(fnRetType); + return D; } AccessorDecl *AccessorDecl::create(ASTContext &ctx, @@ -7224,7 +7341,7 @@ AccessorDecl *AccessorDecl::create(ASTContext &ctx, bool throws, SourceLoc throwsLoc, GenericParamList *genericParams, ParameterList * bodyParams, - TypeLoc fnRetType, + Type fnRetType, DeclContext *parent, ClangNode clangNode) { auto *D = AccessorDecl::createImpl( @@ -7232,7 +7349,7 @@ AccessorDecl *AccessorDecl::create(ASTContext &ctx, staticLoc, staticSpelling, throws, throwsLoc, genericParams, parent, clangNode); D->setParameters(bodyParams); - D->getBodyResultTypeLoc() = fnRetType; + D->setResultInterfaceType(fnRetType); return D; } @@ -7386,7 +7503,7 @@ SourceRange FuncDecl::getSourceRange() const { getBodyKind() == BodyKind::Skipped) return { StartLoc, BodyRange.End }; - SourceLoc RBraceLoc = getBodySourceRange().End; + SourceLoc RBraceLoc = getOriginalBodySourceRange().End; if (RBraceLoc.isValid()) { return { StartLoc, RBraceLoc }; } @@ -7401,9 +7518,9 @@ SourceRange FuncDecl::getSourceRange() const { if (TrailingWhereClauseSourceRange.isValid()) return { StartLoc, TrailingWhereClauseSourceRange.End }; - if (getBodyResultTypeLoc().hasLocation() && - getBodyResultTypeLoc().getSourceRange().End.isValid()) - return { StartLoc, getBodyResultTypeLoc().getSourceRange().End }; + const auto ResultTyEndLoc = getResultTypeSourceRange().End; + if (ResultTyEndLoc.isValid()) + return { StartLoc, ResultTyEndLoc }; if (hasThrows()) return { StartLoc, getThrowsLoc() }; @@ -7507,7 +7624,7 @@ SourceRange ConstructorDecl::getSourceRange() const { if (isImplicit()) return getConstructorLoc(); - SourceLoc End = getBodySourceRange().End; + SourceLoc End = getOriginalBodySourceRange().End; if (End.isInvalid()) End = getGenericTrailingWhereClauseSourceRange().End; if (End.isInvalid()) @@ -7733,7 +7850,7 @@ ConstructorDecl::getDelegatingOrChainedInitKind(DiagnosticEngine *diags, } SourceRange DestructorDecl::getSourceRange() const { - SourceLoc End = getBodySourceRange().End; + SourceLoc End = getOriginalBodySourceRange().End; if (End.isInvalid()) { End = getDestructorLoc(); } @@ -7909,7 +8026,7 @@ void Decl::setClangNode(ClangNode Node) { // dependency. struct DeclTraceFormatter : public UnifiedStatsReporter::TraceFormatter { - void traceName(const void *Entity, raw_ostream &OS) const { + void traceName(const void *Entity, raw_ostream &OS) const override { if (!Entity) return; const Decl *D = static_cast(Entity); @@ -7922,7 +8039,7 @@ struct DeclTraceFormatter : public UnifiedStatsReporter::TraceFormatter { } } void traceLoc(const void *Entity, SourceManager *SM, - clang::SourceManager *CSM, raw_ostream &OS) const { + clang::SourceManager *CSM, raw_ostream &OS) const override { if (!Entity) return; const Decl *D = static_cast(Entity); diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp index 9e0094d02b279..f7b9368589bfa 100644 --- a/lib/AST/DiagnosticEngine.cpp +++ b/lib/AST/DiagnosticEngine.cpp @@ -20,7 +20,6 @@ #include "swift/AST/ASTPrinter.h" #include "swift/AST/Decl.h" #include "swift/AST/DiagnosticSuppression.h" -#include "swift/AST/LocalizationFormat.h" #include "swift/AST/Module.h" #include "swift/AST/Pattern.h" #include "swift/AST/PrintOptions.h" @@ -28,6 +27,7 @@ #include "swift/AST/TypeRepr.h" #include "swift/Basic/SourceManager.h" #include "swift/Config.h" +#include "swift/Localization/LocalizationFormat.h" #include "swift/Parse/Lexer.h" // bad dependency #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" @@ -1010,8 +1010,9 @@ void DiagnosticEngine::emitDiagnostic(const Diagnostic &diagnostic) { emitDiagnostic(childNote); } -const char *DiagnosticEngine::diagnosticStringFor(const DiagID id, - bool printDiagnosticName) { +llvm::StringRef +DiagnosticEngine::diagnosticStringFor(const DiagID id, + bool printDiagnosticName) { // TODO: Print diagnostic names from `localization`. if (printDiagnosticName) { return debugDiagnosticStrings[(unsigned)id]; @@ -1020,7 +1021,7 @@ const char *DiagnosticEngine::diagnosticStringFor(const DiagID id, if (localization) { auto localizedMessage = localization.get()->getMessageOr(id, defaultMessage); - return localizedMessage.data(); + return localizedMessage; } return defaultMessage; } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 59cdfa8ab7cb7..ea39fdece934e 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -126,7 +126,7 @@ namespace { } // end anonymous namespace void Expr::setType(Type T) { - assert(!T || !T->hasTypeVariable()); + assert(!T || !T->hasTypeVariable() || !T->hasHole()); Ty = T; } @@ -288,6 +288,7 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const { return cast(this) ->getSubExpr()->getReferencedDecl(stopAtParenExpr); + PASS_THROUGH_REFERENCE(UnresolvedMemberChainResult, getSubExpr); PASS_THROUGH_REFERENCE(DotSelf, getSubExpr); PASS_THROUGH_REFERENCE(Await, getSubExpr); PASS_THROUGH_REFERENCE(Try, getSubExpr); @@ -606,6 +607,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const { case ExprKind::Paren: case ExprKind::DotSelf: + case ExprKind::UnresolvedMemberChainResult: case ExprKind::Tuple: case ExprKind::Array: case ExprKind::Dictionary: @@ -1606,61 +1608,6 @@ DynamicSubscriptExpr::create(ASTContext &ctx, Expr *base, Expr *index, hasTrailingClosure, decl, implicit); } -UnresolvedMemberExpr::UnresolvedMemberExpr(SourceLoc dotLoc, - DeclNameLoc nameLoc, - DeclNameRef name, Expr *argument, - ArrayRef argLabels, - ArrayRef argLabelLocs, - bool hasTrailingClosure, - bool implicit) - : Expr(ExprKind::UnresolvedMember, implicit), - DotLoc(dotLoc), NameLoc(nameLoc), Name(name), Argument(argument) { - Bits.UnresolvedMemberExpr.HasArguments = (argument != nullptr); - Bits.UnresolvedMemberExpr.NumArgLabels = argLabels.size(); - Bits.UnresolvedMemberExpr.HasArgLabelLocs = !argLabelLocs.empty(); - Bits.UnresolvedMemberExpr.HasTrailingClosure = hasTrailingClosure; - initializeCallArguments(argLabels, argLabelLocs); -} - -UnresolvedMemberExpr *UnresolvedMemberExpr::create(ASTContext &ctx, - SourceLoc dotLoc, - DeclNameLoc nameLoc, - DeclNameRef name, - bool implicit) { - size_t size = totalSizeToAlloc({ }, { }); - - void *memory = ctx.Allocate(size, alignof(UnresolvedMemberExpr)); - return new (memory) UnresolvedMemberExpr(dotLoc, nameLoc, name, nullptr, - { }, { }, - /*hasTrailingClosure=*/false, - implicit); -} - -UnresolvedMemberExpr * -UnresolvedMemberExpr::create(ASTContext &ctx, SourceLoc dotLoc, - DeclNameLoc nameLoc, DeclNameRef name, - SourceLoc lParenLoc, - ArrayRef args, - ArrayRef argLabels, - ArrayRef argLabelLocs, - SourceLoc rParenLoc, - ArrayRef trailingClosures, - bool implicit) { - SmallVector argLabelsScratch; - SmallVector argLabelLocsScratch; - Expr *arg = packSingleArgument(ctx, lParenLoc, args, argLabels, argLabelLocs, - rParenLoc, trailingClosures, implicit, - argLabelsScratch, argLabelLocsScratch); - - size_t size = totalSizeToAlloc(argLabels, argLabelLocs); - - void *memory = ctx.Allocate(size, alignof(UnresolvedMemberExpr)); - return new (memory) UnresolvedMemberExpr(dotLoc, nameLoc, name, arg, - argLabels, argLabelLocs, - trailingClosures.size() == 1, - implicit); -} - ArrayRef ApplyExpr::getArgumentLabels( SmallVectorImpl &scratch) const { // Unary operators and 'self' applications have a single, unlabeled argument. @@ -2001,7 +1948,7 @@ bool ClosureExpr::capturesSelfEnablingImplictSelf() const { } void ClosureExpr::setExplicitResultType(Type ty) { - assert(ty && !ty->hasTypeVariable()); + assert(ty && !ty->hasTypeVariable() && !ty->hasHole()); ExplicitResultTypeAndBodyState.getPointer() ->setType(MetatypeType::get(ty)); } @@ -2470,14 +2417,14 @@ SourceLoc swift::extractNearestSourceLoc(const DefaultArgumentExpr *expr) { // dependency. struct ExprTraceFormatter : public UnifiedStatsReporter::TraceFormatter { - void traceName(const void *Entity, raw_ostream &OS) const { + void traceName(const void *Entity, raw_ostream &OS) const override { if (!Entity) return; const Expr *E = static_cast(Entity); OS << Expr::getKindName(E->getKind()); } void traceLoc(const void *Entity, SourceManager *SM, - clang::SourceManager *CSM, raw_ostream &OS) const { + clang::SourceManager *CSM, raw_ostream &OS) const override { if (!Entity) return; const Expr *E = static_cast(Entity); diff --git a/lib/AST/ExtInfo.cpp b/lib/AST/ExtInfo.cpp index a75a3ff1d9f5e..5b779920ace0b 100644 --- a/lib/AST/ExtInfo.cpp +++ b/lib/AST/ExtInfo.cpp @@ -19,6 +19,20 @@ #include "clang/AST/Type.h" +static void assertIsFunctionType(const clang::Type *type) { +#ifndef NDEBUG + if (!(type->isFunctionPointerType() || type->isBlockPointerType() || + type->isFunctionReferenceType())) { + llvm::SmallString<256> buf; + llvm::raw_svector_ostream os(buf); + os << "Expected a Clang function type wrapped in a pointer type or " + << "a block pointer type but found:\n"; + type->dump(os); + llvm_unreachable(os.str().data()); + } +#endif +} + namespace swift { // MARK: - ClangTypeInfo @@ -53,23 +67,12 @@ void ClangTypeInfo::dump(llvm::raw_ostream &os) const { // MARK: - ASTExtInfoBuilder -void ASTExtInfoBuilder::assertIsFunctionType(const clang::Type *type) { -#ifndef NDEBUG - if (!(type->isFunctionPointerType() || type->isBlockPointerType() || - type->isFunctionReferenceType())) { - SmallString<256> buf; - llvm::raw_svector_ostream os(buf); - os << "Expected a Clang function type wrapped in a pointer type or " - << "a block pointer type but found:\n"; - type->dump(os); - llvm_unreachable(os.str().data()); - } -#endif - return; -} - void ASTExtInfoBuilder::checkInvariants() const { - // TODO: Add validation checks here while making sure things don't blow up. + // TODO: [clang-function-type-serialization] Once we start serializing + // the Clang type, we should also assert that the pointer is non-null. + auto Rep = Representation(bits & RepresentationMask); + if ((Rep == Representation::CFunctionPointer) && clangTypeInfo.type) + assertIsFunctionType(clangTypeInfo.type); } // MARK: - ASTExtInfo diff --git a/lib/AST/GenericEnvironment.cpp b/lib/AST/GenericEnvironment.cpp index a5033e16c4c29..8b29c9c85d1ef 100644 --- a/lib/AST/GenericEnvironment.cpp +++ b/lib/AST/GenericEnvironment.cpp @@ -171,27 +171,6 @@ Type GenericEnvironment::mapTypeIntoContext(GenericTypeParamType *type) const { return result; } -GenericTypeParamType *GenericEnvironment::getSugaredType( - GenericTypeParamType *type) const { - for (auto *sugaredType : getGenericParams()) - if (sugaredType->isEqual(type)) - return sugaredType; - - llvm_unreachable("missing generic parameter"); -} - -Type GenericEnvironment::getSugaredType(Type type) const { - if (!type->hasTypeParameter()) - return type; - - return type.transform([this](Type Ty) -> Type { - if (auto GP = dyn_cast(Ty.getPointer())) { - return Type(getSugaredType(GP)); - } - return Ty; - }); -} - SubstitutionMap GenericEnvironment::getForwardingSubstitutionMap() const { auto genericSig = getGenericSignature(); return SubstitutionMap::get(genericSig, diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp index 9b6befde6a9ea..1f9731635b49f 100644 --- a/lib/AST/GenericSignature.cpp +++ b/lib/AST/GenericSignature.cpp @@ -404,16 +404,6 @@ bool GenericSignatureImpl::requiresClass(Type type) const { // If there is a layout constraint, it might be a class. if (equivClass->layout && equivClass->layout->isClass()) return true; - // If there is a superclass bound, then obviously it must be a class. - // FIXME: We shouldn't need this? - if (equivClass->superclass) return true; - - // If any of the protocols are class-bound, then it must be a class. - // FIXME: We shouldn't need this? - for (const auto &conforms : equivClass->conformsTo) { - if (conforms.first->requiresClass()) return true; - } - return false; } @@ -1047,10 +1037,27 @@ SubstitutionMap GenericSignatureImpl::getIdentitySubstitutionMap() const { MakeAbstractConformanceForGenericType()); } +GenericTypeParamType *GenericSignatureImpl::getSugaredType( + GenericTypeParamType *type) const { + unsigned ordinal = getGenericParamOrdinal(type); + return getGenericParams()[ordinal]; +} + +Type GenericSignatureImpl::getSugaredType(Type type) const { + if (!type->hasTypeParameter()) + return type; + + return type.transform([this](Type Ty) -> Type { + if (auto GP = dyn_cast(Ty.getPointer())) { + return Type(getSugaredType(GP)); + } + return Ty; + }); +} + unsigned GenericSignatureImpl::getGenericParamOrdinal( GenericTypeParamType *param) const { - return GenericParamKey(param->getDepth(), param->getIndex()) - .findIndexIn(getGenericParams()); + return GenericParamKey(param).findIndexIn(getGenericParams()); } bool GenericSignatureImpl::hasTypeVariable() const { diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp index dc03dc5cc0c61..bff5a8688291d 100644 --- a/lib/AST/GenericSignatureBuilder.cpp +++ b/lib/AST/GenericSignatureBuilder.cpp @@ -3871,9 +3871,21 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement( return false; }); - // Remaining logic is not relevant in ObjC protocol cases. - if (proto->isObjC()) + if (proto->isObjC()) { + // @objc implies an inferred AnyObject constraint. + auto innerSource = + FloatingRequirementSource::viaProtocolRequirement(source, proto, + /*inferred=*/true); + addLayoutRequirementDirect(selfType, + LayoutConstraint::getLayoutConstraint( + LayoutConstraintKind::Class, + getASTContext()), + innerSource); + return ConstraintResult::Resolved; + } + + // Remaining logic is not relevant in ObjC protocol cases. // Collect all of the inherited associated types and typealiases in the // inherited protocols (recursively). @@ -7418,13 +7430,11 @@ AbstractGenericSignatureRequest::evaluate( if (baseSignature) canBaseSignature = baseSignature->getCanonicalSignature(); - llvm::SmallDenseMap mappedTypeParameters; SmallVector canAddedParameters; canAddedParameters.reserve(addedParameters.size()); for (auto gp : addedParameters) { auto canGP = gp->getCanonicalType()->castTo(); canAddedParameters.push_back(canGP); - mappedTypeParameters[canGP] = Type(gp); } SmallVector canAddedRequirements; @@ -7441,10 +7451,8 @@ AbstractGenericSignatureRequest::evaluate( if (!canSignatureResult || !*canSignatureResult) return GenericSignature(); - // Substitute in the original generic parameters to form a more-sugared - // result closer to what the original request wanted. Note that this - // loses sugar on concrete types, but for abstract signatures that - // shouldn't matter. + // Substitute in the original generic parameters to form the sugared + // result the original request wanted. auto canSignature = *canSignatureResult; SmallVector resugaredParameters; resugaredParameters.reserve(canSignature->getGenericParams().size()); @@ -7462,9 +7470,8 @@ AbstractGenericSignatureRequest::evaluate( auto resugaredReq = req.subst( [&](SubstitutableType *type) { if (auto gp = dyn_cast(type)) { - auto knownGP = mappedTypeParameters.find(gp); - if (knownGP != mappedTypeParameters.end()) - return knownGP->second; + unsigned ordinal = canSignature->getGenericParamOrdinal(gp); + return Type(resugaredParameters[ordinal]); } return Type(type); }, diff --git a/lib/AST/InlinableText.cpp b/lib/AST/InlinableText.cpp index 7a805d94add6d..c21a0b10e217c 100644 --- a/lib/AST/InlinableText.cpp +++ b/lib/AST/InlinableText.cpp @@ -78,7 +78,7 @@ struct ExtractInactiveRanges : public ASTWalker { ranges.push_back(charRange); } - bool walkToDeclPre(Decl *d) { + bool walkToDeclPre(Decl *d) override { auto icd = dyn_cast(d); if (!icd) return true; diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 6749fdc8b8802..3399d77f3aa7c 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -1994,6 +1994,27 @@ bool SourceFile::isImportedImplementationOnly(const ModuleDecl *module) const { return !imports.isImportedBy(module, getParentModule()); } +bool ModuleDecl::isImportedImplementationOnly(const ModuleDecl *module) const { + auto &imports = getASTContext().getImportCache(); + + // Look through non-implementation-only imports to see if module is imported + // in some other way. Otherwise we assume it's implementation-only imported. + ModuleDecl::ImportFilter filter = { + ModuleDecl::ImportFilterKind::Public, + ModuleDecl::ImportFilterKind::Private, + ModuleDecl::ImportFilterKind::SPIAccessControl, + ModuleDecl::ImportFilterKind::ShadowedBySeparateOverlay}; + SmallVector results; + getImportedModules(results, filter); + + for (auto &desc : results) { + if (imports.isImportedBy(module, desc.importedModule)) + return false; + } + + return true; +} + void SourceFile::lookupImportedSPIGroups( const ModuleDecl *importedModule, llvm::SmallSetVector &spiGroups) const { @@ -2387,7 +2408,7 @@ StringRef SourceFile::getFilename() const { ASTScope &SourceFile::getScope() { if (!Scope) - Scope = std::unique_ptr(new (getASTContext()) ASTScope(this)); + Scope = new (getASTContext()) ASTScope(this); return *Scope.get(); } @@ -2657,14 +2678,14 @@ const clang::Module* ModuleEntity::getAsClangModule() const { // dependency. struct SourceFileTraceFormatter : public UnifiedStatsReporter::TraceFormatter { - void traceName(const void *Entity, raw_ostream &OS) const { + void traceName(const void *Entity, raw_ostream &OS) const override { if (!Entity) return; const SourceFile *SF = static_cast(Entity); OS << llvm::sys::path::filename(SF->getFilename()); } void traceLoc(const void *Entity, SourceManager *SM, - clang::SourceManager *CSM, raw_ostream &OS) const { + clang::SourceManager *CSM, raw_ostream &OS) const override { // SourceFiles don't have SourceLocs of their own; they contain them. } }; diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index fdbfb119ebddb..7ef21cadcb205 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -312,6 +312,19 @@ static void recordShadowedDeclsAfterTypeMatch( } } + // If one declaration is in a protocol or extension thereof and the + // other is not, prefer the one that is not. + if ((bool)firstDecl->getDeclContext()->getSelfProtocolDecl() != + (bool)secondDecl->getDeclContext()->getSelfProtocolDecl()) { + if (firstDecl->getDeclContext()->getSelfProtocolDecl()) { + shadowed.insert(firstDecl); + break; + } else { + shadowed.insert(secondDecl); + continue; + } + } + continue; } @@ -2421,6 +2434,53 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator, } } + // If we have more than one attribute declaration, we have an ambiguity. + // So, emit an ambiguity diagnostic. + if (auto typeRepr = attr->getTypeRepr()) { + if (nominals.size() > 1) { + SmallVector ambiguousCandidates; + // Filter out declarations that cannot be attributes. + for (auto decl : nominals) { + if (isa(decl)) { + continue; + } + ambiguousCandidates.push_back(decl); + } + if (ambiguousCandidates.size() > 1) { + auto attrName = nominals.front()->getName(); + ctx.Diags.diagnose(typeRepr->getLoc(), + diag::ambiguous_custom_attribute_ref, attrName); + for (auto candidate : ambiguousCandidates) { + ctx.Diags.diagnose(candidate->getLoc(), + diag::found_attribute_candidate); + // If the candidate is a top-level attribute, let's suggest + // adding module name to resolve the ambiguity. + if (candidate->getDeclContext()->isModuleScopeContext()) { + auto moduleName = candidate->getParentModule()->getName(); + ctx.Diags + .diagnose(typeRepr->getLoc(), + diag::ambiguous_custom_attribute_ref_fix, + moduleName.str(), attrName, moduleName) + .fixItInsert(typeRepr->getLoc(), moduleName.str().str() + "."); + } + } + return nullptr; + } + } + } + + // There is no nominal type with this name, so complain about this being + // an unknown attribute. + std::string typeName; + if (auto typeRepr = attr->getTypeRepr()) { + llvm::raw_string_ostream out(typeName); + typeRepr->print(out); + } else { + typeName = attr->getType().getString(); + } + + ctx.Diags.diagnose(attr->getLocation(), diag::unknown_attribute, typeName); + return nullptr; } diff --git a/lib/AST/Pattern.cpp b/lib/AST/Pattern.cpp index 2006c06e62e27..eed9e33c0341c 100644 --- a/lib/AST/Pattern.cpp +++ b/lib/AST/Pattern.cpp @@ -517,7 +517,7 @@ SourceRange ExprPattern::getSourceRange() const { // dependency. struct PatternTraceFormatter : public UnifiedStatsReporter::TraceFormatter { - void traceName(const void *Entity, raw_ostream &OS) const { + void traceName(const void *Entity, raw_ostream &OS) const override { if (!Entity) return; const Pattern *P = static_cast(Entity); @@ -526,7 +526,7 @@ struct PatternTraceFormatter : public UnifiedStatsReporter::TraceFormatter { } } void traceLoc(const void *Entity, SourceManager *SM, - clang::SourceManager *CSM, raw_ostream &OS) const { + clang::SourceManager *CSM, raw_ostream &OS) const override { if (!Entity) return; const Pattern *P = static_cast(Entity); diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp index d612dff6a0574..5b2ff91752ca6 100644 --- a/lib/AST/ProtocolConformance.cpp +++ b/lib/AST/ProtocolConformance.cpp @@ -1489,7 +1489,7 @@ ProtocolConformanceRef::getCanonicalConformanceRef() const { struct ProtocolConformanceTraceFormatter : public UnifiedStatsReporter::TraceFormatter { - void traceName(const void *Entity, raw_ostream &OS) const { + void traceName(const void *Entity, raw_ostream &OS) const override { if (!Entity) return; const ProtocolConformance *C = @@ -1497,7 +1497,7 @@ struct ProtocolConformanceTraceFormatter C->printName(OS); } void traceLoc(const void *Entity, SourceManager *SM, - clang::SourceManager *CSM, raw_ostream &OS) const { + clang::SourceManager *CSM, raw_ostream &OS) const override { if (!Entity) return; const ProtocolConformance *C = diff --git a/lib/AST/SILLayout.cpp b/lib/AST/SILLayout.cpp index da70ccd300917..ffbd35175d226 100644 --- a/lib/AST/SILLayout.cpp +++ b/lib/AST/SILLayout.cpp @@ -52,6 +52,8 @@ static void verifyFields(CanGenericSignature Sig, ArrayRef Fields) { && "SILLayout field cannot have an archetype type"); assert(!ty->hasTypeVariable() && "SILLayout cannot contain constraint system type variables"); + assert(!ty->hasHole() && + "SILLayout cannot contain constraint system type holes"); if (!ty->hasTypeParameter()) continue; field.getLoweredType().findIf([Sig](Type t) -> bool { diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 83d24aacaf94a..98541beee21a4 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -524,14 +524,14 @@ SwitchStmt *SwitchStmt::create(LabeledStmtInfo LabelInfo, SourceLoc SwitchLoc, // dependency. struct StmtTraceFormatter : public UnifiedStatsReporter::TraceFormatter { - void traceName(const void *Entity, raw_ostream &OS) const { + void traceName(const void *Entity, raw_ostream &OS) const override { if (!Entity) return; const Stmt *S = static_cast(Entity); OS << Stmt::getKindName(S->getKind()); } void traceLoc(const void *Entity, SourceManager *SM, - clang::SourceManager *CSM, raw_ostream &OS) const { + clang::SourceManager *CSM, raw_ostream &OS) const override { if (!Entity) return; const Stmt *S = static_cast(Entity); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 62142eb9ccb27..402a33ab65356 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -76,7 +76,7 @@ Type QuerySubstitutionMap::operator()(SubstitutableType *type) const { } void TypeLoc::setType(Type Ty) { - assert(!Ty || !Ty->hasTypeVariable()); + assert(!Ty || !Ty->hasTypeVariable() || !Ty->hasHole()); this->Ty = Ty; } @@ -153,9 +153,7 @@ bool TypeBase::isAny() { return isEqual(getASTContext().TheAnyType); } -bool TypeBase::isHole() { - return isEqual(getASTContext().TheUnresolvedType); -} +bool TypeBase::isHole() { return getCanonicalType()->is(); } bool TypeBase::isAnyClassReferenceType() { return getCanonicalType().isAnyClassReferenceType(); @@ -221,6 +219,7 @@ bool CanType::isReferenceTypeImpl(CanType type, const GenericSignatureImpl *sig, case TypeKind::LValue: case TypeKind::InOut: case TypeKind::TypeVariable: + case TypeKind::Hole: case TypeKind::BoundGenericEnum: case TypeKind::BoundGenericStruct: case TypeKind::SILToken: @@ -1149,6 +1148,7 @@ CanType TypeBase::computeCanonicalType() { case TypeKind::Error: case TypeKind::Unresolved: case TypeKind::TypeVariable: + case TypeKind::Hole: llvm_unreachable("these types are always canonical"); #define SUGARED_TYPE(id, parent) \ @@ -3206,14 +3206,8 @@ PrimaryArchetypeType::getNew(const ASTContext &Ctx, } bool ArchetypeType::requiresClass() const { - if (Bits.ArchetypeType.HasSuperclass) - return true; if (auto layout = getLayoutConstraint()) - if (layout->isClass()) - return true; - for (ProtocolDecl *conformed : getConformsTo()) - if (conformed->requiresClass()) - return true; + return layout->isClass(); return false; } @@ -4250,6 +4244,7 @@ case TypeKind::Id: case TypeKind::Error: case TypeKind::Unresolved: case TypeKind::TypeVariable: + case TypeKind::Hole: case TypeKind::GenericTypeParam: case TypeKind::SILToken: case TypeKind::Module: @@ -4952,8 +4947,7 @@ ReferenceCounting TypeBase::getReferenceCounting() { auto archetype = cast(type); auto layout = archetype->getLayoutConstraint(); (void)layout; - assert(archetype->requiresClass() || - (layout && layout->isRefCounted())); + assert(layout && layout->isRefCounted()); if (auto supertype = archetype->getSuperclass()) return supertype->getReferenceCounting(); return ReferenceCounting::Unknown; @@ -4989,6 +4983,7 @@ ReferenceCounting TypeBase::getReferenceCounting() { case TypeKind::LValue: case TypeKind::InOut: case TypeKind::TypeVariable: + case TypeKind::Hole: case TypeKind::BoundGenericEnum: case TypeKind::BoundGenericStruct: case TypeKind::SILToken: diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index ff2efbc44ce89..b6bf4130e16f3 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -935,23 +935,28 @@ void ParamSpecifierRequest::cacheResult(ParamSpecifier specifier) const { // ResultTypeRequest computation. //----------------------------------------------------------------------------// -TypeLoc &ResultTypeRequest::getResultTypeLoc() const { - auto *decl = std::get<0>(getStorage()); - if (auto *funcDecl = dyn_cast(decl)) - return funcDecl->getBodyResultTypeLoc(); - auto *subscriptDecl = cast(decl); - return subscriptDecl->getElementTypeLoc(); -} - Optional ResultTypeRequest::getCachedResult() const { - if (auto type = getResultTypeLoc().getType()) - return type; + Type type; + auto *const decl = std::get<0>(getStorage()); + if (const auto *const funcDecl = dyn_cast(decl)) { + type = funcDecl->FnRetType.getType(); + } else { + type = cast(decl)->ElementTy.getType(); + } - return None; + if (type.isNull()) + return None; + + return type; } void ResultTypeRequest::cacheResult(Type type) const { - getResultTypeLoc().setType(type); + auto *const decl = std::get<0>(getStorage()); + if (auto *const funcDecl = dyn_cast(decl)) { + funcDecl->FnRetType.setType(type); + } else { + cast(decl)->ElementTy.setType(type); + } } //----------------------------------------------------------------------------// @@ -1008,6 +1013,7 @@ void InterfaceTypeRequest::cacheResult(Type type) const { auto *decl = std::get<0>(getStorage()); if (type) { assert(!type->hasTypeVariable() && "Type variable in interface type"); + assert(!type->hasHole() && "Type hole in interface type"); assert(!type->is() && "Interface type must be materializable"); assert(!type->hasArchetype() && "Archetype in interface type"); } diff --git a/lib/AST/TypeJoinMeet.cpp b/lib/AST/TypeJoinMeet.cpp index a5609f8b669fb..468cb6810fc1a 100644 --- a/lib/AST/TypeJoinMeet.cpp +++ b/lib/AST/TypeJoinMeet.cpp @@ -87,6 +87,9 @@ struct TypeJoin : CanTypeVisitor { assert(!first->hasTypeVariable() && !second->hasTypeVariable() && "Cannot compute join of types involving type variables"); + assert(!first->hasHole() && !second->hasHole() && + "Cannot compute join of types involving type holes"); + assert(first->getWithoutSpecifierType()->isEqual(first) && "Expected simple type!"); assert(second->getWithoutSpecifierType()->isEqual(second) && diff --git a/lib/AST/TypeRepr.cpp b/lib/AST/TypeRepr.cpp index 0a28f865f8e88..6490258e3b922 100644 --- a/lib/AST/TypeRepr.cpp +++ b/lib/AST/TypeRepr.cpp @@ -171,6 +171,9 @@ void AttributedTypeRepr::printAttrs(ASTPrinter &Printer, Printer.printStructurePost(PrintStructureKind::BuiltinAttribute); Printer << " "; } + + if (hasAttr(TAK_async)) + Printer.printSimpleAttr("@async") << " "; } IdentTypeRepr *IdentTypeRepr::create(ASTContext &C, @@ -454,14 +457,14 @@ void SILBoxTypeRepr::printImpl(ASTPrinter &Printer, // linkage dependency. struct TypeReprTraceFormatter : public UnifiedStatsReporter::TraceFormatter { - void traceName(const void *Entity, raw_ostream &OS) const { + void traceName(const void *Entity, raw_ostream &OS) const override { if (!Entity) return; const TypeRepr *TR = static_cast(Entity); TR->print(OS); } void traceLoc(const void *Entity, SourceManager *SM, - clang::SourceManager *CSM, raw_ostream &OS) const { + clang::SourceManager *CSM, raw_ostream &OS) const override { if (!Entity) return; const TypeRepr *TR = static_cast(Entity); diff --git a/lib/AST/TypeWalker.cpp b/lib/AST/TypeWalker.cpp index f5be4e10b5223..f95bdb01366f9 100644 --- a/lib/AST/TypeWalker.cpp +++ b/lib/AST/TypeWalker.cpp @@ -34,6 +34,7 @@ class Traversal : public TypeVisitor bool visitErrorType(ErrorType *ty) { return false; } bool visitUnresolvedType(UnresolvedType *ty) { return false; } + bool visitHoleType(HoleType *ty) { return false; } bool visitBuiltinType(BuiltinType *ty) { return false; } bool visitTypeAliasType(TypeAliasType *ty) { if (auto parent = ty->getParent()) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index e82e1638b593a..8bada4e358315 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -27,6 +27,7 @@ add_subdirectory(IDE) add_subdirectory(Immediate) add_subdirectory(IRGen) add_subdirectory(LLVMPasses) +add_subdirectory(Localization) add_subdirectory(Markup) add_subdirectory(Migrator) add_subdirectory(Option) diff --git a/lib/ClangImporter/ClangAdapter.cpp b/lib/ClangImporter/ClangAdapter.cpp index eddac5d46b3bf..a2ff1426bf477 100644 --- a/lib/ClangImporter/ClangAdapter.cpp +++ b/lib/ClangImporter/ClangAdapter.cpp @@ -714,8 +714,7 @@ bool importer::isUnavailableInSwift( return false; } -OptionalTypeKind importer::getParamOptionality(version::Version swiftVersion, - const clang::ParmVarDecl *param, +OptionalTypeKind importer::getParamOptionality(const clang::ParmVarDecl *param, bool knownNonNull) { auto &clangCtx = param->getASTContext(); diff --git a/lib/ClangImporter/ClangAdapter.h b/lib/ClangImporter/ClangAdapter.h index 0b066364bd622..9a15bbd523efa 100644 --- a/lib/ClangImporter/ClangAdapter.h +++ b/lib/ClangImporter/ClangAdapter.h @@ -161,15 +161,11 @@ bool isUnavailableInSwift(const clang::Decl *decl, const PlatformAvailability &, /// Determine the optionality of the given Clang parameter. /// -/// \param swiftLanguageVersion What version of Swift we're using, which affects -/// how optionality is inferred. -/// /// \param param The Clang parameter. /// /// \param knownNonNull Whether a function- or method-level "nonnull" attribute /// applies to this parameter. -OptionalTypeKind getParamOptionality(version::Version swiftLanguageVersion, - const clang::ParmVarDecl *param, +OptionalTypeKind getParamOptionality(const clang::ParmVarDecl *param, bool knownNonNull); } } diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 19f6dc6c0c97e..c38ae00d5e3ab 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -1718,7 +1718,6 @@ bool ClangImporter::canImportModule(Located moduleID) { ModuleDecl *ClangImporter::Implementation::loadModuleClang( SourceLoc importLoc, ArrayRef> path) { - auto &clangContext = getClangASTContext(); auto &clangHeaderSearch = getClangPreprocessor().getHeaderSearchInfo(); // Look up the top-level module first, to see if it exists at all. @@ -1732,8 +1731,9 @@ ModuleDecl *ClangImporter::Implementation::loadModuleClang( SmallVector, 4> clangPath; for (auto component : path) { - clangPath.push_back({&clangContext.Idents.get(component.Item.str()), - exportSourceLoc(component.Loc)}); + clangPath.emplace_back( + getClangPreprocessor().getIdentifierInfo(component.Item.str()), + exportSourceLoc(component.Loc)); } auto &rawDiagClient = Instance->getDiagnosticClient(); @@ -3685,6 +3685,7 @@ void ClangImporter::Implementation::lookupValue( clangDecl->getMostRecentDecl(); CurrentVersion.forEachOtherImportNameVersion( + SwiftContext.LangOpts.EnableExperimentalConcurrency, [&](ImportNameVersion nameVersion) { if (anyMatching) return; @@ -3694,6 +3695,12 @@ void ClangImporter::Implementation::lookupValue( if (!newName.getDeclName().matchesRef(name)) return; + // If we asked for an async import and didn't find one, skip this. + // This filters out duplicates. + if (nameVersion.supportsConcurrency() && + !newName.getAsyncInfo()) + return; + const clang::DeclContext *clangDC = newName.getEffectiveContext().getAsDeclContext(); if (!clangDC || !clangDC->isFileContext()) diff --git a/lib/ClangImporter/ClangModuleDependencyScanner.cpp b/lib/ClangImporter/ClangModuleDependencyScanner.cpp index 6c44002d46dbb..c465b1eb2473c 100644 --- a/lib/ClangImporter/ClangModuleDependencyScanner.cpp +++ b/lib/ClangImporter/ClangModuleDependencyScanner.cpp @@ -87,11 +87,11 @@ namespace { : Command(std::move(Cmd)) {} virtual std::vector - getCompileCommands(StringRef FilePath) const { + getCompileCommands(StringRef FilePath) const override { return {Command}; } - virtual std::vector getAllCompileCommands() const { + virtual std::vector getAllCompileCommands() const override { return {Command}; } @@ -254,6 +254,18 @@ void ClangImporter::recordModuleDependencies( swiftArgs.push_back("-module-name"); swiftArgs.push_back(clangModuleDep.ModuleName); + // Pass down search paths to the -emit-module action. + // Unlike building Swift modules, we need to include all search paths to + // the clang invocation to build PCMs because transitive headers can only + // be found via search paths. Passing these headers as explicit inputs can + // be quite challenging. + for (auto &path: Impl.SwiftContext.SearchPathOpts.ImportSearchPaths) { + addClangArg("-I" + path); + } + for (auto &path: Impl.SwiftContext.SearchPathOpts.FrameworkSearchPaths) { + addClangArg((path.IsSystem ? "-Fsystem": "-F") + path.Path); + } + // Swift frontend option for input file path (Foo.modulemap). swiftArgs.push_back(clangModuleDep.ClangModuleMapFile); // Module-level dependencies. @@ -294,6 +306,7 @@ Optional ClangImporter::getModuleDependencies( // Reform the Clang importer options. // FIXME: Just save a reference or copy so we can get this back. ClangImporterOptions importerOpts; + importerOpts.ExtraArgs = getExtraClangArgs(); // Determine the command-line arguments for dependency scanning. auto &ctx = Impl.SwiftContext; @@ -337,6 +350,7 @@ bool ClangImporter::addBridgingHeaderDependencies( // Reform the Clang importer options. // FIXME: Just save a reference or copy so we can get this back. ClangImporterOptions importerOpts; + importerOpts.ExtraArgs = getExtraClangArgs(); // Retrieve the bridging header. std::string bridgingHeader = *targetModule.getBridgingHeader(); diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index e35b0aed470b7..52f26c7d0eaaf 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -160,10 +160,10 @@ static FuncDecl *createFuncOrAccessor(ASTContext &ctx, SourceLoc funcLoc, DeclName name, SourceLoc nameLoc, ParameterList *bodyParams, Type resultTy, + bool async, bool throws, DeclContext *dc, ClangNode clangNode) { - TypeLoc resultTypeLoc = resultTy ? TypeLoc::withoutLoc(resultTy) : TypeLoc(); if (accessorInfo) { return AccessorDecl::create(ctx, funcLoc, /*accessorKeywordLoc*/ SourceLoc(), @@ -175,16 +175,10 @@ static FuncDecl *createFuncOrAccessor(ASTContext &ctx, SourceLoc funcLoc, /*ThrowsLoc=*/SourceLoc(), /*GenericParams=*/nullptr, bodyParams, - resultTypeLoc, dc, clangNode); + resultTy, dc, clangNode); } else { - return FuncDecl::create(ctx, /*StaticLoc=*/SourceLoc(), - StaticSpellingKind::None, - funcLoc, name, nameLoc, - /*Async=*/false, /*AsyncLoc=*/SourceLoc(), - throws, /*ThrowsLoc=*/SourceLoc(), - /*GenericParams=*/nullptr, - bodyParams, - resultTypeLoc, dc, clangNode); + return FuncDecl::createImported(ctx, funcLoc, name, nameLoc, async, throws, + bodyParams, resultTy, dc, clangNode); } } @@ -611,7 +605,7 @@ static void makeEnumRawValueGetter(ClangImporter::Implementation &Impl, /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), /*GenericParams=*/nullptr, params, - TypeLoc::withoutLoc(rawTy), enumDecl); + rawTy, enumDecl); getterDecl->setImplicit(); getterDecl->setIsObjC(false); getterDecl->setIsDynamic(false); @@ -687,7 +681,7 @@ static AccessorDecl *makeStructRawValueGetter( /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), /*GenericParams=*/nullptr, params, - TypeLoc::withoutLoc(computedType), structDecl); + computedType, structDecl); getterDecl->setImplicit(); getterDecl->setIsObjC(false); getterDecl->setIsDynamic(false); @@ -717,7 +711,7 @@ static AccessorDecl *makeFieldGetterDecl(ClangImporter::Implementation &Impl, /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), /*GenericParams=*/nullptr, params, - TypeLoc::withoutLoc(getterType), importedDecl, clangNode); + getterType, importedDecl, clangNode); getterDecl->setAccess(AccessLevel::Public); getterDecl->setIsObjC(false); getterDecl->setIsDynamic(false); @@ -750,7 +744,7 @@ static AccessorDecl *makeFieldSetterDecl(ClangImporter::Implementation &Impl, /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), /*GenericParams=*/nullptr, params, - TypeLoc::withoutLoc(voidTy), importedDecl, clangNode); + voidTy, importedDecl, clangNode); setterDecl->setIsObjC(false); setterDecl->setIsDynamic(false); setterDecl->setSelfAccessKind(SelfAccessKind::Mutating); @@ -1684,8 +1678,7 @@ buildSubscriptGetterDecl(ClangImporter::Implementation &Impl, /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), /*GenericParams=*/nullptr, - params, - TypeLoc::withoutLoc(elementTy), dc, + params, elementTy, dc, getter->getClangNode()); thunk->setAccess(getOverridableAccessLevel(dc)); @@ -1737,7 +1730,7 @@ buildSubscriptSetterDecl(ClangImporter::Implementation &Impl, /*ThrowsLoc=*/SourceLoc(), /*GenericParams=*/nullptr, valueIndicesPL, - TypeLoc::withoutLoc(TupleType::getEmpty(C)), dc, + TupleType::getEmpty(C), dc, setter->getClangNode()); thunk->setAccess(getOverridableAccessLevel(dc)); @@ -1922,7 +1915,7 @@ static bool addErrorDomain(NominalTypeDecl *swiftDecl, /*ThrowsLoc=*/SourceLoc(), /*GenericParams=*/nullptr, params, - TypeLoc::withoutLoc(stringTy), swiftDecl); + stringTy, swiftDecl); getterDecl->setIsObjC(false); getterDecl->setIsDynamic(false); getterDecl->setIsTransparent(false); @@ -2262,7 +2255,7 @@ namespace { /// Whether the names we're importing are from the language version the user /// requested, or if these are decls from another version bool isActiveSwiftVersion() const { - return getVersion() == getActiveSwiftVersion(); + return getVersion().withConcurrency(false) == getActiveSwiftVersion().withConcurrency(false); } void recordMemberInContext(const DeclContext *dc, ValueDecl *member) { @@ -2308,7 +2301,7 @@ namespace { return canonicalName; } - // Special handling when we import using the older Swift name. + // Special handling when we import using the alternate Swift name. // // Import using the alternate Swift name. If that fails, or if it's // identical to the active Swift name, we won't introduce an alternate @@ -2317,6 +2310,19 @@ namespace { if (!alternateName) return ImportedName(); + // Importing for concurrency is special in that the same declaration + // is imported both with a completion handler parameter and as 'async', + // creating two separate declarations. + if (getVersion().supportsConcurrency()) { + // If the resulting name isn't special for concurrency, it's not + // different. + if (!alternateName.getAsyncInfo()) + return ImportedName(); + + // Otherwise, it's a legitimately different import. + return alternateName; + } + if (alternateName.getDeclName() == canonicalName.getDeclName() && alternateName.getEffectiveContext().equalsWithoutResolving( canonicalName.getEffectiveContext())) { @@ -2478,6 +2484,13 @@ namespace { return; } + // If this the active and current Swift versions differ based on + // concurrency, it's not actually a variant. + if (getVersion().supportsConcurrency() != + getActiveSwiftVersion().supportsConcurrency()) { + return; + } + // TODO: some versions should be deprecated instead of unavailable ASTContext &ctx = decl->getASTContext(); @@ -3477,14 +3490,33 @@ namespace { Decl *VisitClassTemplateSpecializationDecl( const clang::ClassTemplateSpecializationDecl *decl) { - // FIXME: We could import specializations, but perhaps only as unnamed - // structural types. - return nullptr; + // `Sema::isCompleteType` will try to instantiate the class template as a + // side-effect and we rely on this here. `decl->getDefinition()` can + // return nullptr before the call to sema and return its definition + // afterwards. + if (!Impl.getClangSema().isCompleteType( + decl->getLocation(), + Impl.getClangASTContext().getRecordType(decl))) { + // If we got nullptr definition now it means the type is not complete. + // We don't import incomplete types. + return nullptr; + } + auto def = dyn_cast( + decl->getDefinition()); + assert(def && "Class template instantiation didn't have definition"); + // FIXME: This will instantiate all members of the specialization (and detect + // instantiation failures in them), which can be more than is necessary + // and is more than what Clang does. As a result we reject some C++ + // programs that Clang accepts. + Impl.getClangSema().InstantiateClassTemplateSpecializationMembers( + def->getLocation(), def, clang::TSK_ExplicitInstantiationDefinition); + + return VisitRecordDecl(def); } Decl *VisitClassTemplatePartialSpecializationDecl( - const clang::ClassTemplatePartialSpecializationDecl *decl) { - // Note: templates are not imported. + const clang::ClassTemplatePartialSpecializationDecl *decl) { + // Note: partial template specializations are not imported. return nullptr; } @@ -3826,9 +3858,10 @@ namespace { // FIXME: Poor location info. auto nameLoc = Impl.importSourceLoc(decl->getLocation()); - result = createFuncOrAccessor(Impl.SwiftContext, loc, accessorInfo, name, - nameLoc, bodyParams, resultTy, - /*throws*/ false, dc, decl); + result = createFuncOrAccessor( + Impl.SwiftContext, loc, accessorInfo, name, + nameLoc, bodyParams, resultTy, + /*async*/ false, /*throws*/ false, dc, decl); if (!dc->isModuleScopeContext()) { if (selfIsInOut) @@ -4399,16 +4432,15 @@ namespace { } } - auto result = createFuncOrAccessor(Impl.SwiftContext, - /*funcLoc*/SourceLoc(), - accessorInfo, - importedName.getDeclName(), - /*nameLoc*/SourceLoc(), - bodyParams, Type(), - importedName.getErrorInfo().hasValue(), - dc, decl); - - result->setAccess(getOverridableAccessLevel(dc)); + // Determine whether the function is throwing and/or async. + bool throws = importedName.getErrorInfo().hasValue(); + bool async = false; + auto asyncConvention = importedName.getAsyncInfo(); + if (asyncConvention) { + async = true; + if (asyncConvention->isThrowing()) + throws = true; + } auto resultTy = importedType.getType(); auto isIUO = importedType.isImplicitlyUnwrapped(); @@ -4433,8 +4465,15 @@ namespace { } } - // Record the return type. - result->getBodyResultTypeLoc().setType(resultTy); + auto result = createFuncOrAccessor(Impl.SwiftContext, + /*funcLoc*/SourceLoc(), + accessorInfo, + importedName.getDeclName(), + /*nameLoc*/SourceLoc(), + bodyParams, resultTy, + async, throws, dc, decl); + + result->setAccess(getOverridableAccessLevel(dc)); // Optional methods in protocols. if (decl->getImplementationControl() == clang::ObjCMethodDecl::Optional && @@ -4464,6 +4503,11 @@ namespace { result->setForeignErrorConvention(*errorConvention); } + // Record the async convention. + if (asyncConvention) { + result->setForeignAsyncConvention(*asyncConvention); + } + // Handle attributes. if (decl->hasAttr() && isa(result) && @@ -4495,6 +4539,7 @@ namespace { Impl.addAlternateDecl(result, cast(imported)); } } + return result; } @@ -6435,6 +6480,7 @@ ConstructorDecl *SwiftDeclConverter::importConstructor( return known->second; // Create the actual constructor. + assert(!importedName.getAsyncInfo()); auto result = Impl.createDeclWithClangNode( objcMethod, AccessLevel::Public, importedName.getDeclName(), /*NameLoc=*/SourceLoc(), failability, /*FailabilityLoc=*/SourceLoc(), @@ -6864,12 +6910,14 @@ SwiftDeclConverter::importSubscript(Decl *decl, auto &C = Impl.SwiftContext; auto bodyParams = ParameterList::create(C, getterIndex); DeclName name(C, DeclBaseName::createSubscript(), {Identifier()}); - auto subscript = Impl.createDeclWithClangNode( - getter->getClangNode(), getOverridableAccessLevel(dc), name, - /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None, - decl->getLoc(), bodyParams, decl->getLoc(), - TypeLoc::withoutLoc(elementTy), dc, - /*GenericParams=*/nullptr); + auto *const subscript = SubscriptDecl::createImported(C, + name, decl->getLoc(), + bodyParams, decl->getLoc(), + elementTy, dc, + getter->getClangNode()); + const auto access = getOverridableAccessLevel(dc); + subscript->setAccess(access); + subscript->setSetterAccess(access); // Build the thunks. AccessorDecl *getterThunk = @@ -7135,6 +7183,11 @@ void SwiftDeclConverter::importMirroredProtocolMembers( if (isa(afd)) return; + // Asynch methods are also always imported without async, so don't + // record them here. + if (afd->hasAsync()) + return; + auto objcMethod = dyn_cast_or_null(member->getClangDecl()); if (!objcMethod) @@ -8538,8 +8591,7 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc, /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), /*GenericParams=*/nullptr, - params, - TypeLoc::withoutLoc(type), dc); + params, type, dc); func->setStatic(isStatic); func->setAccess(getOverridableAccessLevel(dc)); func->setIsObjC(false); @@ -8885,7 +8937,7 @@ ClangImporter::getEnumConstantName(const clang::EnumConstantDecl *enumConstant){ // linkage dependency. struct ClangDeclTraceFormatter : public UnifiedStatsReporter::TraceFormatter { - void traceName(const void *Entity, raw_ostream &OS) const { + void traceName(const void *Entity, raw_ostream &OS) const override { if (!Entity) return; const clang::Decl *CD = static_cast(Entity); @@ -8908,7 +8960,7 @@ struct ClangDeclTraceFormatter : public UnifiedStatsReporter::TraceFormatter { } void traceLoc(const void *Entity, SourceManager *SM, - clang::SourceManager *CSM, raw_ostream &OS) const { + clang::SourceManager *CSM, raw_ostream &OS) const override { if (!Entity) return; if (CSM) { diff --git a/lib/ClangImporter/ImportName.cpp b/lib/ClangImporter/ImportName.cpp index 1611d20507369..fc0313bbc91df 100644 --- a/lib/ClangImporter/ImportName.cpp +++ b/lib/ClangImporter/ImportName.cpp @@ -31,8 +31,10 @@ #include "swift/Basic/StringExtras.h" #include "swift/ClangImporter/ClangImporterOptions.h" #include "swift/Parse/Parser.h" +#include "swift/Strings.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/Mangle.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Module.h" #include "clang/Basic/OperatorKinds.h" @@ -805,8 +807,6 @@ static bool omitNeedlessWordsInFunctionName( Optional errorParamIndex, bool returnsSelf, bool isInstanceMethod, NameImporter &nameImporter) { clang::ASTContext &clangCtx = nameImporter.getClangContext(); - const version::Version &swiftLanguageVersion = - nameImporter.getLangOpts().EffectiveLanguageVersion; // Collect the parameter type names. StringRef firstParamName; @@ -835,8 +835,7 @@ static bool omitNeedlessWordsInFunctionName( bool hasDefaultArg = ClangImporter::Implementation::inferDefaultArgument( param->getType(), - getParamOptionality(swiftLanguageVersion, param, - !nonNullArgs.empty() && nonNullArgs[i]), + getParamOptionality(param, !nonNullArgs.empty() && nonNullArgs[i]), nameImporter.getIdentifier(baseName), argumentName, i == 0, isLastParameter, nameImporter) != DefaultArgumentKind::None; @@ -1137,6 +1136,181 @@ Optional NameImporter::considerErrorImport( return None; } +/// Whether the given parameter name identifies a completion handler. +static bool isCompletionHandlerParamName(StringRef paramName) { + return paramName == "completionHandler" || paramName == "completion" || + paramName == "withCompletionHandler"; +} + +/// Whether the give base name implies that the first parameter is a completion +/// handler. +/// +/// \returns a trimmed base name when it does, \c None others +static Optional isCompletionHandlerInBaseName(StringRef basename) { + if (basename.endswith("WithCompletionHandler")) { + return basename.drop_back(strlen("WithCompletionHandler")); + } + + if (basename.endswith("WithCompletion")) { + return basename.drop_back(strlen("WithCompletion")); + } + + return None; +} + + +// Determine whether the given type is a nullable NSError type. +static bool isNullableNSErrorType( + clang::ASTContext &clangCtx, clang::QualType type) { + auto objcPtrType = type->getAs(); + if (!objcPtrType) + return false; + + auto iface = objcPtrType->getInterfaceDecl(); + if (!iface || iface->getName() != "NSError") + return false; + + // If nullability is specified, check it. + if (auto nullability = type->getNullability(clangCtx)) { + switch (translateNullability(*nullability)) { + case OTK_None: + return false; + + case OTK_ImplicitlyUnwrappedOptional: + case OTK_Optional: + return true; + } + } + + // Otherwise, assume it's nullable. + return true; +} + +Optional +NameImporter::considerAsyncImport( + const clang::ObjCMethodDecl *clangDecl, + StringRef &baseName, + SmallVectorImpl ¶mNames, + ArrayRef params, + bool isInitializer, bool hasCustomName, + Optional errorInfo) { + // If there are no unclaimed parameters, there's no . + unsigned errorParamAdjust = errorInfo ? 1 : 0; + if (params.size() - errorParamAdjust == 0) + return None; + + // If the # of parameter names doesn't line up with the # of parameters, + // bail out. There are extra C parameters on the method or a custom name + // was incorrect. + if (params.size() != paramNames.size() + errorParamAdjust) + return None; + + // The last parameter will be the completion handler for an async function. + unsigned completionHandlerParamIndex = params.size() - 1; + unsigned completionHandlerParamNameIndex = paramNames.size() - 1; + + // Determine whether the naming indicates that this is a completion + // handler. + Optional newBaseName; + if (isCompletionHandlerParamName(paramNames[completionHandlerParamNameIndex])) { + // The argument label itself has an appropriate name. + } else if (!hasCustomName && completionHandlerParamIndex == 0 && + (newBaseName = isCompletionHandlerInBaseName(baseName))) { + // The base name implies that the first parameter is a completion handler. + } else if (isCompletionHandlerParamName( + params[completionHandlerParamIndex]->getName())) { + // The parameter has an appropriate name. + } else { + return None; + } + + // Used for returns once we've determined that the method cannot be + // imported as async, even though it has what looks like a completion handler + // parameter. + auto notAsync = [&](const char *reason) -> Optional { +#ifdef ASYNC_IMPORT_DEBUG + llvm::errs() << "*** failed async import: " << reason << "\n"; + clangDecl->dump(llvm::errs()); +#endif + + return None; + }; + + // Initializers cannot be 'async'. + // FIXME: We might eventually allow this. + if (isInitializer) + return notAsync("initializers cannot be async"); + + // Accessors are never imported as async. + if (clangDecl->isPropertyAccessor()) + return notAsync("method is a property accessor"); + + // Check whether we method has a suitable return type. + if (clangDecl->getReturnType()->isVoidType()) { + // 'void' is the common case; the method produces no synchronous result. + } else if (errorInfo && + ForeignErrorConvention::resultTypeErasedToVoid( + errorInfo->getKind())) { + // The method has been imported as throwing in a manner that erased the + // result type to Void. + } else { + return notAsync("method does not return void"); + } + + // The completion handler parameter must have block type. + auto completionHandlerParam = params[completionHandlerParamIndex]; + if (!isBlockParameter(completionHandlerParam)) + return notAsync("parameter is not a block"); + + // Dig out the function type of the completion handler's block type. + // If there is no prototype, (e.g., the completion handler is of type + // void (^)()), we cannot importer it. + auto completionHandlerFunctionType = + completionHandlerParam->getType()->castAs() + ->getPointeeType()->getAs(); + if (!completionHandlerFunctionType) + return notAsync("block parameter does not have a prototype"); + + // The completion handler parameter must itself return 'void'. + if (!completionHandlerFunctionType->getReturnType()->isVoidType()) + return notAsync("completion handler parameter does not return 'void'"); + + // Scan the parameters of the block type to look for a parameter of a + // nullable NSError type, which would indicate that the async method could + // throw. + Optional completionHandlerErrorParamIndex; + auto completionHandlerParamTypes = + completionHandlerFunctionType->getParamTypes(); + auto &clangCtx = clangDecl->getASTContext(); + for (unsigned paramIdx : indices(completionHandlerParamTypes)) { + auto paramType = completionHandlerParamTypes[paramIdx]; + + // We are only interested in nullable NSError parameters. + if (!isNullableNSErrorType(clangCtx, paramType)) + continue; + + // If this is the first nullable error parameter, note that. + if (!completionHandlerErrorParamIndex) { + completionHandlerErrorParamIndex = paramIdx; + continue; + } + + // More than one nullable NSError parameter. Don't import as throwing. + completionHandlerErrorParamIndex = None; + break; + } + + // Drop the completion handler parameter name. + paramNames.erase(paramNames.begin() + completionHandlerParamNameIndex); + + // Update the base name, if needed. + if (newBaseName && !hasCustomName) + baseName = *newBaseName; + + return ForeignAsyncConvention( + completionHandlerParamIndex, completionHandlerErrorParamIndex); +} + bool NameImporter::hasErrorMethodNameCollision( const clang::ObjCMethodDecl *method, unsigned paramIndex, StringRef suffixToStrip) { @@ -1348,7 +1522,8 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D, else if (parsedName.IsSetter) result.info.accessorKind = ImportedAccessorKind::PropertySetter; - if (method && parsedName.IsFunctionName) { + if (method && parsedName.IsFunctionName && + result.info.accessorKind == ImportedAccessorKind::None) { // Get the parameters. ArrayRef params{method->param_begin(), method->param_end()}; @@ -1360,6 +1535,21 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D, result.info.hasErrorInfo = true; result.info.errorInfo = *errorInfo; } + + if (version.supportsConcurrency()) { + if (auto asyncInfo = considerAsyncImport( + method, parsedName.BaseName, parsedName.ArgumentLabels, + params, isInitializer, /*hasCustomName=*/true, + result.getErrorInfo())) { + result.info.hasAsyncInfo = true; + result.info.asyncInfo = *asyncInfo; + + // Update the name to reflect the new parameter labels. + result.declName = formDeclName( + swiftCtx, parsedName.BaseName, parsedName.ArgumentLabels, + /*isFunction=*/true, isInitializer); + } + } } return result; @@ -1622,6 +1812,17 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D, result.info.accessorKind = ImportedAccessorKind::SubscriptSetter; } + if (version.supportsConcurrency() && + result.info.accessorKind == ImportedAccessorKind::None) { + if (auto asyncInfo = considerAsyncImport( + objcMethod, baseName, argumentNames, params, isInitializer, + /*hasCustomName=*/false, + result.getErrorInfo())) { + result.info.hasAsyncInfo = true; + result.info.asyncInfo = *asyncInfo; + } + } + break; } } @@ -1698,6 +1899,34 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D, } } + if (auto classTemplateSpecDecl = + dyn_cast(D)) { + if (!isa(D)) { + + auto &astContext = classTemplateSpecDecl->getASTContext(); + // Itanium mangler produces valid Swift identifiers, use it to generate a name for + // this instantiation. + clang::MangleContext *mangler = clang::ItaniumMangleContext::create( + astContext, astContext.getDiagnostics()); + llvm::SmallString<128> storage; + llvm::raw_svector_ostream buffer(storage); + mangler->mangleTypeName(astContext.getRecordType(classTemplateSpecDecl), + buffer); + + // The Itanium mangler does not provide a way to get the mangled + // representation of a type. Instead, we call mangleTypeName() that + // returns the name of the RTTI typeinfo symbol, and remove the _ZTS + // prefix. Then we prepend __CxxTemplateInst to reduce chances of conflict + // with regular C and C++ structs. + llvm::SmallString<128> mangledNameStorage; + llvm::raw_svector_ostream mangledName(mangledNameStorage); + assert(buffer.str().take_front(4) == "_ZTS"); + mangledName << CXX_TEMPLATE_INST_PREFIX << buffer.str().drop_front(4); + + baseName = swiftCtx.getIdentifier(mangledName.str()).get(); + } + } + // swift_newtype-ed declarations may have common words with the type name // stripped. if (auto newtypeDecl = findSwiftNewtype(D, clangSema, version)) { @@ -1865,6 +2094,7 @@ bool NameImporter::forEachDistinctImportName( seenNames.push_back(key); activeVersion.forEachOtherImportNameVersion( + swiftCtx.LangOpts.EnableExperimentalConcurrency, [&](ImportNameVersion nameVersion) { // Check to see if the name is different. ImportedName newName = importName(decl, nameVersion); diff --git a/lib/ClangImporter/ImportName.h b/lib/ClangImporter/ImportName.h index ddb4b0aa4105c..09d90703563c9 100644 --- a/lib/ClangImporter/ImportName.h +++ b/lib/ClangImporter/ImportName.h @@ -23,6 +23,7 @@ #include "swift/Basic/Version.h" #include "swift/AST/ASTContext.h" #include "swift/AST/Decl.h" +#include "swift/AST/ForeignAsyncConvention.h" #include "swift/AST/ForeignErrorConvention.h" #include "clang/Sema/Sema.h" @@ -42,15 +43,18 @@ enum { NumImportedAccessorKindBits = 3 }; /// The name version class ImportNameVersion : public RelationalOperationsBase { - unsigned rawValue; + unsigned rawValue : 31; + unsigned concurrency : 1; + friend llvm::DenseMapInfo; enum AsConstExpr_t { AsConstExpr }; - constexpr ImportNameVersion() : rawValue(0) {} + constexpr ImportNameVersion() : rawValue(0), concurrency(false) {} constexpr ImportNameVersion(unsigned version, AsConstExpr_t) - : rawValue(version) {} - explicit ImportNameVersion(unsigned version) : rawValue(version) { + : rawValue(version), concurrency(false) {} + explicit ImportNameVersion(unsigned version, bool concurrency = false) + : rawValue(version), concurrency(concurrency) { assert(version >= 2 && "only Swift 2 and later are supported"); } public: @@ -67,7 +71,7 @@ class ImportNameVersion : public RelationalOperationsBase { return ImportNameVersion::swift4_2(); } unsigned major = version[0]; - return ImportNameVersion(major >= 5 ? major + 1 : major); + return ImportNameVersion(major >= 5 ? major + 1 : major, false); } unsigned majorVersionNumber() const { @@ -89,11 +93,21 @@ class ImportNameVersion : public RelationalOperationsBase { return llvm::VersionTuple(majorVersionNumber(), minorVersionNumber()); } + /// Whether to consider importing functions as 'async'. + bool supportsConcurrency() const { return concurrency; } + + ImportNameVersion withConcurrency(bool concurrency) const { + ImportNameVersion result = *this; + result.concurrency = concurrency; + return result; + } + bool operator==(ImportNameVersion other) const { - return rawValue == other.rawValue; + return rawValue == other.rawValue && concurrency == other.concurrency; } bool operator<(ImportNameVersion other) const { - return rawValue < other.rawValue; + return rawValue < other.rawValue || + (rawValue == other.rawValue && concurrency < other.concurrency); } /// Calls \p action for each name version other than this one, first going @@ -102,10 +116,19 @@ class ImportNameVersion : public RelationalOperationsBase { /// /// This is the most useful order for importing compatibility stubs. void forEachOtherImportNameVersion( + bool withConcurrency, llvm::function_ref action) const { assert(*this >= ImportNameVersion::swift2()); ImportNameVersion nameVersion = *this; + assert(!nameVersion.supportsConcurrency()); + + // If we've been asked to also consider concurrency, do so for the + // primary version (only). + if (withConcurrency) { + action(nameVersion.withConcurrency(true)); + } + while (nameVersion > ImportNameVersion::swift2()) { --nameVersion.rawValue; action(nameVersion); @@ -175,6 +198,10 @@ class ImportedName { /// throwing Swift methods, describes how the mapping is performed. ForeignErrorConvention::Info errorInfo; + /// For names that map Objective-C completion handlers into async + /// Swift methods, describes how the mapping is performed. + ForeignAsyncConvention asyncInfo; + /// For a declaration name that makes the declaration into an /// instance member, the index of the "Self" parameter. unsigned selfIndex; @@ -201,11 +228,13 @@ class ImportedName { unsigned hasErrorInfo : 1; + unsigned hasAsyncInfo : 1; + Info() : errorInfo(), selfIndex(), initKind(CtorInitializerKind::Designated), accessorKind(ImportedAccessorKind::None), hasCustomName(false), droppedVariadic(false), importAsMember(false), hasSelfIndex(false), - hasErrorInfo(false) {} + hasErrorInfo(false), hasAsyncInfo(false) {} } info; public: @@ -239,6 +268,14 @@ class ImportedName { return None; } + /// For names that map Objective-C methods with completion handlers into + /// async Swift methods, describes how the mapping is performed. + Optional getAsyncInfo() const { + if (info.hasAsyncInfo) + return info.asyncInfo; + return None; + } + /// For a declaration name that makes the declaration into an /// instance member, the index of the "Self" parameter. Optional getSelfIndex() const { @@ -416,6 +453,14 @@ class NameImporter { ArrayRef params, bool isInitializer, bool hasCustomName); + Optional + considerAsyncImport(const clang::ObjCMethodDecl *clangDecl, + StringRef &baseName, + SmallVectorImpl ¶mNames, + ArrayRef params, + bool isInitializer, bool hasCustomName, + Optional errorInfo); + EffectiveClangContext determineEffectiveContext(const clang::NamedDecl *, const clang::DeclContext *, ImportNameVersion version); diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 15da7f4e5ed9b..13b29787a68ec 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -1747,8 +1747,7 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList( // Check nullability of the parameter. OptionalTypeKind OptionalityOfParam = - getParamOptionality(SwiftContext.LangOpts.EffectiveLanguageVersion, - param, !nonNullArgs.empty() && nonNullArgs[index]); + getParamOptionality(param, !nonNullArgs.empty() && nonNullArgs[index]); ImportTypeKind importKind = ImportTypeKind::Parameter; if (param->hasAttr()) @@ -1989,6 +1988,42 @@ static Type mapGenericArgs(const DeclContext *fromDC, return type.subst(subs); } +/// Decompose the type of a completion handler parameter in a function +/// imported as 'async' and produce the result type of the 'async' function. +static Type decomposeCompletionHandlerType( + Type paramTy, ForeignAsyncConvention info) { + auto fnType = paramTy->lookThroughAllOptionalTypes()->getAs(); + if (!fnType) + return Type(); + + SmallVector resultTypeElts; + auto params = fnType->getParams(); + for (unsigned paramIdx : indices(params)) { + const auto ¶m = params[paramIdx]; + if (param.isInOut() || param.isVariadic()) + return Type(); + + // If there is an error parameter to the completion handler, it is + // not part of the result type of the asynchronous function. + if (info.completionHandlerErrorParamIndex() && + paramIdx == *info.completionHandlerErrorParamIndex()) + continue; + + resultTypeElts.push_back(param.getPlainType()); + } + + switch (resultTypeElts.size()) { + case 0: + return paramTy->getASTContext().getVoidDecl()->getDeclaredInterfaceType(); + + case 1: + return resultTypeElts.front().getType(); + + default: + return TupleType::get(resultTypeElts, paramTy->getASTContext()); + } +} + ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType( const DeclContext *dc, const clang::ObjCMethodDecl *clangDecl, ArrayRef params, bool isVariadic, @@ -2025,6 +2060,7 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType( CanType origSwiftResultTy; Optional errorInfo = importedName.getErrorInfo(); + auto asyncInfo = importedName.getAsyncInfo(); OptionalTypeKind OptionalityOfReturn; if (clangDecl->hasAttr()) { OptionalityOfReturn = OTK_None; @@ -2123,12 +2159,14 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType( continue; } + bool paramIsCompletionHandler = + asyncInfo && paramIndex == asyncInfo->completionHandlerParamIndex(); + // Import the parameter type into Swift. // Check nullability of the parameter. OptionalTypeKind optionalityOfParam - = getParamOptionality(SwiftContext.LangOpts.EffectiveLanguageVersion, - param, + = getParamOptionality(param, !nonNullArgs.empty() && nonNullArgs[paramIndex]); bool allowNSUIntegerAsIntInParam = isFromSystemModule; @@ -2193,6 +2231,21 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType( continue; } + // If this is a completion handler, figure out it's effect on the result + // type but don't build it into the parameter type. + if (paramIsCompletionHandler) { + if (Type replacedSwiftResultTy = + decomposeCompletionHandlerType(swiftParamTy, *asyncInfo)) { + swiftResultTy = replacedSwiftResultTy; + + // FIXME: We will need an equivalent to "error parameter is replaced" + // for asynchronous functions. Perhaps add "async: ()"? + continue; + } + + llvm_unreachable("async info computed incorrectly?"); + } + // Map __attribute__((noescape)) to @noescape. bool addNoEscapeAttr = false; if (param->hasAttr()) { diff --git a/lib/ClangImporter/SwiftLookupTable.cpp b/lib/ClangImporter/SwiftLookupTable.cpp index 74a64dcb025d5..6653b2d0ee38d 100644 --- a/lib/ClangImporter/SwiftLookupTable.cpp +++ b/lib/ClangImporter/SwiftLookupTable.cpp @@ -1857,6 +1857,7 @@ SwiftNameLookupExtension::hashExtension(llvm::hash_code code) const { SWIFT_LOOKUP_TABLE_VERSION_MAJOR, SWIFT_LOOKUP_TABLE_VERSION_MINOR, inferImportAsMember, + swiftCtx.LangOpts.EnableExperimentalConcurrency, version::getSwiftFullVersion()); } @@ -1881,10 +1882,16 @@ void importer::addEntryToLookupTable(SwiftLookupTable &table, // struct names when relevant, not just pointer names. That way we can check // both CFDatabase.def and the objc_bridge attribute and cover all our bases. if (auto *tagDecl = dyn_cast(named)) { - if (!tagDecl->getDefinition()) + // We add entries for ClassTemplateSpecializations that don't have + // definition. It's possible that the decl will be instantiated by + // SwiftDeclConverter later on. We cannot force instantiating + // ClassTemplateSPecializations here because we're currently writing the + // AST, so we cannot modify it. + if (!isa(named) && + !tagDecl->getDefinition()) { return; + } } - // If we have a name to import as, add this entry to the table. auto currentVersion = ImportNameVersion::fromOptions(nameImporter.getLangOpts()); @@ -2077,6 +2084,19 @@ void SwiftLookupTableWriter::populateTableWithDecl(SwiftLookupTable &table, // Add this entry to the lookup table. addEntryToLookupTable(table, named, nameImporter); + if (auto typedefDecl = dyn_cast(named)) { + if (auto typedefType = dyn_cast( + typedefDecl->getUnderlyingType())) { + if (auto CTSD = dyn_cast( + typedefType->getAsTagDecl())) { + // Adding template instantiation behind typedef as a top-level entry + // so the instantiation appears in the API. + assert(!isa(CTSD) && + "Class template partial specialization cannot appear behind typedef"); + addEntryToLookupTable(table, CTSD, nameImporter); + } + } + } } void SwiftLookupTableWriter::populateTable(SwiftLookupTable &table, diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp index 3628481d8a47e..f49ba90261714 100644 --- a/lib/Demangling/Demangler.cpp +++ b/lib/Demangling/Demangler.cpp @@ -2669,7 +2669,7 @@ NodePointer Demangler::demangleSpecAttributes(Node::Kind SpecKind) { } NodePointer Demangler::demangleWitness() { - switch (nextChar()) { + switch (char c = nextChar()) { case 'C': return createWithChild(Node::Kind::EnumCase, popNode(isEntity)); @@ -2811,6 +2811,30 @@ NodePointer Demangler::demangleWitness() { return nullptr; } } + case 'Z': + case 'z': { + auto declList = createNode(Node::Kind::GlobalVariableOnceDeclList); + std::vector vars; + while (auto sig = popNode(Node::Kind::FirstElementMarker)) { + auto identifier = popNode(isDeclName); + if (!identifier) + return nullptr; + vars.push_back(identifier); + } + for (auto i = vars.rbegin(); i != vars.rend(); ++i) { + declList->addChild(*i, *this); + } + + auto context = popContext(); + if (!context) + return nullptr; + Node::Kind kind = c == 'Z' + ? Node::Kind::GlobalVariableOnceFunction + : Node::Kind::GlobalVariableOnceToken; + return createWithChildren(kind, + context, + declList); + } default: return nullptr; } diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp index e7ea0e52e29d6..3a7fc824699b2 100644 --- a/lib/Demangling/NodePrinter.cpp +++ b/lib/Demangling/NodePrinter.cpp @@ -552,6 +552,9 @@ class NodePrinter { case Node::Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction: case Node::Kind::NoncanonicalSpecializedGenericTypeMetadata: case Node::Kind::NoncanonicalSpecializedGenericTypeMetadataCache: + case Node::Kind::GlobalVariableOnceDeclList: + case Node::Kind::GlobalVariableOnceFunction: + case Node::Kind::GlobalVariableOnceToken: return false; } printer_unreachable("bad node kind"); @@ -2466,6 +2469,28 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) { Printer << "cache variable for noncanonical specialized generic type metadata for "; print(Node->getChild(0)); return nullptr; + case Node::Kind::GlobalVariableOnceToken: + case Node::Kind::GlobalVariableOnceFunction: + Printer << (kind == Node::Kind::GlobalVariableOnceToken + ? "one-time initialization token for " + : "one-time initialization function for "); + printContext(Node->getChild(0)); + print(Node->getChild(1)); + return nullptr; + case Node::Kind::GlobalVariableOnceDeclList: + if (Node->getNumChildren() == 1) { + print(Node->getChild(0)); + } else { + Printer << '('; + for (unsigned i = 0, e = Node->getNumChildren(); i < e; ++i) { + if (i != 0) { + Printer << ", "; + } + print(Node->getChild(i)); + } + Printer << ')'; + } + return nullptr; } printer_unreachable("bad node kind!"); } diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp index ba7ca2eb51960..7df26cbfad047 100644 --- a/lib/Demangling/OldRemangler.cpp +++ b/lib/Demangling/OldRemangler.cpp @@ -2139,6 +2139,15 @@ void Remangler::mangleAccessorFunctionReference(Node *node) { void Remangler::mangleMetadataInstantiationCache(Node *node) { unreachable("unsupported"); } +void Remangler::mangleGlobalVariableOnceToken(Node *node) { + unreachable("unsupported"); +} +void Remangler::mangleGlobalVariableOnceFunction(Node *node) { + unreachable("unsupported"); +} +void Remangler::mangleGlobalVariableOnceDeclList(Node *node) { + unreachable("unsupported"); +} void Remangler::mangleCanonicalSpecializedGenericMetaclass(Node *node) { Buffer << "MM"; diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp index 60dfeafaee925..8abad3f38cf0f 100644 --- a/lib/Demangling/Remangler.cpp +++ b/lib/Demangling/Remangler.cpp @@ -2566,6 +2566,23 @@ void Remangler::mangleNoncanonicalSpecializedGenericTypeMetadataCache(Node *node Buffer << "MJ"; } +void Remangler::mangleGlobalVariableOnceToken(Node *node) { + mangleChildNodes(node); + Buffer << "Wz"; +} + +void Remangler::mangleGlobalVariableOnceFunction(Node *node) { + mangleChildNodes(node); + Buffer << "WZ"; +} + +void Remangler::mangleGlobalVariableOnceDeclList(Node *node) { + for (unsigned i = 0, e = node->getNumChildren(); i < e; ++i) { + mangle(node->getChild(i)); + Buffer << '_'; + } +} + } // anonymous namespace /// The top-level interface to the remangler. diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp index 0dcde774e73f8..25117800eed96 100644 --- a/lib/Driver/Action.cpp +++ b/lib/Driver/Action.cpp @@ -33,6 +33,7 @@ const char *Action::getClassName(Kind AC) { case Kind::GenerateDSYMJob: return "generate-dSYM"; case Kind::VerifyDebugInfoJob: return "verify-debug-info"; case Kind::GeneratePCHJob: return "generate-pch"; + case Kind::VerifyModuleInterfaceJob: return "verify-module-interface"; } llvm_unreachable("invalid class"); @@ -65,3 +66,5 @@ void GenerateDSYMJobAction::anchor() {} void VerifyDebugInfoJobAction::anchor() {} void GeneratePCHJobAction::anchor() {} + +void VerifyModuleInterfaceJobAction::anchor() {} diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 74640ed9ac387..1a0e75575438c 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -2194,6 +2194,30 @@ void Driver::buildActions(SmallVectorImpl &TopLevelActions, TopLevelActions.push_back(MergeModuleAction); TopLevelActions.append(AllLinkerInputs.begin(), AllLinkerInputs.end()); } + +#ifdef NDEBUG + bool verifyInterfacesByDefault = false; +#else + bool verifyInterfacesByDefault = true; +#endif + + if (MergeModuleAction + && Args.hasFlag(options::OPT_verify_emitted_module_interface, + options::OPT_no_verify_emitted_module_interface, + verifyInterfacesByDefault)) { + if (Args.hasArgNoClaim(options::OPT_emit_module_interface, + options::OPT_emit_module_interface_path)) { + TopLevelActions.push_back( + C.createAction(MergeModuleAction, + file_types::TY_SwiftModuleInterfaceFile)); + } + + if (Args.hasArgNoClaim(options::OPT_emit_private_module_interface_path)) { + TopLevelActions.push_back( + C.createAction(MergeModuleAction, + file_types::TY_PrivateSwiftModuleInterfaceFile)); + } + } } bool Driver::handleImmediateArgs(const ArgList &Args, const ToolChain &TC) { diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index 784348922f6fb..522a9727c454a 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -111,6 +111,7 @@ std::unique_ptr ToolChain::constructJob( CASE(GeneratePCHJob) CASE(AutolinkExtractJob) CASE(REPLJob) + CASE(VerifyModuleInterfaceJob) #undef CASE case Action::Kind::Input: llvm_unreachable("not a JobAction"); diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index d92cb1c568bc4..7c721cabb33c6 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -212,7 +212,6 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, inputArgs.AddLastArg(arguments, options::OPT_require_explicit_availability_target); inputArgs.AddLastArg(arguments, options::OPT_enable_testing); inputArgs.AddLastArg(arguments, options::OPT_enable_private_imports); - inputArgs.AddLastArg(arguments, options::OPT_enable_cxx_interop); inputArgs.AddLastArg(arguments, options::OPT_g_Group); inputArgs.AddLastArg(arguments, options::OPT_debug_info_format); inputArgs.AddLastArg(arguments, options::OPT_import_underlying_module); @@ -1047,6 +1046,41 @@ ToolChain::constructInvocation(const MergeModuleJobAction &job, return II; } +ToolChain::InvocationInfo +ToolChain::constructInvocation(const VerifyModuleInterfaceJobAction &job, + const JobContext &context) const { + InvocationInfo II{SWIFT_EXECUTABLE_NAME}; + ArgStringList &Arguments = II.Arguments; + II.allowsResponseFiles = true; + + for (auto &s : getDriver().getSwiftProgramArgs()) + Arguments.push_back(s.c_str()); + Arguments.push_back("-frontend"); + + Arguments.push_back("-typecheck-module-from-interface"); + + size_t sizeBefore = Arguments.size(); + addInputsOfType(Arguments, context.Inputs, context.Args, job.getInputType()); + + (void)sizeBefore; + assert(Arguments.size() - sizeBefore == 1 && + "should verify exactly one module interface per job"); + + addCommonFrontendArgs(context.OI, context.Output, context.Args, Arguments); + addRuntimeLibraryFlags(context.OI, Arguments); + + addOutputsOfType(Arguments, context.Output, context.Args, + file_types::TY_SerializedDiagnostics, + "-serialize-diagnostics-path"); + + context.Args.AddLastArg(Arguments, options::OPT_import_objc_header); + + Arguments.push_back("-module-name"); + Arguments.push_back(context.Args.MakeArgString(context.OI.ModuleName)); + + return II; +} + ToolChain::InvocationInfo ToolChain::constructInvocation(const ModuleWrapJobAction &job, const JobContext &context) const { diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index 05b0ed04f5083..c876a44f87383 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -147,7 +147,8 @@ bool ArgsToFrontendOptionsConverter::convert( Opts.RequestedAction = determineRequestedAction(Args); } - if (Opts.RequestedAction == FrontendOptions::ActionType::CompileModuleFromInterface) { + if (Opts.RequestedAction == FrontendOptions::ActionType::CompileModuleFromInterface || + Opts.RequestedAction == FrontendOptions::ActionType::TypecheckModuleFromInterface) { // The situations where we use this action, e.g. explicit module building and // generating prebuilt module cache, don't need synchronization. We should avoid // using lock files for them. @@ -354,6 +355,8 @@ ArgsToFrontendOptionsConverter::determineRequestedAction(const ArgList &args) { return FrontendOptions::ActionType::EmitImportedModules; if (Opt.matches(OPT_scan_dependencies)) return FrontendOptions::ActionType::ScanDependencies; + if (Opt.matches(OPT_scan_clang_dependencies)) + return FrontendOptions::ActionType::ScanClangDependencies; if (Opt.matches(OPT_parse)) return FrontendOptions::ActionType::Parse; if (Opt.matches(OPT_resolve_imports)) @@ -389,6 +392,8 @@ ArgsToFrontendOptionsConverter::determineRequestedAction(const ArgList &args) { return FrontendOptions::ActionType::Immediate; if (Opt.matches(OPT_compile_module_from_interface)) return FrontendOptions::ActionType::CompileModuleFromInterface; + if (Opt.matches(OPT_typecheck_module_from_interface)) + return FrontendOptions::ActionType::TypecheckModuleFromInterface; llvm_unreachable("Unhandled mode option"); } @@ -401,8 +406,7 @@ bool ArgsToFrontendOptionsConverter::setUpInputKindAndImmediateArgs() { if (Opts.InputsAndOutputs.verifyInputs( Diags, treatAsSIL, Opts.RequestedAction == FrontendOptions::ActionType::REPL, - (Opts.RequestedAction == FrontendOptions::ActionType::NoneAction || - Opts.RequestedAction == FrontendOptions::ActionType::PrintVersion))){ + !FrontendOptions::doesActionRequireInputs(Opts.RequestedAction))) { return true; } if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate) { diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index 0cb3c72b15b96..08988f9a078ee 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -23,6 +23,7 @@ target_link_libraries(swiftFrontend PRIVATE swiftSILGen swiftSILOptimizer swiftIRGen + swiftLocalization swiftSema swiftSerialization swiftTBDGen) diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 32ba70f163950..874cf47f790eb 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -325,6 +325,8 @@ static void ParseModuleInterfaceArgs(ModuleInterfaceOptions &Opts, Args.hasArg(OPT_experimental_print_full_convention); Opts.ExperimentalSPIImports |= Args.hasArg(OPT_experimental_spi_imports); + Opts.DebugPrintInvalidSyntax |= + Args.hasArg(OPT_debug_emit_invalid_swiftinterface_syntax); } /// Save a copy of any flags marked as ModuleInterfaceOption, if running @@ -913,7 +915,8 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, } if (const Arg *A = Args.getLastArg(OPT_placeholder_dependency_module_map)) Opts.PlaceholderDependencyModuleMap = A->getValue(); - + if (const Arg *A = Args.getLastArg(OPT_batch_scan_input_file)) + Opts.BatchScanInputFilePath = A->getValue(); // Opts.RuntimeIncludePath is set by calls to // setRuntimeIncludePath() or setMainExecutablePath(). // Opts.RuntimeImportPath is set by calls to diff --git a/lib/Frontend/DependencyVerifier.cpp b/lib/Frontend/DependencyVerifier.cpp index b8950be51032d..2e468f83de842 100644 --- a/lib/Frontend/DependencyVerifier.cpp +++ b/lib/Frontend/DependencyVerifier.cpp @@ -481,71 +481,50 @@ bool DependencyVerifier::verifyObligations( auto &diags = SF->getASTContext().Diags; for (auto &expectation : ExpectedDependencies) { const bool wantsCascade = expectation.isCascading(); - switch (expectation.Info.Kind) { - case Expectation::Kind::Negative: + if (expectation.Info.Kind == Expectation::Kind::Negative) { // We'll verify negative expectations separately. NegativeExpectations.insert({expectation.MessageRange, expectation}); - break; - case Expectation::Kind::Member: - matchExpectationOrFail( - OM, expectation, - [&](Obligation &p) { - const auto haveCascade = p.getCascades(); + continue; + } + + matchExpectationOrFail( + OM, expectation, + [&](Obligation &O) { + const auto haveCascade = O.getCascades(); + switch (expectation.Info.Kind) { + case Expectation::Kind::Negative: + llvm_unreachable("Should have been handled above!"); + case Expectation::Kind::Member: if (haveCascade != wantsCascade) { diagnose(diags, expectation.MessageRange.begin(), diag::dependency_cascading_mismatch, wantsCascade, haveCascade); - return p.fail(); + return O.fail(); + } else { + return O.fullfill(); } - - return p.fullfill(); - }, - [&](const Expectation &e) { - diagnose( - diags, e.MessageRange.begin(), diag::missing_member_dependency, - static_cast(expectation.Info.Kind), e.MessageRange); - }); - break; - case Expectation::Kind::PotentialMember: - matchExpectationOrFail( - OM, expectation, - [&](Obligation &p) { - assert(p.getName().empty()); - const auto haveCascade = p.getCascades(); + case Expectation::Kind::PotentialMember: + assert(O.getName().empty()); if (haveCascade != wantsCascade) { diagnose(diags, expectation.MessageRange.begin(), diag::potential_dependency_cascading_mismatch, wantsCascade, haveCascade); - return p.fail(); + return O.fail(); + } else { + return O.fullfill(); } - - return p.fullfill(); - }, - [&](const Expectation &e) { - diagnose( - diags, e.MessageRange.begin(), diag::missing_member_dependency, - static_cast(expectation.Info.Kind), e.MessageRange); - }); - break; - case Expectation::Kind::Provides: - matchExpectationOrFail( - OM, expectation, [](Obligation &O) { return O.fullfill(); }, - [&](const Expectation &e) { - diagnose( - diags, e.MessageRange.begin(), diag::missing_member_dependency, - static_cast(expectation.Info.Kind), e.MessageRange); - }); - break; - case Expectation::Kind::DynamicMember: - matchExpectationOrFail( - OM, expectation, [](Obligation &O) { return O.fullfill(); }, - [&](const Expectation &e) { - diagnose( - diags, e.MessageRange.begin(), diag::missing_member_dependency, - static_cast(expectation.Info.Kind), e.MessageRange); - }); - break; - } + case Expectation::Kind::Provides: + case Expectation::Kind::DynamicMember: + return O.fullfill(); + } + + llvm_unreachable("Unhandled expectation kind!"); + }, + [&](const Expectation &e) { + diagnose(diags, e.MessageRange.begin(), + diag::missing_member_dependency, + static_cast(expectation.Info.Kind), e.MessageRange); + }); } return false; diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 7e000a0b6a563..688acbf0b29dd 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -33,6 +33,7 @@ #include "swift/SILOptimizer/Utils/Generics.h" #include "swift/Serialization/SerializationOptions.h" #include "swift/Serialization/SerializedModuleLoader.h" +#include "swift/Serialization/ModuleDependencyScanner.h" #include "swift/Strings.h" #include "swift/Subsystems.h" #include "clang/AST/ASTContext.h" @@ -192,7 +193,9 @@ void CompilerInstance::recordPrimaryInputBuffer(unsigned BufID) { bool CompilerInstance::setUpASTContextIfNeeded() { if (Invocation.getFrontendOptions().RequestedAction == - FrontendOptions::ActionType::CompileModuleFromInterface) { + FrontendOptions::ActionType::CompileModuleFromInterface || + Invocation.getFrontendOptions().RequestedAction == + FrontendOptions::ActionType::TypecheckModuleFromInterface) { // Compiling a module interface from source uses its own CompilerInstance // with options read from the input file. Don't bother setting up an // ASTContext at this level. @@ -520,9 +523,36 @@ bool CompilerInstance::setUpModuleLoaders() { this->DefaultSerializedLoader = ISML.get(); Context->addModuleLoader(std::move(ISML)); } - + Context->addModuleLoader(std::move(clangImporter), /*isClang*/ true); + // When scanning for dependencies, we must add the scanner loaders in order to handle + // ASTContext operations such as canImportModule + if (Invocation.getFrontendOptions().RequestedAction == + FrontendOptions::ActionType::ScanDependencies) { + auto ModuleCachePath = getModuleCachePathFromClang(Context + ->getClangModuleLoader()->getClangInstance()); + auto &FEOpts = Invocation.getFrontendOptions(); + ModuleInterfaceLoaderOptions LoaderOpts(FEOpts); + InterfaceSubContextDelegateImpl ASTDelegate(Context->SourceMgr, Context->Diags, + Context->SearchPathOpts, Context->LangOpts, + LoaderOpts, + Context->getClangModuleLoader(), + /*buildModuleCacheDirIfAbsent*/false, + ModuleCachePath, + FEOpts.PrebuiltModuleCachePath, + FEOpts.SerializeModuleInterfaceDependencyHashes, + FEOpts.shouldTrackSystemDependencies()); + auto mainModuleName = Context->getIdentifier(FEOpts.ModuleName); + std::unique_ptr PSMS = + std::make_unique(*Context, + MLM, + mainModuleName, + Context->SearchPathOpts.PlaceholderDependencyModuleMap, + ASTDelegate); + Context->addModuleLoader(std::move(PSMS)); + } + return false; } @@ -818,7 +848,7 @@ void CompilerInstance::setMainModule(ModuleDecl *newMod) { Context->addLoadedModule(newMod); } -void CompilerInstance::performParseAndResolveImportsOnly() { +bool CompilerInstance::performParseAndResolveImportsOnly() { FrontendStatsTracer tracer(getStatsReporter(), "parse-and-resolve-imports"); // Resolve imports for all the source files. @@ -837,6 +867,7 @@ void CompilerInstance::performParseAndResolveImportsOnly() { mainModule->setHasResolvedImports(); bindExtensions(*mainModule); + return Context->hadError(); } void CompilerInstance::performSema() { diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp index 1e1253ddcb6c5..16fe1877a6d25 100644 --- a/lib/Frontend/FrontendOptions.cpp +++ b/lib/Frontend/FrontendOptions.cpp @@ -51,6 +51,7 @@ bool FrontendOptions::needsProperModuleName(ActionType action) { case ActionType::EmitModuleOnly: case ActionType::MergeModules: case ActionType::CompileModuleFromInterface: + case ActionType::TypecheckModuleFromInterface: return true; case ActionType::Immediate: case ActionType::REPL: @@ -64,6 +65,7 @@ bool FrontendOptions::needsProperModuleName(ActionType action) { case ActionType::DumpTypeInfo: case ActionType::EmitPCM: case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: return true; } llvm_unreachable("Unknown ActionType"); @@ -71,19 +73,104 @@ bool FrontendOptions::needsProperModuleName(ActionType action) { bool FrontendOptions::shouldActionOnlyParse(ActionType action) { switch (action) { - case FrontendOptions::ActionType::Parse: - case FrontendOptions::ActionType::DumpParse: - case FrontendOptions::ActionType::EmitSyntax: - case FrontendOptions::ActionType::DumpInterfaceHash: - case FrontendOptions::ActionType::EmitImportedModules: - case FrontendOptions::ActionType::ScanDependencies: - case FrontendOptions::ActionType::PrintVersion: + case ActionType::Parse: + case ActionType::DumpParse: + case ActionType::EmitSyntax: + case ActionType::DumpInterfaceHash: + case ActionType::EmitImportedModules: + case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: + case ActionType::PrintVersion: return true; default: return false; } } +bool FrontendOptions::doesActionRequireSwiftStandardLibrary(ActionType action) { + switch (action) { + case ActionType::NoneAction: + case ActionType::Parse: + case ActionType::DumpParse: + case ActionType::EmitSyntax: + case ActionType::DumpInterfaceHash: + case ActionType::EmitImportedModules: + case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: + case ActionType::PrintVersion: + case ActionType::EmitPCH: + case ActionType::EmitPCM: + case ActionType::DumpPCM: + case ActionType::CompileModuleFromInterface: + case ActionType::TypecheckModuleFromInterface: + return false; + case ActionType::ResolveImports: + case ActionType::Typecheck: + case ActionType::DumpAST: + case ActionType::PrintAST: + case ActionType::DumpScopeMaps: + case ActionType::DumpTypeRefinementContexts: + case ActionType::EmitSILGen: + case ActionType::EmitSIL: + case ActionType::EmitModuleOnly: + case ActionType::MergeModules: + case ActionType::EmitSIBGen: + case ActionType::EmitSIB: + case ActionType::Immediate: + case ActionType::REPL: + case ActionType::EmitAssembly: + case ActionType::EmitIR: + case ActionType::EmitBC: + case ActionType::EmitObject: + case ActionType::DumpTypeInfo: + assert(!FrontendOptions::shouldActionOnlyParse(action) && + "Parse-only actions should not load modules!"); + return true; + } + llvm_unreachable("Unknown ActionType"); +} + +bool FrontendOptions::doesActionRequireInputs(ActionType action) { + switch (action) { + case ActionType::NoneAction: + case ActionType::PrintVersion: + return false; + case ActionType::REPL: + case ActionType::Parse: + case ActionType::DumpParse: + case ActionType::EmitSyntax: + case ActionType::DumpInterfaceHash: + case ActionType::EmitImportedModules: + case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: + case ActionType::EmitPCH: + case ActionType::EmitPCM: + case ActionType::DumpPCM: + case ActionType::CompileModuleFromInterface: + case ActionType::TypecheckModuleFromInterface: + case ActionType::ResolveImports: + case ActionType::Typecheck: + case ActionType::DumpAST: + case ActionType::PrintAST: + case ActionType::DumpScopeMaps: + case ActionType::DumpTypeRefinementContexts: + case ActionType::EmitSILGen: + case ActionType::EmitSIL: + case ActionType::EmitModuleOnly: + case ActionType::MergeModules: + case ActionType::EmitSIBGen: + case ActionType::EmitSIB: + case ActionType::Immediate: + case ActionType::EmitAssembly: + case ActionType::EmitIR: + case ActionType::EmitBC: + case ActionType::EmitObject: + case ActionType::DumpTypeInfo: + return true; + } + llvm_unreachable("Unknown ActionType"); +} + void FrontendOptions::forAllOutputPaths( const InputFile &input, llvm::function_ref fn) const { if (RequestedAction != FrontendOptions::ActionType::EmitModuleOnly && @@ -118,6 +205,7 @@ FrontendOptions::formatForPrincipalOutputFileForAction(ActionType action) { case ActionType::Parse: case ActionType::ResolveImports: case ActionType::Typecheck: + case ActionType::TypecheckModuleFromInterface: case ActionType::DumpParse: case ActionType::DumpInterfaceHash: case ActionType::DumpAST: @@ -174,6 +262,7 @@ FrontendOptions::formatForPrincipalOutputFileForAction(ActionType action) { return TY_ClangModuleFile; case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: return TY_JSONDependencies; } llvm_unreachable("unhandled action"); @@ -192,6 +281,7 @@ bool FrontendOptions::canActionEmitDependencies(ActionType action) { case ActionType::DumpTypeRefinementContexts: case ActionType::DumpTypeInfo: case ActionType::CompileModuleFromInterface: + case ActionType::TypecheckModuleFromInterface: case ActionType::Immediate: case ActionType::REPL: case ActionType::DumpPCM: @@ -213,6 +303,7 @@ bool FrontendOptions::canActionEmitDependencies(ActionType action) { case ActionType::EmitImportedModules: case ActionType::EmitPCM: case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: return true; } llvm_unreachable("unhandled action"); @@ -232,11 +323,13 @@ bool FrontendOptions::canActionEmitReferenceDependencies(ActionType action) { case ActionType::DumpTypeRefinementContexts: case ActionType::DumpTypeInfo: case ActionType::CompileModuleFromInterface: + case ActionType::TypecheckModuleFromInterface: case ActionType::Immediate: case ActionType::REPL: case ActionType::EmitPCM: case ActionType::DumpPCM: case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: case ActionType::PrintVersion: return false; case ActionType::Typecheck: @@ -280,11 +373,13 @@ bool FrontendOptions::canActionEmitObjCHeader(ActionType action) { case ActionType::DumpTypeRefinementContexts: case ActionType::DumpTypeInfo: case ActionType::CompileModuleFromInterface: + case ActionType::TypecheckModuleFromInterface: case ActionType::Immediate: case ActionType::REPL: case ActionType::EmitPCM: case ActionType::DumpPCM: case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: case ActionType::PrintVersion: return false; case ActionType::Typecheck: @@ -317,11 +412,13 @@ bool FrontendOptions::canActionEmitLoadedModuleTrace(ActionType action) { case ActionType::DumpTypeRefinementContexts: case ActionType::DumpTypeInfo: case ActionType::CompileModuleFromInterface: + case ActionType::TypecheckModuleFromInterface: case ActionType::Immediate: case ActionType::REPL: case ActionType::EmitPCM: case ActionType::DumpPCM: case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: case ActionType::PrintVersion: return false; case ActionType::ResolveImports: @@ -360,11 +457,13 @@ bool FrontendOptions::canActionEmitModule(ActionType action) { case ActionType::DumpTypeInfo: case ActionType::EmitSILGen: case ActionType::CompileModuleFromInterface: + case ActionType::TypecheckModuleFromInterface: case ActionType::Immediate: case ActionType::REPL: case ActionType::EmitPCM: case ActionType::DumpPCM: case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: case ActionType::PrintVersion: return false; case ActionType::MergeModules: @@ -404,11 +503,13 @@ bool FrontendOptions::canActionEmitInterface(ActionType action) { case ActionType::EmitSILGen: case ActionType::EmitSIBGen: case ActionType::CompileModuleFromInterface: + case ActionType::TypecheckModuleFromInterface: case ActionType::Immediate: case ActionType::REPL: case ActionType::EmitPCM: case ActionType::DumpPCM: case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: return false; case ActionType::Typecheck: case ActionType::MergeModules: @@ -450,10 +551,12 @@ bool FrontendOptions::doesActionProduceOutput(ActionType action) { case ActionType::EmitImportedModules: case ActionType::MergeModules: case ActionType::CompileModuleFromInterface: + case ActionType::TypecheckModuleFromInterface: case ActionType::DumpTypeInfo: case ActionType::EmitPCM: case ActionType::DumpPCM: case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: return true; case ActionType::NoneAction: @@ -484,6 +587,7 @@ bool FrontendOptions::doesActionProduceTextualOutput(ActionType action) { case ActionType::Parse: case ActionType::ResolveImports: case ActionType::Typecheck: + case ActionType::TypecheckModuleFromInterface: case ActionType::DumpParse: case ActionType::DumpInterfaceHash: case ActionType::DumpAST: @@ -499,6 +603,7 @@ bool FrontendOptions::doesActionProduceTextualOutput(ActionType action) { case ActionType::DumpTypeInfo: case ActionType::DumpPCM: case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: case ActionType::PrintVersion: return true; } @@ -521,9 +626,11 @@ bool FrontendOptions::doesActionGenerateSIL(ActionType action) { case ActionType::EmitImportedModules: case ActionType::EmitPCH: case ActionType::CompileModuleFromInterface: + case ActionType::TypecheckModuleFromInterface: case ActionType::EmitPCM: case ActionType::DumpPCM: case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: case ActionType::PrintVersion: return false; case ActionType::EmitSILGen: @@ -557,6 +664,7 @@ bool FrontendOptions::doesActionGenerateIR(ActionType action) { case ActionType::DumpTypeRefinementContexts: case ActionType::DumpTypeInfo: case ActionType::CompileModuleFromInterface: + case ActionType::TypecheckModuleFromInterface: case ActionType::Typecheck: case ActionType::ResolveImports: case ActionType::MergeModules: @@ -570,6 +678,7 @@ bool FrontendOptions::doesActionGenerateIR(ActionType action) { case ActionType::EmitPCM: case ActionType::DumpPCM: case ActionType::ScanDependencies: + case ActionType::ScanClangDependencies: case ActionType::PrintVersion: return false; case ActionType::Immediate: diff --git a/lib/Frontend/ModuleInterfaceBuilder.cpp b/lib/Frontend/ModuleInterfaceBuilder.cpp index 4e118f04c0e5a..58ba8c45ef46b 100644 --- a/lib/Frontend/ModuleInterfaceBuilder.cpp +++ b/lib/Frontend/ModuleInterfaceBuilder.cpp @@ -161,10 +161,10 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal( llvm::RestorePrettyStackState(savedInnerPrettyStackState); }; - SubError = subASTDelegate.runInSubCompilerInstance(moduleName, - interfacePath, - OutPath, - diagnosticLoc, + SubError = (bool)subASTDelegate.runInSubCompilerInstance(moduleName, + interfacePath, + OutPath, + diagnosticLoc, [&](SubCompilerInstanceInfo &info) { auto &SubInstance = *info.Instance; auto subInvocation = SubInstance.getInvocation(); @@ -173,9 +173,11 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal( .getModuleInterfaceLoader())->tryEmitForwardingModule(moduleName, interfacePath, CompiledCandidates, OutPath)) { - return false; + return std::error_code(); } FrontendOptions &FEOpts = subInvocation.getFrontendOptions(); + bool isTypeChecking = + (FEOpts.RequestedAction == FrontendOptions::ActionType::Typecheck); const auto &InputInfo = FEOpts.InputsAndOutputs.firstInput(); StringRef InPath = InputInfo.file(); const auto &OutputInfo = @@ -198,9 +200,9 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal( getSwiftInterfaceCompilerVersionForCurrentCompiler( SubInstance.getASTContext()); StringRef emittedByCompiler = info.CompilerVersion; - diagnose(diag::module_interface_build_failed, moduleName, - emittedByCompiler == builtByCompiler, emittedByCompiler, - builtByCompiler); + diagnose(diag::module_interface_build_failed, isTypeChecking, + moduleName, emittedByCompiler == builtByCompiler, + emittedByCompiler, builtByCompiler); } }; @@ -208,7 +210,7 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal( SubInstance.performSema(); if (SubInstance.getASTContext().hadError()) { LLVM_DEBUG(llvm::dbgs() << "encountered errors\n"); - return true; + return std::make_error_code(std::errc::not_supported); } SILOptions &SILOpts = subInvocation.getSILOptions(); @@ -217,7 +219,7 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal( auto SILMod = performASTLowering(Mod, TC, SILOpts); if (!SILMod) { LLVM_DEBUG(llvm::dbgs() << "SILGen did not produce a module\n"); - return true; + return std::make_error_code(std::errc::not_supported); } // Setup the callbacks for serialization, which can occur during the @@ -237,11 +239,14 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal( SmallVector Deps; bool serializeHashes = FEOpts.SerializeModuleInterfaceDependencyHashes; if (collectDepsForSerialization(SubInstance, Deps, serializeHashes)) { - return true; + return std::make_error_code(std::errc::not_supported); } if (ShouldSerializeDeps) SerializationOpts.Dependencies = Deps; SILMod->setSerializeSILAction([&]() { + if (isTypeChecking) + return; + // We don't want to serialize module docs in the cache -- they // will be serialized beside the interface file. serializeToBuffers(Mod, SerializationOpts, ModuleBuffer, @@ -253,9 +258,12 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal( LLVM_DEBUG(llvm::dbgs() << "Running SIL processing passes\n"); if (SubInstance.performSILProcessing(SILMod.get())) { LLVM_DEBUG(llvm::dbgs() << "encountered errors\n"); - return true; + return std::make_error_code(std::errc::not_supported); + } + if (SubInstance.getDiags().hadAnyError()) { + return std::make_error_code(std::errc::not_supported); } - return SubInstance.getDiags().hadAnyError(); + return std::error_code(); }); }); return !RunSuccess || SubError; diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index fed69f9a43f13..2029ff1de9dc1 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -950,7 +950,8 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory( SmallVectorImpl *ModuleInterfacePath, std::unique_ptr *ModuleBuffer, std::unique_ptr *ModuleDocBuffer, - std::unique_ptr *ModuleSourceInfoBuffer) { + std::unique_ptr *ModuleSourceInfoBuffer, + bool IsFramework) { // If running in OnlySerialized mode, ModuleInterfaceLoader // should not have been constructed at all. @@ -1259,7 +1260,7 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( inheritOptionsForBuildingInterface(searchPathOpts, langOpts); // Configure front-end input. auto &SubFEOpts = genericSubInvocation.getFrontendOptions(); - SubFEOpts.RequestedAction = FrontendOptions::ActionType::EmitModuleOnly; + SubFEOpts.RequestedAction = LoaderOpts.requestedAction; if (!moduleCachePath.empty()) { genericSubInvocation.setClangModuleCachePath(moduleCachePath); } @@ -1392,11 +1393,12 @@ InterfaceSubContextDelegateImpl::getCacheHash(StringRef useInterfacePath) { return llvm::APInt(64, H).toString(36, /*Signed=*/false); } -bool InterfaceSubContextDelegateImpl::runInSubContext(StringRef moduleName, - StringRef interfacePath, - StringRef outputPath, - SourceLoc diagLoc, - llvm::function_ref, +std::error_code +InterfaceSubContextDelegateImpl::runInSubContext(StringRef moduleName, + StringRef interfacePath, + StringRef outputPath, + SourceLoc diagLoc, + llvm::function_ref, ArrayRef, StringRef)> action) { return runInSubCompilerInstance(moduleName, interfacePath, outputPath, diagLoc, [&](SubCompilerInstanceInfo &info){ @@ -1408,11 +1410,12 @@ bool InterfaceSubContextDelegateImpl::runInSubContext(StringRef moduleName, }); } -bool InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName, - StringRef interfacePath, - StringRef outputPath, - SourceLoc diagLoc, - llvm::function_ref action) { +std::error_code +InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName, + StringRef interfacePath, + StringRef outputPath, + SourceLoc diagLoc, + llvm::function_ref action) { // We are about to mess up the compiler invocation by using the compiler // arguments in the textual interface file. So copy to use a new compiler // invocation. @@ -1442,7 +1445,10 @@ bool InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleN std::vector outputFiles{"/"}; std::vector ModuleOutputPaths; ModuleOutputPaths.emplace_back(); - ModuleOutputPaths.back().ModuleOutputPath = outputPath.str(); + if (subInvocation.getFrontendOptions().RequestedAction == + FrontendOptions::ActionType::EmitModuleOnly) { + ModuleOutputPaths.back().ModuleOutputPath = outputPath.str(); + } assert(subInvocation.getFrontendOptions().InputsAndOutputs.isWholeModule()); subInvocation.getFrontendOptions().InputsAndOutputs .setMainAndSupplementaryOutputs(outputFiles, ModuleOutputPaths); @@ -1456,12 +1462,12 @@ bool InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleN CompilerVersion, interfacePath, diagLoc)) { - return true; + return std::make_error_code(std::errc::not_supported); } // Insert arguments collected from the interface file. BuildArgs.insert(BuildArgs.end(), SubArgs.begin(), SubArgs.end()); if (subInvocation.parseArgs(SubArgs, Diags)) { - return true; + return std::make_error_code(std::errc::not_supported); } CompilerInstance subInstance; SubCompilerInstanceInfo info; @@ -1473,7 +1479,7 @@ bool InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleN ForwardingDiagnosticConsumer FDC(Diags); subInstance.addDiagnosticConsumer(&FDC); if (subInstance.setup(subInvocation)) { - return true; + return std::make_error_code(std::errc::not_supported); } info.BuildArguments = BuildArgs; info.Hash = CacheHash; @@ -1521,28 +1527,30 @@ ExplicitSwiftModuleLoader::ExplicitSwiftModuleLoader( ExplicitSwiftModuleLoader::~ExplicitSwiftModuleLoader() { delete &Impl; } -std::error_code ExplicitSwiftModuleLoader::findModuleFilesInDirectory( - AccessPathElem ModuleID, - const SerializedModuleBaseName &BaseName, - SmallVectorImpl *ModuleInterfacePath, - std::unique_ptr *ModuleBuffer, - std::unique_ptr *ModuleDocBuffer, - std::unique_ptr *ModuleSourceInfoBuffer) { +bool ExplicitSwiftModuleLoader::findModule(AccessPathElem ModuleID, + SmallVectorImpl *ModuleInterfacePath, + std::unique_ptr *ModuleBuffer, + std::unique_ptr *ModuleDocBuffer, + std::unique_ptr *ModuleSourceInfoBuffer, + bool &IsFramework, bool &IsSystemModule) { StringRef moduleName = ModuleID.Item.str(); auto it = Impl.ExplicitModuleMap.find(moduleName); // If no explicit module path is given matches the name, return with an // error code. if (it == Impl.ExplicitModuleMap.end()) { - return std::make_error_code(std::errc::not_supported); + return false; } auto &moduleInfo = it->getValue(); if (moduleInfo.moduleBuffer) { // We found an explicit module matches the given name, give the buffer // back to the caller side. *ModuleBuffer = std::move(moduleInfo.moduleBuffer); - return std::error_code(); + return true; } + // Set IsFramework bit according to the moduleInfo + IsFramework = moduleInfo.isFramework; + auto &fs = *Ctx.SourceMgr.getFileSystem(); // Open .swiftmodule file auto moduleBuf = fs.getBufferForFile(moduleInfo.modulePath); @@ -1550,7 +1558,7 @@ std::error_code ExplicitSwiftModuleLoader::findModuleFilesInDirectory( // We cannot read the module content, diagnose. Ctx.Diags.diagnose(SourceLoc(), diag::error_opening_explicit_module_file, moduleInfo.modulePath); - return moduleBuf.getError(); + return false; } assert(moduleBuf); @@ -1566,13 +1574,13 @@ std::error_code ExplicitSwiftModuleLoader::findModuleFilesInDirectory( // We cannot read the module content, diagnose. Ctx.Diags.diagnose(SourceLoc(), diag::error_opening_explicit_module_file, moduleInfo.modulePath); - return moduleBuf.getError(); + return false; } } else { // We cannot read the module content, diagnose. Ctx.Diags.diagnose(SourceLoc(), diag::error_opening_explicit_module_file, moduleInfo.modulePath); - return forwardingModule.getError(); + return false; } } assert(moduleBuf); @@ -1591,7 +1599,19 @@ std::error_code ExplicitSwiftModuleLoader::findModuleFilesInDirectory( if (moduleSourceInfoBuf) *ModuleSourceInfoBuffer = std::move(moduleSourceInfoBuf.get()); } - return std::error_code(); + return true; +} + +std::error_code ExplicitSwiftModuleLoader::findModuleFilesInDirectory( + AccessPathElem ModuleID, + const SerializedModuleBaseName &BaseName, + SmallVectorImpl *ModuleInterfacePath, + std::unique_ptr *ModuleBuffer, + std::unique_ptr *ModuleDocBuffer, + std::unique_ptr *ModuleSourceInfoBuffer, + bool IsFramework) { + llvm_unreachable("Not supported in the Explicit Swift Module Loader."); + return std::make_error_code(std::errc::not_supported); } bool ExplicitSwiftModuleLoader::canImportModule( diff --git a/lib/Frontend/ModuleInterfaceSupport.cpp b/lib/Frontend/ModuleInterfaceSupport.cpp index 65e094af7ccc8..21150755bdf2c 100644 --- a/lib/Frontend/ModuleInterfaceSupport.cpp +++ b/lib/Frontend/ModuleInterfaceSupport.cpp @@ -551,5 +551,8 @@ bool swift::emitSwiftInterface(raw_ostream &out, if (needDummyProtocolDeclaration) InheritedProtocolCollector::printDummyProtocolDeclaration(out); + if (Opts.DebugPrintInvalidSyntax) + out << "#__debug_emit_invalid_swiftinterface_syntax__\n"; + return false; } diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 37c2f1bf41190..f4b42016d7d46 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -35,6 +35,7 @@ #include "swift/AST/IRGenRequests.h" #include "swift/AST/NameLookup.h" #include "swift/AST/ASTMangler.h" +#include "swift/AST/TBDGenRequests.h" #include "swift/AST/TypeRefinementContext.h" #include "swift/Basic/Dwarf.h" #include "swift/Basic/Edit.h" @@ -342,6 +343,31 @@ class ABIDependencyEvaluator { void reexposeImportedABI(ModuleDecl *module, ModuleDecl *importedModule, bool includeImportedModule = true); + /// Check if a Swift module is an overlay for some Clang module. + /// + /// FIXME: Delete this hack once SR-13363 is fixed and ModuleDecl has the + /// right API which we can use directly. + bool isOverlayOfClangModule(ModuleDecl *swiftModule); + + /// Check for cases where we have a fake cycle through an overlay. + /// + /// \code + /// Actual stack: + /// sandwichedModule -> Overlay (Swift) -> ... -> sandwichedModule + /// ^^--- wrong! + /// Ideal stack: + /// sandwichedModule -> Underlying (Clang) + /// \endcode + /// + /// This happens when we have a dependency like: + /// \code + /// Overlay (Swift) -> sandwichedModule -> Underlying (Clang) + /// \endcode + /// + /// We check this lazily because eagerly detecting if the dependency on an + /// overlay is correct or not is difficult. + bool isFakeCycleThroughOverlay(ModuleDecl **sandwichedModuleIter); + /// Recursive step in computing ABI dependencies. /// /// Use this method instead of using the \c forClangModule/\c forSwiftModule @@ -453,9 +479,42 @@ void ABIDependencyEvaluator::reexposeImportedABI( addToABIExportMap(module, reexportedModule); } +bool ABIDependencyEvaluator::isOverlayOfClangModule(ModuleDecl *swiftModule) { + assert(!swiftModule->isNonSwiftModule()); + + llvm::SmallPtrSet importList; + ::getImmediateImports(swiftModule, importList, + {ModuleDecl::ImportFilterKind::Public}); + bool isOverlay = + llvm::any_of(importList, [&](ModuleDecl *importedModule) -> bool { + return isClangOverlayOf(swiftModule, importedModule); + }); + return isOverlay; +} + +bool ABIDependencyEvaluator::isFakeCycleThroughOverlay( + ModuleDecl **sandwichModuleIter) { + assert(sandwichModuleIter >= searchStack.begin() + && sandwichModuleIter < searchStack.end() + && "sandwichModuleIter points to an element in searchStack"); + // The sandwichedModule must be a Clang module. + if (!(*sandwichModuleIter)->isNonSwiftModule()) + return false; + auto nextModuleIter = sandwichModuleIter + 1; + if (nextModuleIter == searchStack.end()) + return false; + // The next module must be a Swift overlay for a Clang module + if ((*nextModuleIter)->isNonSwiftModule()) + return false; + return isOverlayOfClangModule(*nextModuleIter); +} + void ABIDependencyEvaluator::computeABIDependenciesForModule( ModuleDecl *module) { - if (llvm::find(searchStack, module) != searchStack.end()) { + auto moduleIter = llvm::find(searchStack, module); + if (moduleIter != searchStack.end()) { + if (isFakeCycleThroughOverlay(moduleIter)) + return; crashOnInvariantViolation([&](llvm::raw_string_ostream &os) { os << "unexpected cycle in import graph!\n"; for (auto m: searchStack) { @@ -510,6 +569,10 @@ void ABIDependencyEvaluator::computeABIDependenciesForClangModule( // C' imports S. This creates a cycle: S -> C' -> ... -> S. // In practice, this case is hit for // Darwin (Swift) -> SwiftOverlayShims (Clang) -> Darwin (Swift). + // We may also hit this in a slightly different direction, in case + // the module directly imports SwiftOverlayShims: + // SwiftOverlayShims -> Darwin (Swift) -> SwiftOverlayShims + // The latter is handled later by isFakeCycleThroughOverlay. // 3. [NOTE: Intra-module-leafwards-traversal] // Cycles within the same top-level module. // These don't matter for us, since we only care about the dependency @@ -519,15 +582,15 @@ void ABIDependencyEvaluator::computeABIDependenciesForClangModule( if (import->isStdlibModule()) { continue; } - if (!import->isNonSwiftModule() - && import->findUnderlyingClangModule() != nullptr - && llvm::find(searchStack, import) != searchStack.end()) { + if (!import->isNonSwiftModule() && isOverlayOfClangModule(import) && + llvm::find(searchStack, import) != searchStack.end()) { continue; } if (import->isNonSwiftModule() && module->getTopLevelModule() == import->getTopLevelModule() - && !import->findUnderlyingClangModule() - ->isSubModuleOf(module->findUnderlyingClangModule())) { + && (module == import + || !import->findUnderlyingClangModule() + ->isSubModuleOf(module->findUnderlyingClangModule()))) { continue; } computeABIDependenciesForModule(import); @@ -1166,7 +1229,7 @@ static void verifyGenericSignaturesIfNeeded(const CompilerInvocation &Invocation GenericSignatureBuilder::verifyGenericSignaturesInModule(module); } -static void dumpAndPrintScopeMap(const CompilerInstance &Instance, +static bool dumpAndPrintScopeMap(const CompilerInstance &Instance, SourceFile *SF) { // Not const because may require reexpansion ASTScope &scope = SF->getScope(); @@ -1176,13 +1239,14 @@ static void dumpAndPrintScopeMap(const CompilerInstance &Instance, llvm::errs() << "***Complete scope map***\n"; scope.buildFullyExpandedTree(); scope.print(llvm::errs()); - return; + return Instance.getASTContext().hadError(); } // Probe each of the locations, and dump what we find. for (auto lineColumn : opts.DumpScopeMapLocations) { scope.buildFullyExpandedTree(); scope.dumpOneScopeMapLocation(lineColumn); } + return Instance.getASTContext().hadError(); } static SourceFile * @@ -1197,7 +1261,7 @@ getPrimaryOrMainSourceFile(const CompilerInstance &Instance) { /// Dumps the AST of all available primary source files. If corresponding output /// files were specified, use them; otherwise, dump the AST to stdout. -static void dumpAST(CompilerInstance &Instance) { +static bool dumpAST(CompilerInstance &Instance) { auto primaryFiles = Instance.getPrimarySourceFiles(); if (!primaryFiles.empty()) { for (SourceFile *sourceFile: primaryFiles) { @@ -1212,55 +1276,7 @@ static void dumpAST(CompilerInstance &Instance) { auto *SF = getPrimaryOrMainSourceFile(Instance); SF->dump(llvm::outs(), /*parseIfNeeded*/ true); } -} - -/// We may have been told to dump the AST (either after parsing or -/// type-checking, which is already differentiated in -/// CompilerInstance::performSema()), so dump or print the main source file and -/// return. - -static Optional dumpASTIfNeeded(CompilerInstance &Instance) { - const auto &opts = Instance.getInvocation().getFrontendOptions(); - const FrontendOptions::ActionType Action = opts.RequestedAction; - ASTContext &Context = Instance.getASTContext(); - switch (Action) { - default: - return None; - - case FrontendOptions::ActionType::PrintAST: - getPrimaryOrMainSourceFile(Instance) - ->print(llvm::outs(), PrintOptions::printEverything()); - break; - - case FrontendOptions::ActionType::DumpScopeMaps: - dumpAndPrintScopeMap(Instance, getPrimaryOrMainSourceFile(Instance)); - break; - - case FrontendOptions::ActionType::DumpTypeRefinementContexts: - getPrimaryOrMainSourceFile(Instance) - ->getTypeRefinementContext() - ->dump(llvm::errs(), Context.SourceMgr); - break; - - case FrontendOptions::ActionType::DumpInterfaceHash: - getPrimaryOrMainSourceFile(Instance)->dumpInterfaceHash(llvm::errs()); - break; - - case FrontendOptions::ActionType::EmitSyntax: - emitSyntax(getPrimaryOrMainSourceFile(Instance), - opts.InputsAndOutputs.getSingleOutputFilename()); - break; - - case FrontendOptions::ActionType::DumpParse: - case FrontendOptions::ActionType::DumpAST: - dumpAST(Instance); - break; - - case FrontendOptions::ActionType::EmitImportedModules: - emitImportedModules(Context, Instance.getMainModule(), opts); - break; - } - return Context.hadError(); + return Instance.getASTContext().hadError(); } static void emitReferenceDependenciesForAllPrimaryInputsIfNeeded( @@ -1637,6 +1653,7 @@ static void performEndOfPipelineActions(CompilerInstance &Instance) { // it's -emit-imported-modules, which can load modules. auto action = opts.RequestedAction; if (FrontendOptions::shouldActionOnlyParse(action) && + !ctx.getLoadedModules().empty() && action != FrontendOptions::ActionType::EmitImportedModules) { assert(ctx.getNumLoadedModules() == 1 && "Loaded a module during parse-only"); @@ -1673,9 +1690,15 @@ static void performEndOfPipelineActions(CompilerInstance &Instance) { } } - // Emit dependencies and index data. + // FIXME: This predicate matches the status quo, but there's no reason + // indexing cannot run for actions that do not require stdlib e.g. to better + // facilitate tests. + if (FrontendOptions::doesActionRequireSwiftStandardLibrary(action)) { + emitIndexData(Instance); + } + + // Emit dependencies. emitReferenceDependenciesForAllPrimaryInputsIfNeeded(Instance); - emitIndexData(Instance); emitMakeDependenciesIfNeeded(Instance.getDiags(), Instance.getDependencyTracker(), opts); @@ -1684,37 +1707,190 @@ static void performEndOfPipelineActions(CompilerInstance &Instance) { emitCompiledSourceForAllPrimaryInputsIfNeeded(Instance); } +static bool printSwiftVersion(const CompilerInvocation &Invocation) { + llvm::outs() << version::getSwiftFullVersion( + version::Version::getCurrentLanguageVersion()) + << '\n'; + llvm::outs() << "Target: " << Invocation.getLangOptions().Target.str() + << '\n'; + return false; +} + +static bool +withSemanticAnalysis(CompilerInstance &Instance, FrontendObserver *observer, + llvm::function_ref cont) { + const auto &Invocation = Instance.getInvocation(); + const auto &opts = Invocation.getFrontendOptions(); + assert(!FrontendOptions::shouldActionOnlyParse(opts.RequestedAction) && + "Action may only parse, but has requested semantic analysis!"); + + Instance.performSema(); + if (observer) + observer->performedSemanticAnalysis(Instance); + + switch (opts.CrashMode) { + case FrontendOptions::DebugCrashMode::AssertAfterParse: + debugFailWithAssertion(); + return true; + case FrontendOptions::DebugCrashMode::CrashAfterParse: + debugFailWithCrash(); + return true; + case FrontendOptions::DebugCrashMode::None: + break; + } + + (void)migrator::updateCodeAndEmitRemapIfNeeded(&Instance); + + if (Instance.getASTContext().hadError()) + return true; + + return cont(Instance); +} + +static bool performScanDependencies(CompilerInstance &Instance) { + auto batchScanInput = + Instance.getASTContext().SearchPathOpts.BatchScanInputFilePath; + if (batchScanInput.empty()) { + return scanDependencies(Instance); + } else { + return batchScanModuleDependencies(Instance, batchScanInput); + } +} + +static bool performParseOnly(ModuleDecl &MainModule) { + // A -parse invocation only cares about the side effects of parsing, so + // force the parsing of all the source files. + for (auto *file : MainModule.getFiles()) { + if (auto *SF = dyn_cast(file)) + (void)SF->getTopLevelDecls(); + } + return MainModule.getASTContext().hadError(); +} + +static bool performAction(CompilerInstance &Instance, + int &ReturnValue, + FrontendObserver *observer) { + const auto &opts = Instance.getInvocation().getFrontendOptions(); + auto &Context = Instance.getASTContext(); + switch (Instance.getInvocation().getFrontendOptions().RequestedAction) { + // MARK: Trivial Actions + case FrontendOptions::ActionType::NoneAction: + return Context.hadError(); + case FrontendOptions::ActionType::PrintVersion: + return printSwiftVersion(Instance.getInvocation()); + case FrontendOptions::ActionType::REPL: + llvm::report_fatal_error("Compiler-internal integrated REPL has been " + "removed; use the LLDB-enhanced REPL instead."); + + // MARK: Actions for Clang and Clang Modules + // We've been asked to precompile a bridging header or module; we want to + // avoid touching any other inputs and just parse, emit and exit. + case FrontendOptions::ActionType::EmitPCH: + return precompileBridgingHeader(Instance); + case FrontendOptions::ActionType::EmitPCM: + return precompileClangModule(Instance); + case FrontendOptions::ActionType::DumpPCM: + return dumpPrecompiledClangModule(Instance); + + // MARK: Module Interface Actions + case FrontendOptions::ActionType::CompileModuleFromInterface: + case FrontendOptions::ActionType::TypecheckModuleFromInterface: + return buildModuleFromInterface(Instance); + + // MARK: Actions that Dump + case FrontendOptions::ActionType::DumpParse: + return dumpAST(Instance); + case FrontendOptions::ActionType::DumpAST: { + // FIXME: -dump-ast expects to be able to write output even if type checking + // fails which does not cleanly fit the model \c withSemanticAnalysis is + // trying to impose. Once there is a request for the "semantic AST", this + // point is moot. + Instance.performSema(); + return dumpAST(Instance); + } + case FrontendOptions::ActionType::PrintAST: + return withSemanticAnalysis( + Instance, observer, [](CompilerInstance &Instance) { + getPrimaryOrMainSourceFile(Instance)->print( + llvm::outs(), PrintOptions::printEverything()); + return Instance.getASTContext().hadError(); + }); + case FrontendOptions::ActionType::DumpScopeMaps: + return withSemanticAnalysis( + Instance, observer, [](CompilerInstance &Instance) { + return dumpAndPrintScopeMap(Instance, + getPrimaryOrMainSourceFile(Instance)); + }); + case FrontendOptions::ActionType::DumpTypeRefinementContexts: + return withSemanticAnalysis( + Instance, observer, [](CompilerInstance &Instance) { + getPrimaryOrMainSourceFile(Instance) + ->getTypeRefinementContext() + ->dump(llvm::errs(), Instance.getASTContext().SourceMgr); + return Instance.getASTContext().hadError(); + }); + case FrontendOptions::ActionType::DumpInterfaceHash: + getPrimaryOrMainSourceFile(Instance)->dumpInterfaceHash(llvm::errs()); + return Context.hadError(); + case FrontendOptions::ActionType::EmitSyntax: + return emitSyntax(getPrimaryOrMainSourceFile(Instance), + opts.InputsAndOutputs.getSingleOutputFilename()); + case FrontendOptions::ActionType::EmitImportedModules: + return emitImportedModules(Instance.getMainModule(), opts); + + // MARK: Dependency Scanning Actions + case FrontendOptions::ActionType::ScanDependencies: + return performScanDependencies(Instance); + case FrontendOptions::ActionType::ScanClangDependencies: + return scanClangDependencies(Instance); + + // MARK: General Compilation Actions + case FrontendOptions::ActionType::Parse: + return performParseOnly(*Instance.getMainModule()); + case FrontendOptions::ActionType::ResolveImports: + return Instance.performParseAndResolveImportsOnly(); + case FrontendOptions::ActionType::Typecheck: + return withSemanticAnalysis(Instance, observer, + [](CompilerInstance &Instance) { + return Instance.getASTContext().hadError(); + }); + case FrontendOptions::ActionType::EmitSILGen: + case FrontendOptions::ActionType::EmitSIBGen: + case FrontendOptions::ActionType::EmitSIL: + case FrontendOptions::ActionType::EmitSIB: + case FrontendOptions::ActionType::EmitModuleOnly: + case FrontendOptions::ActionType::MergeModules: + case FrontendOptions::ActionType::Immediate: + case FrontendOptions::ActionType::EmitAssembly: + case FrontendOptions::ActionType::EmitIR: + case FrontendOptions::ActionType::EmitBC: + case FrontendOptions::ActionType::EmitObject: + case FrontendOptions::ActionType::DumpTypeInfo: + return withSemanticAnalysis( + Instance, observer, [&](CompilerInstance &Instance) { + assert(FrontendOptions::doesActionGenerateSIL(opts.RequestedAction) && + "All actions not requiring SILGen must have been handled!"); + return performCompileStepsPostSema(Instance, ReturnValue, observer); + }); + } + + assert(false && "Unhandled case in performCompile!"); + return Context.hadError(); +} + /// Performs the compile requested by the user. /// \param Instance Will be reset after performIRGeneration when the verifier /// mode is NoVerify and there were no errors. /// \returns true on error static bool performCompile(CompilerInstance &Instance, - ArrayRef Args, int &ReturnValue, FrontendObserver *observer) { const auto &Invocation = Instance.getInvocation(); const auto &opts = Invocation.getFrontendOptions(); const FrontendOptions::ActionType Action = opts.RequestedAction; - // We've been asked to precompile a bridging header or module; we want to - // avoid touching any other inputs and just parse, emit and exit. - if (Action == FrontendOptions::ActionType::EmitPCH) - return precompileBridgingHeader(Instance); - if (Action == FrontendOptions::ActionType::EmitPCM) - return precompileClangModule(Instance); - if (Action == FrontendOptions::ActionType::DumpPCM) - return dumpPrecompiledClangModule(Instance); - if (Action == FrontendOptions::ActionType::PrintVersion) { - llvm::outs() << version::getSwiftFullVersion( - version::Version::getCurrentLanguageVersion()) << '\n'; - llvm::outs() << "Target: " - << Invocation.getLangOptions().Target.str() << '\n'; - return false; - } - if (Action == FrontendOptions::ActionType::CompileModuleFromInterface) - return buildModuleFromInterface(Instance); - - if (Invocation.getInputKind() == InputFileKind::LLVM) + // To compile LLVM IR, just pass it off unmodified. + if (Instance.getInvocation().getInputKind() == InputFileKind::LLVM) return compileLLVMIR(Instance); // If we aren't in a parse-only context and expect an implicit stdlib import, @@ -1723,90 +1899,33 @@ static bool performCompile(CompilerInstance &Instance, // trigger a bunch of other errors due to the stdlib being missing, or at // worst crash downstream as many call sites don't currently handle a missing // stdlib. - if (!FrontendOptions::shouldActionOnlyParse(Action)) { + if (FrontendOptions::doesActionRequireSwiftStandardLibrary(Action)) { if (Instance.loadStdlibIfNeeded()) return true; } - bool didFinishPipeline = false; - SWIFT_DEFER { - assert(didFinishPipeline && "Returned without calling finishPipeline"); - }; - - auto finishPipeline = [&](bool hadError) -> bool { - // We might have freed the ASTContext already, but in that case we would - // have already performed these actions. - if (Instance.hasASTContext()) { - performEndOfPipelineActions(Instance); - hadError |= Instance.getASTContext().hadError(); - } - didFinishPipeline = true; - return hadError; - }; - - auto &Context = Instance.getASTContext(); - if (FrontendOptions::shouldActionOnlyParse(Action)) { - // Parsing gets triggered lazily, but let's make sure we have the right - // input kind. - auto kind = Invocation.getInputKind(); - assert((kind == InputFileKind::Swift || - kind == InputFileKind::SwiftLibrary || - kind == InputFileKind::SwiftModuleInterface) && - "Only supports parsing .swift files"); - (void)kind; - } else if (Action == FrontendOptions::ActionType::ResolveImports) { - Instance.performParseAndResolveImportsOnly(); - return finishPipeline(Context.hadError()); - } else { - Instance.performSema(); - } - - if (Action == FrontendOptions::ActionType::Parse) { - // A -parse invocation only cares about the side effects of parsing, so - // force the parsing of all the source files. - for (auto *file : Instance.getMainModule()->getFiles()) { - if (auto *SF = dyn_cast(file)) - (void)SF->getTopLevelDecls(); + assert([&]() -> bool { + if (FrontendOptions::shouldActionOnlyParse(Action)) { + // Parsing gets triggered lazily, but let's make sure we have the right + // input kind. + auto kind = Invocation.getInputKind(); + return kind == InputFileKind::Swift || + kind == InputFileKind::SwiftLibrary || + kind == InputFileKind::SwiftModuleInterface; } - return finishPipeline(Context.hadError()); - } - - if (Action == FrontendOptions::ActionType::ScanDependencies) - return finishPipeline(scanDependencies(Instance)); + return true; + }() && "Only supports parsing .swift files"); - if (observer) - observer->performedSemanticAnalysis(Instance); + bool hadError = performAction(Instance, ReturnValue, observer); - { - FrontendOptions::DebugCrashMode CrashMode = opts.CrashMode; - if (CrashMode == FrontendOptions::DebugCrashMode::AssertAfterParse) - debugFailWithAssertion(); - else if (CrashMode == FrontendOptions::DebugCrashMode::CrashAfterParse) - debugFailWithCrash(); + // We might have freed the ASTContext already, but in that case we would + // have already performed these actions. + if (Instance.hasASTContext() && + FrontendOptions::doesActionRequireInputs(Action)) { + performEndOfPipelineActions(Instance); + hadError |= Instance.getASTContext().hadError(); } - - (void)migrator::updateCodeAndEmitRemapIfNeeded(&Instance); - - if (Action == FrontendOptions::ActionType::REPL) { - llvm::report_fatal_error("Compiler-internal integrated REPL has been " - "removed; use the LLDB-enhanced REPL instead."); - } - - if (auto r = dumpASTIfNeeded(Instance)) - return finishPipeline(*r); - - if (Context.hadError()) - return finishPipeline(/*hadError*/ true); - - // We've just been told to perform a typecheck, so we can return now. - if (Action == FrontendOptions::ActionType::Typecheck) - return finishPipeline(/*hadError*/ false); - - assert(FrontendOptions::doesActionGenerateSIL(Action) && - "All actions not requiring SILGen must have been handled!"); - - return finishPipeline( - performCompileStepsPostSema(Instance, ReturnValue, observer)); + return hadError; } static bool serializeSIB(SILModule *SM, const PrimarySpecificPaths &PSPs, @@ -2580,7 +2699,7 @@ int swift::performFrontend(ArrayRef Args, } int ReturnValue = 0; - bool HadError = performCompile(*Instance, Args, ReturnValue, observer); + bool HadError = performCompile(*Instance, ReturnValue, observer); if (verifierEnabled) { DiagnosticEngine &diags = Instance->getDiags(); diff --git a/lib/FrontendTool/ImportedModules.cpp b/lib/FrontendTool/ImportedModules.cpp index 90a33895ee52a..d750417737264 100644 --- a/lib/FrontendTool/ImportedModules.cpp +++ b/lib/FrontendTool/ImportedModules.cpp @@ -42,9 +42,9 @@ static void findAllClangImports(const clang::Module *module, } } -bool swift::emitImportedModules(ASTContext &Context, ModuleDecl *mainModule, +bool swift::emitImportedModules(ModuleDecl *mainModule, const FrontendOptions &opts) { - + auto &Context = mainModule->getASTContext(); std::string path = opts.InputsAndOutputs.getSingleOutputFilename(); std::error_code EC; llvm::raw_fd_ostream out(path, EC, llvm::sys::fs::F_None); diff --git a/lib/FrontendTool/ImportedModules.h b/lib/FrontendTool/ImportedModules.h index 42b4e76babaf4..510fa4ccdedde 100644 --- a/lib/FrontendTool/ImportedModules.h +++ b/lib/FrontendTool/ImportedModules.h @@ -20,8 +20,7 @@ class FrontendOptions; class ModuleDecl; /// Emit the names of the modules imported by \c mainModule. -bool emitImportedModules(ASTContext &Context, ModuleDecl *mainModule, - const FrontendOptions &opts); +bool emitImportedModules(ModuleDecl *mainModule, const FrontendOptions &opts); } // end namespace swift #endif diff --git a/lib/FrontendTool/ScanDependencies.cpp b/lib/FrontendTool/ScanDependencies.cpp index 6a90ae8231c86..34e99395e1b17 100644 --- a/lib/FrontendTool/ScanDependencies.cpp +++ b/lib/FrontendTool/ScanDependencies.cpp @@ -31,13 +31,105 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/StringSaver.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/YAMLParser.h" #include using namespace swift; +using namespace llvm::yaml; namespace { +struct BatchScanInput { + StringRef moduleName; + StringRef arguments; + StringRef outputPath; + bool isSwift; +}; + +static std::string getScalaNodeText(Node *N) { + SmallString<32> Buffer; + return cast(N)->getValue(Buffer).str(); +} + +/// Parse an entry like this, where the "platforms" key-value pair is optional: +/// { +/// "swiftModuleName": "Foo", +/// "arguments": "-target 10.15", +/// "output": "../Foo.json" +/// }, +static bool parseBatchInputEntries(ASTContext &Ctx, llvm::StringSaver &saver, + Node *Node, std::vector &result) { + auto *SN = cast(Node); + if (!SN) + return true; + for (auto It = SN->begin(); It != SN->end(); ++It) { + auto *MN = cast(&*It); + BatchScanInput entry; + Optional> Platforms; + for (auto &Pair: *MN) { + auto Key = getScalaNodeText(Pair.getKey()); + auto* Value = Pair.getValue(); + if (Key == "clangModuleName") { + entry.moduleName = saver.save(getScalaNodeText(Value)); + entry.isSwift = false; + } else if (Key == "swiftModuleName") { + entry.moduleName = saver.save(getScalaNodeText(Value)); + entry.isSwift = true; + } else if (Key == "arguments") { + entry.arguments = saver.save(getScalaNodeText(Value)); + } else if (Key == "output") { + entry.outputPath = saver.save(getScalaNodeText(Value)); + } else { + // Future proof. + continue; + } + } + if (entry.moduleName.empty()) + return true; + if (entry.outputPath.empty()) + return true; + result.emplace_back(std::move(entry)); + } + return false; +} +static Optional> +parseBatchScanInputFile(ASTContext &ctx, StringRef batchInputPath, + llvm::StringSaver &saver) { + assert(!batchInputPath.empty()); + namespace yaml = llvm::yaml; + std::vector result; + + // Load the input file. + llvm::ErrorOr> FileBufOrErr = + llvm::MemoryBuffer::getFile(batchInputPath); + if (!FileBufOrErr) { + ctx.Diags.diagnose(SourceLoc(), diag::batch_scan_input_file_missing, + batchInputPath); + return None; + } + StringRef Buffer = FileBufOrErr->get()->getBuffer(); + + // Use a new source manager instead of the one from ASTContext because we + // don't want the Json file to be persistent. + SourceManager SM; + yaml::Stream Stream(llvm::MemoryBufferRef(Buffer, batchInputPath), + SM.getLLVMSourceMgr()); + for (auto DI = Stream.begin(); DI != Stream.end(); ++ DI) { + assert(DI != Stream.end() && "Failed to read a document"); + yaml::Node *N = DI->getRoot(); + assert(N && "Failed to find a root"); + if (parseBatchInputEntries(ctx, saver, N, result)) { + ctx.Diags.diagnose(SourceLoc(), diag::batch_scan_input_file_corrupted, + batchInputPath); + return None; + } + } + return result; +} } /// Find all of the imported Clang modules starting with the given module name. @@ -216,6 +308,13 @@ namespace { out << "\""; } + /// Write a boolean value as JSON. + void writeJSONValue(llvm::raw_ostream &out, + bool value, + unsigned indentLevel) { + out.write_escaped(value ? "true" : "false"); + } + /// Write a module identifier. void writeJSONValue(llvm::raw_ostream &out, const ModuleDependencyID &module, @@ -397,6 +496,11 @@ static void writeJSON(llvm::raw_ostream &out, swiftDeps->compiledModulePath, 5, /*trailingComma=*/false); } + writeJSONSingleField( + out, "isFramework", + swiftDeps->isFramework, 5, + /*trailingComma=*/!swiftDeps->extraPCMArgs.empty() || + swiftDeps->bridgingHeaderFile.hasValue()); if (!swiftDeps->extraPCMArgs.empty()) { out.indent(5 * 2); out << "\"extraPcmArgs\": [\n"; @@ -521,6 +625,123 @@ static bool diagnoseCycle(CompilerInstance &instance, return false; } +static bool scanModuleDependencies(CompilerInstance &instance, + StringRef moduleName, + bool isClang, + StringRef outputPath) { + ASTContext &ctx = instance.getASTContext(); + auto &FEOpts = instance.getInvocation().getFrontendOptions(); + ModuleInterfaceLoaderOptions LoaderOpts(FEOpts); + auto ModuleCachePath = getModuleCachePathFromClang(ctx + .getClangModuleLoader()->getClangInstance()); + + llvm::SetVector, + std::set> allModules; + // Create the module dependency cache. + ModuleDependenciesCache cache; + InterfaceSubContextDelegateImpl ASTDelegate(ctx.SourceMgr, ctx.Diags, + ctx.SearchPathOpts, ctx.LangOpts, + LoaderOpts, + ctx.getClangModuleLoader(), + /*buildModuleCacheDirIfAbsent*/false, + ModuleCachePath, + FEOpts.PrebuiltModuleCachePath, + FEOpts.SerializeModuleInterfaceDependencyHashes, + FEOpts.shouldTrackSystemDependencies()); + Optional rootDeps; + if (isClang) { + // Loading the clang module using Clang importer. + // This action will populate the cache with the main module's dependencies. + rootDeps = ctx.getModuleDependencies(moduleName, /*IsClang*/true, cache, + ASTDelegate); + } else { + // Loading the swift module's dependencies. + rootDeps = ctx.getSwiftModuleDependencies(moduleName, cache, ASTDelegate); + } + if (!rootDeps.hasValue()) { + // We cannot find the clang module, abort. + return true; + } + // Add the main module. + allModules.insert({moduleName.str(), isClang ? ModuleDependenciesKind::Clang: + ModuleDependenciesKind::Swift}); + + // Explore the dependencies of every module. + for (unsigned currentModuleIdx = 0; + currentModuleIdx < allModules.size(); + ++currentModuleIdx) { + auto module = allModules[currentModuleIdx]; + auto discoveredModules = + resolveDirectDependencies(instance, module, cache, ASTDelegate); + allModules.insert(discoveredModules.begin(), discoveredModules.end()); + } + // Write out the JSON description. + std::error_code EC; + llvm::raw_fd_ostream out(outputPath, EC, llvm::sys::fs::F_None); + writeJSON(out, instance, cache, ASTDelegate, allModules.getArrayRef()); + return false; +} + +bool swift::scanClangDependencies(CompilerInstance &instance) { + return scanModuleDependencies(instance, + instance.getMainModule()->getNameStr(), + /*isClang*/true, + instance.getInvocation().getFrontendOptions() + .InputsAndOutputs.getSingleOutputFilename()); +} + +bool swift::batchScanModuleDependencies(CompilerInstance &instance, + llvm::StringRef batchInputFile) { + const CompilerInvocation &invok = instance.getInvocation(); + + (void)instance.getMainModule(); + llvm::BumpPtrAllocator alloc; + llvm::StringSaver saver(alloc); + auto results = parseBatchScanInputFile(instance.getASTContext(), + batchInputFile, saver); + if (!results.hasValue()) + return true; + auto &diags = instance.getDiags(); + ForwardingDiagnosticConsumer FDC(diags); + // Keep track of all compiler instances we have created. + llvm::StringMap> subInstanceMap; + for (auto &entry: *results) { + CompilerInstance *pInstance = nullptr; + if (entry.arguments.empty()) { + // Use the compiler's instance if no arguments are specified. + pInstance = &instance; + } else if (subInstanceMap.count(entry.arguments)) { + // Use the previously created instance if we've seen the arguments before. + pInstance = subInstanceMap[entry.arguments].get(); + } else { + // Create a new instance by the arguments and save it in the map. + pInstance = subInstanceMap.insert({entry.arguments, + std::make_unique()}).first->getValue().get(); + SmallVector args; + llvm::cl::TokenizeGNUCommandLine(entry.arguments, saver, args); + CompilerInvocation subInvok = invok; + pInstance->addDiagnosticConsumer(&FDC); + if (subInvok.parseArgs(args, diags)) { + instance.getDiags().diagnose(SourceLoc(), diag::scanner_arguments_invalid, + entry.arguments); + return true; + } + if (pInstance->setup(subInvok)) { + instance.getDiags().diagnose(SourceLoc(), diag::scanner_arguments_invalid, + entry.arguments); + return true; + } + } + assert(pInstance); + // Scan using the chosen compiler instance. + if (scanModuleDependencies(*pInstance, entry.moduleName, !entry.isSwift, + entry.outputPath)) { + return true; + } + } + return false; +} + bool swift::scanDependencies(CompilerInstance &instance) { ASTContext &Context = instance.getASTContext(); ModuleDecl *mainModule = instance.getMainModule(); diff --git a/lib/FrontendTool/ScanDependencies.h b/lib/FrontendTool/ScanDependencies.h index ece8515097608..fab7d26bbb190 100644 --- a/lib/FrontendTool/ScanDependencies.h +++ b/lib/FrontendTool/ScanDependencies.h @@ -13,13 +13,24 @@ #ifndef SWIFT_FRONTENDTOOL_SCANDEPENDENCIES_H #define SWIFT_FRONTENDTOOL_SCANDEPENDENCIES_H +#include "llvm/ADT/StringRef.h" + namespace swift { +class CompilerInvocation; class CompilerInstance; +/// Batch scan the dependencies for modules specified in \c batchInputFile. +bool batchScanModuleDependencies(CompilerInstance &instance, + llvm::StringRef batchInputFile); + /// Scans the dependencies of the main module of \c instance. bool scanDependencies(CompilerInstance &instance); +/// Scans the dependencies of the underlying clang module of the main module +/// of \c instance. +bool scanClangDependencies(CompilerInstance &instance); + } // end namespace swift #endif diff --git a/lib/FrontendTool/TBD.cpp b/lib/FrontendTool/TBD.cpp index 77a27a2152e87..f64d86ee13c38 100644 --- a/lib/FrontendTool/TBD.cpp +++ b/lib/FrontendTool/TBD.cpp @@ -17,6 +17,7 @@ #include "swift/AST/DiagnosticsFrontend.h" #include "swift/AST/FileUnit.h" #include "swift/AST/Module.h" +#include "swift/AST/TBDGenRequests.h" #include "swift/Basic/LLVM.h" #include "swift/Demangling/Demangle.h" #include "swift/Frontend/FrontendOptions.h" diff --git a/lib/IDE/CMakeLists.txt b/lib/IDE/CMakeLists.txt index 7348c057ef63a..d028e874d39b7 100644 --- a/lib/IDE/CMakeLists.txt +++ b/lib/IDE/CMakeLists.txt @@ -7,6 +7,7 @@ add_swift_host_library(swiftIDE STATIC ConformingMethodList.cpp ExprContextAnalysis.cpp Formatting.cpp + FuzzyStringMatcher.cpp Refactoring.cpp ModuleInterfacePrinting.cpp REPLCodeCompletion.cpp @@ -21,6 +22,7 @@ add_swift_host_library(swiftIDE STATIC target_link_libraries(swiftIDE PRIVATE swiftAST swiftClangImporter + swiftDriver swiftFrontend swiftIndex swiftParse diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index d3eb0b21c6d14..bd5c98c9a4e20 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -2387,7 +2387,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { // i.e. cases where 'ExprType' != 'keyPathInfo.baseType'. auto *SD = keyPathInfo.subscript; - auto elementTy = SD->getElementTypeLoc().getType(); + const auto elementTy = SD->getElementInterfaceType(); if (!elementTy->hasTypeParameter()) return elementTy; @@ -4284,14 +4284,18 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { if (!T->mayHaveMembers()) return; - DeclContext *DC = const_cast(CurrDeclContext); - // We can only say .foo where foo is a static member of the contextual // type and has the same type (or if the member is a function, then the // same result type) as the contextual type. FilteredDeclConsumer consumer(*this, [=](ValueDecl *VD, DeclVisibilityKind Reason) { - return isReferenceableByImplicitMemberExpr(CurrModule, DC, T, VD); + if (T->getOptionalObjectType() && + VD->getModuleContext()->isStdlibModule()) { + // In optional context, ignore '.init()', 'init(nilLiteral:)', + if (isa(VD)) + return false; + } + return true; }); auto baseType = MetatypeType::get(T); diff --git a/lib/IDE/CodeCompletionResultPrinter.cpp b/lib/IDE/CodeCompletionResultPrinter.cpp index e5c9986ab1fde..7b61aa1835153 100644 --- a/lib/IDE/CodeCompletionResultPrinter.cpp +++ b/lib/IDE/CodeCompletionResultPrinter.cpp @@ -10,8 +10,9 @@ // //===----------------------------------------------------------------------===// -#include "swift/Basic/LLVM.h" #include "swift/IDE/CodeCompletionResultPrinter.h" +#include "swift/AST/ASTPrinter.h" +#include "swift/Basic/LLVM.h" #include "swift/IDE/CodeCompletion.h" #include "swift/Markup/XMLUtils.h" #include "llvm/Support/raw_ostream.h" @@ -255,3 +256,186 @@ void swift::ide::printCodeCompletionResultTypeNameAnnotated(const CodeCompletion AnnotatingResultPrinter printer(OS); printer.printTypeName(Result); } + +/// Provide the text for the call parameter, including constructing a typed +/// editor placeholder for it. +static void +constructTextForCallParam(ArrayRef ParamGroup, + raw_ostream &OS) { + assert(ParamGroup.front().is(ChunkKind::CallParameterBegin)); + + for (; !ParamGroup.empty(); ParamGroup = ParamGroup.slice(1)) { + auto &C = ParamGroup.front(); + if (C.isAnnotation()) + continue; + if (C.is(ChunkKind::CallParameterInternalName) || + C.is(ChunkKind::CallParameterType) || + C.is(ChunkKind::CallParameterTypeBegin) || + C.is(ChunkKind::CallParameterClosureExpr)) { + break; + } + if (!C.hasText()) + continue; + OS << C.getText(); + } + + SmallString<32> DisplayString; + SmallString<32> TypeString; + SmallString<32> ExpansionTypeString; + + for (auto i = ParamGroup.begin(), e = ParamGroup.end(); i != e; ++i) { + auto &C = *i; + if (C.is(ChunkKind::CallParameterTypeBegin)) { + assert(TypeString.empty()); + auto nestingLevel = C.getNestingLevel(); + ++i; + for (; i != e; ++i) { + if (i->endsPreviousNestedGroup(nestingLevel)) + break; + if (!i->isAnnotation() && i->hasText()) { + TypeString += i->getText(); + DisplayString += i->getText(); + } + } + --i; + continue; + } + if (C.is(ChunkKind::CallParameterClosureType)) { + assert(ExpansionTypeString.empty()); + ExpansionTypeString = C.getText(); + continue; + } + if (C.is(ChunkKind::CallParameterType)) { + assert(TypeString.empty()); + TypeString = C.getText(); + } + if (C.is(ChunkKind::CallParameterClosureExpr)) { + // We have a closure expression, so provide it directly instead of in + // a placeholder. + OS << "{"; + if (!C.getText().empty()) + OS << " " << C.getText(); + OS << "\n" << getCodePlaceholder() << "\n}"; + return; + } + if (C.isAnnotation() || !C.hasText()) + continue; + DisplayString += C.getText(); + } + + StringRef Display = DisplayString.str(); + StringRef Type = TypeString.str(); + StringRef ExpansionType = ExpansionTypeString.str(); + if (ExpansionType.empty()) + ExpansionType = Type; + + OS << "<#T##" << Display; + if (Display == Type && Display == ExpansionType) { + // Short version, display and type are the same. + } else { + OS << "##" << Type; + if (ExpansionType != Type) + OS << "##" << ExpansionType; + } + OS << "#>"; +} + +void swift::ide::printCodeCompletionResultSourceText( + const CodeCompletionResult &Result, llvm::raw_ostream &OS) { + auto Chunks = Result.getCompletionString()->getChunks(); + for (size_t i = 0; i < Chunks.size(); ++i) { + auto &C = Chunks[i]; + if (C.is(ChunkKind::BraceStmtWithCursor)) { + OS << " {\n" << getCodePlaceholder() << "\n}"; + continue; + } + if (C.is(ChunkKind::CallParameterBegin)) { + size_t Start = i++; + for (; i < Chunks.size(); ++i) { + if (Chunks[i].endsPreviousNestedGroup(C.getNestingLevel())) + break; + } + constructTextForCallParam(Chunks.slice(Start, i - Start), OS); + --i; + continue; + } + if (C.is(ChunkKind::TypeAnnotationBegin)) { + // Skip type annotation structure. + auto level = C.getNestingLevel(); + do { + ++i; + } while (i != Chunks.size() && !Chunks[i].endsPreviousNestedGroup(level)); + --i; + } + if (!C.isAnnotation() && C.hasText()) { + OS << C.getText(); + } + } +} + +void swift::ide::printCodeCompletionResultFilterName( + const CodeCompletionResult &Result, llvm::raw_ostream &OS) { + auto str = Result.getCompletionString(); + // FIXME: we need a more uniform way to handle operator completions. + if (str->getChunks().size() == 1 && str->getChunks()[0].is(ChunkKind::Dot)) { + OS << "."; + return; + } else if (str->getChunks().size() == 2 && + str->getChunks()[0].is(ChunkKind::QuestionMark) && + str->getChunks()[1].is(ChunkKind::Dot)) { + OS << "?."; + return; + } + + auto FirstTextChunk = str->getFirstTextChunkIndex(); + if (FirstTextChunk.hasValue()) { + auto chunks = str->getChunks().slice(*FirstTextChunk); + for (auto i = chunks.begin(), e = chunks.end(); i != e; ++i) { + auto &C = *i; + + if (C.is(ChunkKind::BraceStmtWithCursor)) + break; // Don't include brace-stmt in filter name. + + if (C.is(ChunkKind::Equal)) { + OS << C.getText(); + break; + } + + bool shouldPrint = !C.isAnnotation(); + switch (C.getKind()) { + case ChunkKind::TypeAnnotation: + case ChunkKind::CallParameterInternalName: + case ChunkKind::CallParameterClosureType: + case ChunkKind::CallParameterClosureExpr: + case ChunkKind::CallParameterType: + case ChunkKind::DeclAttrParamColon: + case ChunkKind::Comma: + case ChunkKind::Whitespace: + case ChunkKind::Ellipsis: + case ChunkKind::Ampersand: + case ChunkKind::OptionalMethodCallTail: + continue; + case ChunkKind::CallParameterTypeBegin: + case ChunkKind::TypeAnnotationBegin: { + // Skip call parameter type or type annotation structure. + auto nestingLevel = C.getNestingLevel(); + do { + ++i; + } while (i != e && !i->endsPreviousNestedGroup(nestingLevel)); + --i; + continue; + } + case ChunkKind::CallParameterColon: + // Since we don't add the type, also don't add the space after ':'. + if (shouldPrint) + OS << ":"; + continue; + default: + break; + } + + if (C.hasText() && shouldPrint) + OS << C.getText(); + } + } +} diff --git a/lib/IDE/CompletionInstance.cpp b/lib/IDE/CompletionInstance.cpp index 26df36591975f..1aeffb3304356 100644 --- a/lib/IDE/CompletionInstance.cpp +++ b/lib/IDE/CompletionInstance.cpp @@ -85,8 +85,6 @@ template Decl *getElementAt(const Range &Decls, unsigned N) { /// Find the equivalent \c DeclContext with \p DC from \p SF AST. /// This assumes the AST which contains \p DC has exact the same structure with /// \p SF. -/// FIXME: This doesn't support IfConfigDecl blocks. If \p DC is in an inactive -/// config block, this function returns \c false. static DeclContext *getEquivalentDeclContextFromSourceFile(DeclContext *DC, SourceFile *SF) { PrettyStackTraceDeclContext trace("getting equivalent decl context for", DC); @@ -129,7 +127,6 @@ static DeclContext *getEquivalentDeclContextFromSourceFile(DeclContext *DC, } // Not found in the decl context tree. - // FIXME: Probably DC is in an inactive #if block. if (N == ~0U) { return nullptr; } @@ -411,9 +408,14 @@ bool CompletionInstance::performCachedOperationIfPossible( oldInfo.PrevOffset = newInfo.PrevOffset; oldState->restoreCodeCompletionDelayedDeclState(oldInfo); + auto newBufferStart = SM.getRangeForBuffer(newBufferID).getStart(); + SourceRange newBodyRange(newBufferStart.getAdvancedLoc(newInfo.StartOffset), + newBufferStart.getAdvancedLoc(newInfo.EndOffset)); + auto *AFD = cast(DC); - if (AFD->isBodySkipped()) - AFD->setBodyDelayed(AFD->getBodySourceRange()); + AFD->setBodyToBeReparsed(newBodyRange); + SM.setReplacedRange({AFD->getOriginalBodySourceRange(), newBodyRange}); + oldSF->clearScope(); traceDC = AFD; break; @@ -483,8 +485,6 @@ bool CompletionInstance::performCachedOperationIfPossible( } CachedReuseCount += 1; - cacheDependencyHashIfNeeded(CI, SM.getCodeCompletionBufferID(), - InMemoryDependencyHash); return true; } @@ -599,9 +599,6 @@ bool swift::ide::CompletionInstance::performOperation( // We don't need token list. Invocation.getLangOptions().CollectParsedToken = false; - // FIXME: ASTScopeLookup doesn't support code completion yet. - Invocation.disableASTScopeLookup(); - if (EnableASTCaching) { // Compute the signature of the invocation. llvm::hash_code ArgsHash(0); diff --git a/lib/IDE/ConformingMethodList.cpp b/lib/IDE/ConformingMethodList.cpp index 9a843b82f0cc0..f1fcf9f6f00e0 100644 --- a/lib/IDE/ConformingMethodList.cpp +++ b/lib/IDE/ConformingMethodList.cpp @@ -154,7 +154,7 @@ void ConformingMethodListCallbacks::getMatchingMethods( Result(result) {} void foundDecl(ValueDecl *VD, DeclVisibilityKind reason, - DynamicLookupInfo) { + DynamicLookupInfo) override { if (isMatchingMethod(VD) && !VD->shouldHideFromEditor()) Result.push_back(VD); } diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index 787606e321891..96f0b2126ce09 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -46,9 +46,11 @@ void swift::ide::typeCheckContextAt(DeclContext *DC, SourceLoc Loc) { while (isa(DC)) DC = DC->getParent(); - // Make sure the extension has been bound, in case it is in an inactive #if - // or something weird like that. + // Make sure the extension has been bound. { + // Even if the extension is invalid (e.g. nested in a function or another + // type), we want to know the "intended nominal" of the extension so that + // we can know the type of 'Self'. SmallVector extensions; for (auto typeCtx = DC->getInnermostTypeContext(); typeCtx != nullptr; typeCtx = typeCtx->getParent()->getInnermostTypeContext()) { @@ -59,6 +61,20 @@ void swift::ide::typeCheckContextAt(DeclContext *DC, SourceLoc Loc) { extensions.back()->computeExtendedNominal(); extensions.pop_back(); } + + // If the completion happens in the inheritance clause of the extension, + // 'DC' is the parent of the extension. We need to iterate the top level + // decls to find it. In theory, we don't need the extended nominal in the + // inheritance clause, but ASTScope lookup requires that. We don't care + // unless 'DC' is not 'SourceFile' because non-toplevel extensions are + // 'canNeverBeBound()' anyway. + if (auto *SF = dyn_cast(DC)) { + auto &SM = DC->getASTContext().SourceMgr; + for (auto *decl : SF->getTopLevelDecls()) + if (auto *ext = dyn_cast(decl)) + if (SM.rangeContainsTokenLoc(ext->getSourceRange(), Loc)) + ext->computeExtendedNominal(); + } } // Type-check this context. @@ -85,6 +101,11 @@ void swift::ide::typeCheckContextAt(DeclContext *DC, SourceLoc Loc) { typeCheckPatternBinding(PBD, i); } } + } else if (auto *defaultArg = dyn_cast(DC)) { + if (auto *AFD = dyn_cast(defaultArg->getParent())) { + auto *Param = AFD->getParameters()->get(defaultArg->getIndex()); + (void*)Param->getTypeCheckedDefaultExpr(); + } } break; @@ -558,6 +579,31 @@ static void collectPossibleCalleesByQualifiedLookup( } } +/// 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(), + 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, @@ -599,6 +645,8 @@ static bool collectPossibleCalleesForApply( } else if (auto CRCE = dyn_cast(fnExpr)) { collectPossibleCalleesByQualifiedLookup( DC, CRCE->getArg(), DeclNameRef::createConstructor(), candidates); + } else if (auto *UME = dyn_cast(fnExpr)) { + collectPossibleCalleesForUnresolvedMember(DC, UME, candidates); } if (!candidates.empty()) @@ -662,39 +710,6 @@ static bool collectPossibleCalleesForSubscript( return !candidates.empty(); } -/// For the given \p unresolvedMemberExpr, collect possible callee types and -/// declarations. -static bool collectPossibleCalleesForUnresolvedMember( - DeclContext &DC, UnresolvedMemberExpr *unresolvedMemberExpr, - SmallVectorImpl &candidates) { - auto currModule = DC.getParentModule(); - - auto collectMembers = [&](Type expectedTy) { - if (!expectedTy->mayHaveMembers()) - return; - SmallVector members; - collectPossibleCalleesByQualifiedLookup(DC, MetatypeType::get(expectedTy), - unresolvedMemberExpr->getName(), - members); - for (auto member : members) { - if (isReferenceableByImplicitMemberExpr(currModule, &DC, expectedTy, - member.Decl)) - candidates.push_back(member); - } - }; - - // 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(); -} - /// Get index of \p CCExpr in \p Args. \p Args is usually a \c TupleExpr /// or \c ParenExpr. /// \returns \c true if success, \c false if \p CCExpr is not a part of \p Args. @@ -761,11 +776,6 @@ class ExprContextAnalyzer { if (!collectPossibleCalleesForSubscript(*DC, subscriptExpr, Candidates)) return false; Arg = subscriptExpr->getIndex(); - } else if (auto *unresolvedMemberExpr = dyn_cast(E)) { - if (!collectPossibleCalleesForUnresolvedMember(*DC, unresolvedMemberExpr, - Candidates)) - return false; - Arg = unresolvedMemberExpr->getArgument(); } else { llvm_unreachable("unexpected expression kind"); } @@ -840,7 +850,6 @@ class ExprContextAnalyzer { switch (Parent->getKind()) { case ExprKind::Call: case ExprKind::Subscript: - case ExprKind::UnresolvedMember: case ExprKind::Binary: case ExprKind::PrefixUnary: { analyzeApplyExpr(Parent); @@ -848,8 +857,10 @@ class ExprContextAnalyzer { } case ExprKind::Array: { if (auto type = ParsedExpr->getType()) { - recordPossibleType(type); - break; + if (!type->is()) { + recordPossibleType(type); + break; + } } // Check context types of the array literal expression. @@ -1144,7 +1155,6 @@ class ExprContextAnalyzer { case ExprKind::Assign: case ExprKind::Dictionary: case ExprKind::If: - case ExprKind::UnresolvedMember: return true; case ExprKind::Array: return (!Parent.getAsExpr() || @@ -1153,8 +1163,7 @@ class ExprContextAnalyzer { auto ParentE = Parent.getAsExpr(); return !ParentE || (!isa(ParentE) && !isa(ParentE) && - !isa(ParentE) && - !isa(ParentE)); + !isa(ParentE)); } case ExprKind::Closure: return isSingleExpressionBodyForCodeCompletion( @@ -1228,73 +1237,3 @@ ExprContextInfo::ExprContextInfo(DeclContext *DC, Expr *TargetExpr) { singleExpressionBody); Analyzer.Analyze(); } - -//===----------------------------------------------------------------------===// -// isReferenceableByImplicitMemberExpr(ModuleD, DeclContext, Type, ValueDecl) -//===----------------------------------------------------------------------===// - -bool swift::ide::isReferenceableByImplicitMemberExpr( - ModuleDecl *CurrModule, DeclContext *DC, Type T, ValueDecl *VD) { - - if (VD->isOperator()) - return false; - - if (T->getOptionalObjectType() && - VD->getModuleContext()->isStdlibModule()) { - // In optional context, ignore '.init()', 'init(nilLiteral:)', - if (isa(VD)) - return false; - // TODO: Ignore '.some()' and '.none' too *in expression - // context*. They are useful in pattern context though. - } - - // Enum element decls can always be referenced by implicit member - // expression. - if (isa(VD)) - return true; - - // Only non-failable constructors are implicitly referenceable. - if (auto CD = dyn_cast(VD)) { - return (!CD->isFailable() || CD->isImplicitlyUnwrappedOptional()); - } - - // Otherwise, check the result type matches the contextual type. - auto declTy = T->getTypeOfMember(CurrModule, VD); - if (declTy->is()) - return false; - - // Member types can also be implicitly referenceable as long as it's - // convertible to the contextual type. - if (auto CD = dyn_cast(VD)) { - declTy = declTy->getMetatypeInstanceType(); - - // Emit construction for the same type via typealias doesn't make sense - // because we are emitting all `.init()`s. - if (declTy->isEqual(T)) - return false; - - // Only non-protocol nominal type can be instantiated. - auto nominal = declTy->getAnyNominal(); - if (!nominal || isa(nominal)) - return false; - - return swift::isConvertibleTo(declTy, T, /*openArchetypes=*/true, *DC); - } - - // Only static member can be referenced. - if (!VD->isStatic()) - return false; - - if (isa(VD)) { - // Strip '(Self.Type) ->' and parameters. - declTy = declTy->castTo()->getResult(); - declTy = declTy->castTo()->getResult(); - } else if (auto FT = declTy->getAs()) { - // The compiler accepts 'static var factory: () -> T' for implicit - // member expression. - // FIXME: This emits just 'factory'. We should emit 'factory()' instead. - declTy = FT->getResult(); - } - return declTy->isEqual(T) || - swift::isConvertibleTo(declTy, T, /*openArchetypes=*/true, *DC); -} diff --git a/lib/IDE/ExprContextAnalysis.h b/lib/IDE/ExprContextAnalysis.h index 1e0b749ac065c..9c957353b68e0 100644 --- a/lib/IDE/ExprContextAnalysis.h +++ b/lib/IDE/ExprContextAnalysis.h @@ -114,10 +114,6 @@ class ExprContextInfo { } }; -/// Returns whether \p VD is referenceable with implicit member expression. -bool isReferenceableByImplicitMemberExpr( - ModuleDecl *CurrModule, DeclContext *DC, Type T, ValueDecl *VD); - } // namespace ide } // namespace swift diff --git a/lib/IDE/Formatting.cpp b/lib/IDE/Formatting.cpp index 69b9fc92f4b7a..6100a21d41669 100644 --- a/lib/IDE/Formatting.cpp +++ b/lib/IDE/Formatting.cpp @@ -61,6 +61,13 @@ getLocForContentStartOnSameLine(SourceManager &SM, SourceLoc Loc) { return LineStart.getAdvancedLoc(Indentation.size()); } +/// \returns true if the line at \c Loc is either empty or only contains whitespace +static bool isLineAtLocEmpty(SourceManager &SM, SourceLoc Loc) { + SourceLoc LineStart = Lexer::getLocForStartOfLine(SM, Loc); + SourceLoc Next = Lexer::getTokenAtLocation(SM, LineStart, CommentRetentionMode::ReturnAsTokens).getLoc(); + return Next.isInvalid() || !isOnSameLine(SM, Loc, Next); +} + /// \returns the first token after the token at \c Loc. static Optional getTokenAfter(SourceManager &SM, SourceLoc Loc, bool SkipComments = true) { @@ -136,6 +143,21 @@ static ClosureExpr *findTrailingClosureFromArgument(Expr *arg) { return nullptr; } +static size_t calcVisibleWhitespacePrefix(StringRef Line, + CodeFormatOptions Options) { + size_t Indent = 0; + for (auto Char : Line) { + if (Char == '\t') { + Indent += Options.TabWidth; + } else if (Char == ' ' || Char == '\v' || Char == '\f') { + Indent++; + } else { + break; + } + } + return Indent; +} + /// An indentation context of the target location struct IndentContext { enum ContextKind { Exact, LineStart }; @@ -258,16 +280,14 @@ class FormatContext { Optional InnermostCtx; bool InDocCommentBlock; bool InCommentLine; - bool InStringLiteral; public: FormatContext(SourceManager &SM, Optional IndentCtx, bool InDocCommentBlock = false, - bool InCommentLine = false, - bool InStringLiteral = false) + bool InCommentLine = false) :SM(SM), InnermostCtx(IndentCtx), InDocCommentBlock(InDocCommentBlock), - InCommentLine(InCommentLine), InStringLiteral(InStringLiteral) { } + InCommentLine(InCommentLine) { } bool IsInDocCommentBlock() { return InDocCommentBlock; @@ -277,10 +297,6 @@ class FormatContext { return InCommentLine; } - bool IsInStringLiteral() const { - return InStringLiteral; - } - void padToExactColumn(StringBuilder &Builder, const CodeFormatOptions &FmtOptions) { assert(isExact() && "Context is not exact?"); @@ -1208,8 +1224,9 @@ class FormatWalker : public ASTWalker { bool InDocCommentBlock = false; /// Whether the target location appears within a line comment. bool InCommentLine = false; - /// Whether the target location appears within a string literal. - bool InStringLiteral = false; + + /// The range of the string literal the target is inside of (if any, invalid otherwise). + CharSourceRange StringLiteralRange; public: explicit FormatWalker(SourceFile &SF, SourceManager &SM, CodeFormatOptions &Options) @@ -1224,7 +1241,8 @@ class FormatWalker : public ASTWalker { CtxOverride.clear(); TargetLocation = Loc; TargetLineLoc = Lexer::getLocForStartOfLine(SM, TargetLocation); - InDocCommentBlock = InCommentLine = InStringLiteral = false; + InDocCommentBlock = InCommentLine = false; + StringLiteralRange = CharSourceRange(); NodesToSkip.clear(); CurrentTokIt = TokenList.begin(); @@ -1234,14 +1252,99 @@ class FormatWalker : public ASTWalker { if (InnermostCtx) CtxOverride.applyIfNeeded(SM, *InnermostCtx); + if (StringLiteralRange.isValid()) { + assert(!InDocCommentBlock && !InCommentLine && + "Target is in both a string and comment"); + InnermostCtx = indentWithinStringLiteral(); + } else { + assert(!InDocCommentBlock || !InCommentLine && + "Target is in both a doc comment block and comment line"); + } + return FormatContext(SM, InnermostCtx, InDocCommentBlock, - InCommentLine, InStringLiteral); + InCommentLine); } +private: + + Optional indentWithinStringLiteral() { + assert(StringLiteralRange.isValid() && "Target is not within a string literal"); + + // This isn't ideal since if the user types """""" and then an enter + // inside after, we won't indent the end quotes. But indenting the end + // quotes could lead to an error in the rest of the string, so best to + // avoid it entirely for now. + if (isOnSameLine(SM, TargetLineLoc, StringLiteralRange.getEnd())) + return IndentContext {TargetLocation, false, IndentContext::Exact}; + + // If there's contents before the end quotes then it's likely the quotes + // are actually the start quotes of the next string in the file. Pretend + // they don't exist so their indent doesn't affect the indenting. + SourceLoc EndLineContentLoc = + getLocForContentStartOnSameLine(SM, StringLiteralRange.getEnd()); + bool HaveEndQuotes = CharSourceRange(SM, EndLineContentLoc, + StringLiteralRange.getEnd()) + .str().equals(StringRef("\"\"\"")); + + if (!HaveEndQuotes) { + // Indent to the same indentation level as the first non-empty line + // before the target. If that line is the start line then either use + // the same indentation of the start quotes if they are on their own + // line, or an extra indentation otherwise. + // + // This will indent lines with content on it as well, which should be + // fine since it is quite unlikely anyone would format a range that + // includes an unterminated string. + + SourceLoc AlignLoc = TargetLineLoc; + while (SM.isBeforeInBuffer(StringLiteralRange.getStart(), AlignLoc)) { + AlignLoc = Lexer::getLocForStartOfLine(SM, AlignLoc.getAdvancedLoc(-1)); + if (!isLineAtLocEmpty(SM, AlignLoc)) { + AlignLoc = getLocForContentStartOnSameLine(SM, AlignLoc); + break; + } + } + + if (isOnSameLine(SM, AlignLoc, StringLiteralRange.getStart())) { + SourceLoc StartLineContentLoc = + getLocForContentStartOnSameLine(SM, StringLiteralRange.getStart()); + bool StartLineOnlyQuotes = CharSourceRange(SM, StartLineContentLoc, + StringLiteralRange.getEnd()) + .str().startswith(StringRef("\"\"\"")); + if (!StartLineOnlyQuotes) + return IndentContext {StringLiteralRange.getStart(), true}; + + AlignLoc = StringLiteralRange.getStart(); + } + + return IndentContext {AlignLoc, false, IndentContext::Exact}; + } + + // If there are end quotes, only enforce a minimum indentation. We don't + // want to add any other indentation since that could add unintended + // whitespace to existing strings. Could change this if the full range + // was passed rather than a single line - in that case we *would* indent + // if the range was a single empty line. + + CharSourceRange TargetIndentRange = + CharSourceRange(SM, Lexer::getLocForStartOfLine(SM, TargetLocation), + TargetLocation); + CharSourceRange EndIndentRange = + CharSourceRange(SM, Lexer::getLocForStartOfLine(SM, EndLineContentLoc), + EndLineContentLoc); + + size_t TargetIndent = + calcVisibleWhitespacePrefix(TargetIndentRange.str(), FmtOptions); + size_t EndIndent = + calcVisibleWhitespacePrefix(EndIndentRange.str(), FmtOptions); + if (TargetIndent >= EndIndent) + return IndentContext {TargetLocation, false, IndentContext::Exact}; + + return IndentContext {EndLineContentLoc, false, IndentContext::Exact}; + } #pragma mark ASTWalker overrides and helpers -private: bool walkCustomAttributes(Decl *D) { // CustomAttrs of non-param VarDecls are handled when this method is called // on their containing PatternBindingDecls (below). @@ -1330,7 +1433,7 @@ class FormatWalker : public ASTWalker { SM.isBeforeInBuffer(E->getStartLoc(), TargetLocation) && SM.isBeforeInBuffer(TargetLocation, Lexer::getLocForEndOfToken(SM, E->getEndLoc()))) { - InStringLiteral = true; + StringLiteralRange = Lexer::getCharSourceRangeFromSourceRange(SM, E->getSourceRange()); } // Create a default indent context for all top-level expressions @@ -1352,7 +1455,7 @@ class FormatWalker : public ASTWalker { // Don't visit the child expressions of interpolated strings directly - // visit only the argument of each appendInterpolation call instead, and - // update InStringLiteral for each segment. + // set StringLiteralRange if needed for each segment. if (auto *ISL = dyn_cast(E)) { if (Action.shouldVisitChildren()) { llvm::SaveAndRestore(Parent, ISL); @@ -1364,7 +1467,8 @@ class FormatWalker : public ASTWalker { // Handle the preceeding string segment. CharSourceRange StringRange(SM, PrevStringStart, CE->getStartLoc()); if (StringRange.contains(TargetLocation)) { - InStringLiteral = true; + StringLiteralRange = + Lexer::getCharSourceRangeFromSourceRange(SM, E->getSourceRange()); return; } // Walk into the interpolation segment. @@ -1378,7 +1482,8 @@ class FormatWalker : public ASTWalker { SourceLoc End = Lexer::getLocForEndOfToken(SM, ISL->getStartLoc()); CharSourceRange StringRange(SM, PrevStringStart, End); if (StringRange.contains(TargetLocation)) - InStringLiteral = true; + StringLiteralRange = + Lexer::getCharSourceRangeFromSourceRange(SM, E->getSourceRange()); return {false, E}; } @@ -1467,7 +1572,7 @@ class FormatWalker : public ASTWalker { } void scanTokensUntil(SourceLoc Loc) { - if (InDocCommentBlock || InCommentLine) + if (InDocCommentBlock || InCommentLine || StringLiteralRange.isValid()) return; for (auto Invalid = Loc.isInvalid(); CurrentTokIt != TokenList.end() && (Invalid || SM.isBeforeInBuffer(CurrentTokIt->getLoc(), Loc)); @@ -1477,16 +1582,16 @@ class FormatWalker : public ASTWalker { SourceLoc StartLineLoc = Lexer::getLocForStartOfLine( SM, CommentRange.getStart()); - // The -1 is needed in case the past-the-end position is a newline - // character. In that case getLocForStartOfLine returns the start of - // the next line. SourceLoc EndLineLoc = Lexer::getLocForStartOfLine( - SM, CommentRange.getEnd().getAdvancedLoc(-1)); + SM, CommentRange.getEnd()); auto TokenStr = CurrentTokIt->getRange().str(); InDocCommentBlock |= SM.isBeforeInBuffer(StartLineLoc, TargetLineLoc) && !SM.isBeforeInBuffer(EndLineLoc, TargetLineLoc) && TokenStr.startswith("/*"); InCommentLine |= StartLineLoc == TargetLineLoc && TokenStr.startswith("//"); + } else if (CurrentTokIt->getKind() == tok::unknown && + CurrentTokIt->getRange().str().startswith("\"\"\"")) { + StringLiteralRange = CurrentTokIt->getRange(); } } } @@ -2797,12 +2902,6 @@ class CodeFormatter { std::pair indent(unsigned LineIndex, FormatContext &FC, StringRef Text) { - if (FC.IsInStringLiteral()) { - return std::make_pair( - LineRange(LineIndex, 1), - swift::ide::getTextForLine(LineIndex, Text, /*Trim*/ false).str()); - } - if (FC.isExact()) { StringRef Line = swift::ide::getTextForLine(LineIndex, Text, /*Trim*/true); StringBuilder Builder; diff --git a/tools/SourceKit/lib/Support/FuzzyStringMatcher.cpp b/lib/IDE/FuzzyStringMatcher.cpp similarity index 99% rename from tools/SourceKit/lib/Support/FuzzyStringMatcher.cpp rename to lib/IDE/FuzzyStringMatcher.cpp index 463d541d0d850..d016464691f19 100644 --- a/tools/SourceKit/lib/Support/FuzzyStringMatcher.cpp +++ b/lib/IDE/FuzzyStringMatcher.cpp @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information @@ -10,12 +10,13 @@ // //===----------------------------------------------------------------------===// -#include "SourceKit/Support/FuzzyStringMatcher.h" +#include "swift/IDE/FuzzyStringMatcher.h" #include "clang/Basic/CharInfo.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" -using namespace SourceKit; +using namespace swift; +using namespace swift::ide; using clang::toUppercase; using clang::toLowercase; using clang::isUppercase; diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp index 8c6bdcc01143e..e7838a606ce3e 100644 --- a/lib/IDE/Refactoring.cpp +++ b/lib/IDE/Refactoring.cpp @@ -1711,7 +1711,7 @@ class FindAllSubDecls : public SourceEntityWalker { FindAllSubDecls(llvm::SmallPtrSetImpl &found) : Found(found) {} - bool walkToDeclPre(Decl *D, CharSourceRange range) { + bool walkToDeclPre(Decl *D, CharSourceRange range) override { // Record this Decl, and skip its contents if we've already touched it. if (!Found.insert(D).second) return false; @@ -1876,7 +1876,7 @@ findConcatenatedExpressions(ResolvedRangeInfo Info, ASTContext &Ctx) { return true; } - bool walkToExprPre(Expr *E) { + bool walkToExprPre(Expr *E) override { if (E->isImplicit()) return true; // FIXME: we should have ErrorType instead of null. @@ -2001,13 +2001,13 @@ class ExpandableAssignTernaryExprInfo: public ExpandableTernaryExprInfo { public: ExpandableAssignTernaryExprInfo(AssignExpr *Assign): Assign(Assign) {} - IfExpr *getIf() { + IfExpr *getIf() override { if (!Assign) return nullptr; return dyn_cast_or_null(Assign->getSrc()); } - SourceRange getNameRange() { + SourceRange getNameRange() override { auto Invalid = SourceRange(); if (!Assign) @@ -2019,7 +2019,7 @@ class ExpandableAssignTernaryExprInfo: public ExpandableTernaryExprInfo { return Invalid; } - Type getType() { + Type getType() override { return nullptr; } @@ -2035,7 +2035,7 @@ class ExpandableBindingTernaryExprInfo: public ExpandableTernaryExprInfo { ExpandableBindingTernaryExprInfo(PatternBindingDecl *Binding): Binding(Binding) {} - IfExpr *getIf() { + IfExpr *getIf() override { if (Binding && Binding->getNumPatternEntries() == 1) { if (auto *Init = Binding->getInit(0)) { return dyn_cast(Init); @@ -2045,14 +2045,14 @@ class ExpandableBindingTernaryExprInfo: public ExpandableTernaryExprInfo { return nullptr; } - SourceRange getNameRange() { + SourceRange getNameRange() override { if (auto Pattern = getNamePattern()) return Pattern->getSourceRange(); return SourceRange(); } - Type getType() { + Type getType() override { if (auto Pattern = getNamePattern()) return Pattern->getType(); @@ -2347,7 +2347,7 @@ isApplicable(ResolvedRangeInfo Info, DiagnosticEngine &Diag) { bool ConditionUseOnlyAllowedFunctions = false; StringRef ExpectName; - Expr *walkToExprPost(Expr *E) { + Expr *walkToExprPost(Expr *E) override { if (E->getKind() != ExprKind::DeclRef) return E; auto D = dyn_cast(E)->getDecl(); @@ -2446,7 +2446,7 @@ bool RefactoringActionConvertToSwitchStmt::performChange() { public: std::string VarName; - Expr *walkToExprPost(Expr *E) { + Expr *walkToExprPost(Expr *E) override { if (E->getKind() != ExprKind::DeclRef) return E; auto D = dyn_cast(E)->getDecl(); @@ -2463,7 +2463,7 @@ bool RefactoringActionConvertToSwitchStmt::performChange() { SmallString<64> ConditionalPattern = SmallString<64>(); - Expr *walkToExprPost(Expr *E) { + Expr *walkToExprPost(Expr *E) override { if (E->getKind() != ExprKind::Binary) return E; auto BE = dyn_cast(E); @@ -2472,7 +2472,7 @@ bool RefactoringActionConvertToSwitchStmt::performChange() { return E; } - std::pair walkToPatternPre(Pattern *P) { + std::pair walkToPatternPre(Pattern *P) override { ConditionalPattern.append(Lexer::getCharSourceRangeFromSourceRange(SM, P->getSourceRange()).str()); if (P->getKind() == PatternKind::OptionalSome) ConditionalPattern.append("?"); @@ -2705,7 +2705,7 @@ findConvertToTernaryExpression(ResolvedRangeInfo Info) { walk(S); } - virtual bool walkToExprPre(Expr *E) { + virtual bool walkToExprPre(Expr *E) override { Assign = dyn_cast(E); return false; } @@ -3086,7 +3086,7 @@ static Expr *findLocalizeTarget(ResolvedCursorInfo CursorInfo) { SourceLoc StartLoc; Expr *Target; StringLiteralFinder(SourceLoc StartLoc): StartLoc(StartLoc), Target(nullptr) {} - bool walkToExprPre(Expr *E) { + bool walkToExprPre(Expr *E) override { if (E->getStartLoc() != StartLoc) return false; if (E->getKind() == ExprKind::InterpolatedStringLiteral) diff --git a/lib/IDE/SourceEntityWalker.cpp b/lib/IDE/SourceEntityWalker.cpp index 6f6f08e9daf27..dd494e03cad25 100644 --- a/lib/IDE/SourceEntityWalker.cpp +++ b/lib/IDE/SourceEntityWalker.cpp @@ -715,6 +715,12 @@ passReference(ValueDecl *D, Type Ty, SourceLoc BaseNameLoc, SourceRange Range, } } + if (D == nullptr) { + // FIXME: When does this happen? + assert(false && "unhandled reference"); + return true; + } + CharSourceRange CharRange = Lexer::getCharSourceRangeFromSourceRange(D->getASTContext().SourceMgr, Range); diff --git a/lib/IDE/SwiftSourceDocInfo.cpp b/lib/IDE/SwiftSourceDocInfo.cpp index b372b1cba3e39..6f44a3078ac63 100644 --- a/lib/IDE/SwiftSourceDocInfo.cpp +++ b/lib/IDE/SwiftSourceDocInfo.cpp @@ -282,10 +282,6 @@ Stmt *NameMatcher::walkToStmtPost(Stmt *S) { } Expr *NameMatcher::getApplicableArgFor(Expr *E) { - if (auto *UME = dyn_cast(E)) { - if (auto *Arg = UME->getArgument()) - return Arg; - } if (ParentCalls.empty()) return nullptr; auto &Last = ParentCalls.back(); diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp index 0d06879c184a7..7504a1b6bf183 100644 --- a/lib/IDE/SyntaxModel.cpp +++ b/lib/IDE/SyntaxModel.cpp @@ -905,7 +905,7 @@ bool ModelASTWalker::walkToDeclPre(Decl *D) { AFD->getSignatureSourceRange()); if (FD) { SN.TypeRange = charSourceRangeFromSourceRange(SM, - FD->getBodyResultTypeLoc().getSourceRange()); + FD->getResultTypeSourceRange()); } pushStructureNode(SN, AFD); } else if (auto *NTD = dyn_cast(D)) { @@ -1096,7 +1096,7 @@ bool ModelASTWalker::walkToDeclPre(Decl *D) { SN.NameRange = charSourceRangeFromSourceRange(SM, SubscriptD->getSignatureSourceRange()); SN.TypeRange = charSourceRangeFromSourceRange(SM, - SubscriptD->getElementTypeLoc().getSourceRange()); + SubscriptD->getElementTypeSourceRange()); pushStructureNode(SN, SubscriptD); } else if (auto *AssociatedTypeD = dyn_cast(D)) { SyntaxStructureNode SN; diff --git a/lib/IDE/TypeContextInfo.cpp b/lib/IDE/TypeContextInfo.cpp index aacaa875d96b3..0ab8242b7aa34 100644 --- a/lib/IDE/TypeContextInfo.cpp +++ b/lib/IDE/TypeContextInfo.cpp @@ -158,7 +158,7 @@ void ContextInfoCallbacks::getImplicitMembers( : DC(DC), CurModule(DC->getParentModule()), T(T), Result(Result) {} void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason, - DynamicLookupInfo) { + DynamicLookupInfo) override { if (canBeImplictMember(VD) && !VD->shouldHideFromEditor()) Result.push_back(VD); } diff --git a/lib/IDE/Utils.cpp b/lib/IDE/Utils.cpp index 616a0e6e0678f..5d0dda4b8e555 100644 --- a/lib/IDE/Utils.cpp +++ b/lib/IDE/Utils.cpp @@ -14,6 +14,7 @@ #include "swift/Basic/Edit.h" #include "swift/Basic/SourceManager.h" #include "swift/ClangImporter/ClangModule.h" +#include "swift/Driver/FrontendUtil.h" #include "swift/Frontend/Frontend.h" #include "swift/Parse/Parser.h" #include "swift/Subsystems.h" @@ -188,6 +189,190 @@ ide::isSourceInputComplete(StringRef Text,SourceFileKind SFKind) { SFKind); } +static FrontendInputsAndOutputs resolveSymbolicLinksInInputs( + FrontendInputsAndOutputs &inputsAndOutputs, StringRef UnresolvedPrimaryFile, + llvm::IntrusiveRefCntPtr FileSystem, + std::string &Error) { + assert(FileSystem); + + llvm::SmallString<128> PrimaryFile; + if (auto err = FileSystem->getRealPath(UnresolvedPrimaryFile, PrimaryFile)) + PrimaryFile = UnresolvedPrimaryFile; + + unsigned primaryCount = 0; + // FIXME: The frontend should be dealing with symlinks, maybe similar to + // clang's FileManager ? + FrontendInputsAndOutputs replacementInputsAndOutputs; + for (const InputFile &input : inputsAndOutputs.getAllInputs()) { + llvm::SmallString<128> newFilename; + if (auto err = FileSystem->getRealPath(input.file(), newFilename)) + newFilename = input.file(); + llvm::sys::path::native(newFilename); + bool newIsPrimary = input.isPrimary() || + (!PrimaryFile.empty() && PrimaryFile == newFilename); + if (newIsPrimary) { + ++primaryCount; + } + assert(primaryCount < 2 && "cannot handle multiple primaries"); + replacementInputsAndOutputs.addInput( + InputFile(newFilename.str(), newIsPrimary, input.buffer())); + } + + if (PrimaryFile.empty() || primaryCount == 1) { + return replacementInputsAndOutputs; + } + + llvm::SmallString<64> Err; + llvm::raw_svector_ostream OS(Err); + OS << "'" << PrimaryFile << "' is not part of the input files"; + Error = std::string(OS.str()); + return replacementInputsAndOutputs; +} + +static void disableExpensiveSILOptions(SILOptions &Opts) { + // Disable the sanitizers. + Opts.Sanitizers = {}; + + // Disable PGO and code coverage. + Opts.GenerateProfile = false; + Opts.EmitProfileCoverageMapping = false; + Opts.UseProfile = ""; +} + +namespace { +class StreamDiagConsumer : public DiagnosticConsumer { + llvm::raw_ostream &OS; + +public: + StreamDiagConsumer(llvm::raw_ostream &OS) : OS(OS) {} + + void handleDiagnostic(SourceManager &SM, + const DiagnosticInfo &Info) override { + // FIXME: Print location info if available. + switch (Info.Kind) { + case DiagnosticKind::Error: + OS << "error: "; + break; + case DiagnosticKind::Warning: + OS << "warning: "; + break; + case DiagnosticKind::Note: + OS << "note: "; + break; + case DiagnosticKind::Remark: + OS << "remark: "; + break; + } + DiagnosticEngine::formatDiagnosticText(OS, Info.FormatString, + Info.FormatArgs); + } +}; +} // end anonymous namespace + +bool ide::initCompilerInvocation( + CompilerInvocation &Invocation, ArrayRef OrigArgs, + DiagnosticEngine &Diags, StringRef UnresolvedPrimaryFile, + llvm::IntrusiveRefCntPtr FileSystem, + const std::string &runtimeResourcePath, + const std::string &diagnosticDocumentationPath, + bool shouldOptimizeForIDE, time_t sessionTimestamp, std::string &Error) { + SmallVector Args; + // Make sure to put '-resource-dir' and '-diagnostic-documentation-path' at + // the top to allow overriding them with the passed in arguments. + Args.push_back("-resource-dir"); + Args.push_back(runtimeResourcePath.c_str()); + Args.push_back("-Xfrontend"); + Args.push_back("-diagnostic-documentation-path"); + Args.push_back("-Xfrontend"); + Args.push_back(diagnosticDocumentationPath.c_str()); + Args.append(OrigArgs.begin(), OrigArgs.end()); + + SmallString<32> ErrStr; + llvm::raw_svector_ostream ErrOS(ErrStr); + StreamDiagConsumer DiagConsumer(ErrOS); + Diags.addConsumer(DiagConsumer); + + bool HadError = driver::getSingleFrontendInvocationFromDriverArguments( + Args, Diags, [&](ArrayRef FrontendArgs) { + return Invocation.parseArgs(FrontendArgs, Diags); + }, /*ForceNoOutputs=*/true); + + // Remove the StreamDiagConsumer as it's no longer needed. + Diags.removeConsumer(DiagConsumer); + + if (HadError) { + Error = std::string(ErrOS.str()); + return true; + } + + Invocation.getFrontendOptions().InputsAndOutputs = + resolveSymbolicLinksInInputs( + Invocation.getFrontendOptions().InputsAndOutputs, + UnresolvedPrimaryFile, FileSystem, Error); + if (!Error.empty()) + return true; + + ClangImporterOptions &ImporterOpts = Invocation.getClangImporterOptions(); + ImporterOpts.DetailedPreprocessingRecord = true; + + assert(!Invocation.getModuleName().empty()); + + auto &LangOpts = Invocation.getLangOptions(); + LangOpts.AttachCommentsToDecls = true; + LangOpts.DiagnosticsEditorMode = true; + LangOpts.CollectParsedToken = true; + if (LangOpts.PlaygroundTransform) { + // The playground instrumenter changes the AST in ways that disrupt the + // SourceKit functionality. Since we don't need the instrumenter, and all we + // actually need is the playground semantics visible to the user, like + // silencing the "expression resolves to an unused l-value" error, disable it. + LangOpts.PlaygroundTransform = false; + } + + // Disable the index-store functionality for the sourcekitd requests. + auto &FrontendOpts = Invocation.getFrontendOptions(); + FrontendOpts.IndexStorePath.clear(); + ImporterOpts.IndexStorePath.clear(); + + // Force the action type to be -typecheck. This affects importing the + // SwiftONoneSupport module. + FrontendOpts.RequestedAction = FrontendOptions::ActionType::Typecheck; + + // We don't care about LLVMArgs + FrontendOpts.LLVMArgs.clear(); + + // SwiftSourceInfo files provide source location information for decls coming + // from loaded modules. For most IDE use cases it either has an undesirable + // impact on performance with no benefit (code completion), results in stale + // locations being used instead of more up-to-date indexer locations (cursor + // info), or has no observable effect (diagnostics, which are filtered to just + // those with a location in the primary file, and everything else). + if (shouldOptimizeForIDE) + FrontendOpts.IgnoreSwiftSourceInfo = true; + + // To save the time for module validation, consider the lifetime of ASTManager + // as a single build session. + // NOTE: Do this only if '-disable-modules-validate-system-headers' is *not* + // explicitly enabled. + auto &SearchPathOpts = Invocation.getSearchPathOptions(); + if (!SearchPathOpts.DisableModulesValidateSystemDependencies) { + // NOTE: 'SessionTimestamp - 1' because clang compares it with '<=' that may + // cause unnecessary validations if they happens within one second + // from the SourceKit startup. + ImporterOpts.ExtraArgs.push_back("-fbuild-session-timestamp=" + + std::to_string(sessionTimestamp - 1)); + ImporterOpts.ExtraArgs.push_back( + "-fmodules-validate-once-per-build-session"); + + SearchPathOpts.DisableModulesValidateSystemDependencies = true; + } + + // Disable expensive SIL options to reduce time spent in SILGen. + disableExpensiveSILOptions(Invocation.getSILOptions()); + + return false; +} + // Adjust the cc1 triple string we got from clang, to make sure it will be // accepted when it goes through the swift clang importer. static std::string adjustClangTriple(StringRef TripleStr) { diff --git a/lib/IRGen/GenArchetype.cpp b/lib/IRGen/GenArchetype.cpp index 84f9c98b2e55e..c81255520af49 100644 --- a/lib/IRGen/GenArchetype.cpp +++ b/lib/IRGen/GenArchetype.cpp @@ -284,8 +284,7 @@ const TypeInfo *TypeConverter::convertArchetypeType(ArchetypeType *archetype) { // If the archetype is class-constrained, use a class pointer // representation. - if (archetype->requiresClass() || - (layout && layout->isRefCounted())) { + if (layout && layout->isRefCounted()) { auto refcount = archetype->getReferenceCounting(); llvm::PointerType *reprTy; diff --git a/lib/IRGen/GenClangType.cpp b/lib/IRGen/GenClangType.cpp index bc788fab6904a..8bc35dd99c134 100644 --- a/lib/IRGen/GenClangType.cpp +++ b/lib/IRGen/GenClangType.cpp @@ -132,10 +132,10 @@ namespace { /// ABI. class GenClangType : public CanTypeVisitor { IRGenModule &IGM; - ClangTypeConverter &Converter; + irgen::ClangTypeConverter &Converter; public: - GenClangType(IRGenModule &IGM, ClangTypeConverter &converter) + GenClangType(IRGenModule &IGM, irgen::ClangTypeConverter &converter) : IGM(IGM), Converter(converter) {} const clang::ASTContext &getClangASTContext() const { @@ -264,8 +264,8 @@ static clang::CanQualType getClangBuiltinTypeFromTypedef( } clang::CanQualType -ClangTypeConverter::reverseBuiltinTypeMapping(IRGenModule &IGM, - CanStructType type) { +irgen::ClangTypeConverter::reverseBuiltinTypeMapping(IRGenModule &IGM, + CanStructType type) { // Handle builtin types by adding entries to the cache that reverse // the mapping done by the importer. We could try to look at the // members of the struct instead, but even if that's ABI-equivalent @@ -748,7 +748,7 @@ clang::CanQualType GenClangType::visitType(CanType type) { llvm_unreachable("Unexpected type in Clang type generation."); } -clang::CanQualType ClangTypeConverter::convert(IRGenModule &IGM, CanType type) { +clang::CanQualType irgen::ClangTypeConverter::convert(IRGenModule &IGM, CanType type) { // Look in the cache. auto it = Cache.find(type); if (it != Cache.end()) { diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 5029660d88834..fb6dde89cc7ad 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -1164,18 +1164,32 @@ void IRGenerator::emitTypeMetadataRecords() { } } +static void +deleteAndReenqueueForEmissionValuesDependentOnCanonicalPrespecializedMetadataRecords( + IRGenModule &IGM, CanType typeWithCanonicalMetadataPrespecialization, + NominalTypeDecl &decl) { + IGM.IRGen.noteLazyReemissionOfNominalTypeDescriptor(&decl); + // The type context descriptor depends on canonical metadata records because + // pointers to them are attached as trailing objects to it. + // + // Don't call + // + // noteUseOfTypeContextDescriptor + // + // here because we don't want to reemit metadata. + emitLazyTypeContextDescriptor(IGM, &decl, RequireMetadata); +} + /// Emit any lazy definitions (of globals or functions or whatever /// else) that we require. void IRGenerator::emitLazyDefinitions() { while (!LazyTypeMetadata.empty() || !LazySpecializedTypeMetadataRecords.empty() || !LazyTypeContextDescriptors.empty() || - !LazyOpaqueTypeDescriptors.empty() || - !LazyFieldDescriptors.empty() || - !LazyFunctionDefinitions.empty() || - !LazyWitnessTables.empty() || - !LazyCanonicalSpecializedMetadataAccessors.empty()) { - + !LazyOpaqueTypeDescriptors.empty() || !LazyFieldDescriptors.empty() || + !LazyFunctionDefinitions.empty() || !LazyWitnessTables.empty() || + !LazyCanonicalSpecializedMetadataAccessors.empty() || + !LazyMetadataAccessors.empty()) { // Emit any lazy type metadata we require. while (!LazyTypeMetadata.empty()) { NominalTypeDecl *type = LazyTypeMetadata.pop_back_val(); @@ -1187,10 +1201,23 @@ void IRGenerator::emitLazyDefinitions() { emitLazyTypeMetadata(*IGM.get(), type); } while (!LazySpecializedTypeMetadataRecords.empty()) { - CanType type = LazySpecializedTypeMetadataRecords.pop_back_val(); - auto *nominal = type->getNominalOrBoundGenericNominal(); - CurrentIGMPtr IGM = getGenModule(nominal->getDeclContext()); - emitLazySpecializedGenericTypeMetadata(*IGM.get(), type); + CanType theType; + TypeMetadataCanonicality canonicality; + std::tie(theType, canonicality) = + LazySpecializedTypeMetadataRecords.pop_back_val(); + auto *nominal = theType->getNominalOrBoundGenericNominal(); + CurrentIGMPtr IGMPtr = getGenModule(nominal->getDeclContext()); + auto &IGM = *IGMPtr.get(); + // A new canonical prespecialized metadata changes both the type + // descriptor (adding a new entry to the trailing list of metadata) and + // the metadata accessor (adding a new list of generic arguments against + // which to compare the arguments to the function). Consequently, it is + // necessary to force these to be reemitted. + if (canonicality == TypeMetadataCanonicality::Canonical) { + deleteAndReenqueueForEmissionValuesDependentOnCanonicalPrespecializedMetadataRecords( + IGM, theType, *nominal); + } + emitLazySpecializedGenericTypeMetadata(IGM, theType); } while (!LazyTypeContextDescriptors.empty()) { NominalTypeDecl *type = LazyTypeContextDescriptors.pop_back_val(); @@ -1236,17 +1263,25 @@ void IRGenerator::emitLazyDefinitions() { LazyCanonicalSpecializedMetadataAccessors.pop_back_val(); auto *nominal = theType->getAnyNominal(); assert(nominal); + CurrentIGMPtr IGMPtr = getGenModule(nominal->getDeclContext()); + auto &IGM = *IGMPtr.get(); + // TODO: Once non-canonical accessors are available, this variable should + // reflect the canonicality of the accessor rather than always being + // canonical. + auto canonicality = TypeMetadataCanonicality::Canonical; + if (canonicality == TypeMetadataCanonicality::Canonical) { + deleteAndReenqueueForEmissionValuesDependentOnCanonicalPrespecializedMetadataRecords( + IGM, theType, *nominal); + } + emitLazyCanonicalSpecializedMetadataAccessor(IGM, theType); + } + while (!LazyMetadataAccessors.empty()) { + NominalTypeDecl *nominal = LazyMetadataAccessors.pop_back_val(); CurrentIGMPtr IGM = getGenModule(nominal->getDeclContext()); - emitLazyCanonicalSpecializedMetadataAccessor(*IGM.get(), theType); + emitLazyMetadataAccessor(*IGM.get(), nominal); } } - while (!LazyMetadataAccessors.empty()) { - NominalTypeDecl *nominal = LazyMetadataAccessors.pop_back_val(); - CurrentIGMPtr IGM = getGenModule(nominal->getDeclContext()); - emitLazyMetadataAccessor(*IGM.get(), nominal); - } - FinishedEmittingLazyDefinitions = true; } @@ -1442,17 +1477,19 @@ static bool typeKindCanBePrespecialized(TypeKind theKind) { } } -void IRGenerator::noteUseOfSpecializedGenericTypeMetadata(CanType type) { - assert(typeKindCanBePrespecialized(type->getKind())); - auto key = type->getAnyNominal(); +void IRGenerator::noteUseOfSpecializedGenericTypeMetadata( + IRGenModule &IGM, CanType theType, TypeMetadataCanonicality canonicality) { + assert(typeKindCanBePrespecialized(theType->getKind())); + auto key = theType->getAnyNominal(); assert(key); assert(key->isGenericContext()); - auto &enqueuedSpecializedTypes = CanonicalSpecializationsForGenericTypes[key]; + auto &enqueuedSpecializedTypes = + MetadataPrespecializationsForGenericTypes[key]; if (llvm::all_of(enqueuedSpecializedTypes, - [&](CanType enqueued) { return enqueued != type; })) { + [&](auto enqueued) { return enqueued.first != theType; })) { assert(!FinishedEmittingLazyDefinitions); - LazySpecializedTypeMetadataRecords.push_back(type); - enqueuedSpecializedTypes.push_back(type); + LazySpecializedTypeMetadataRecords.push_back({theType, canonicality}); + enqueuedSpecializedTypes.push_back({theType, canonicality}); } } @@ -2024,8 +2061,10 @@ llvm::Function *irgen::createFunction(IRGenModule &IGM, IGM.Module.getFunctionList().push_back(fn); } - ApplyIRLinkage({linkInfo.getLinkage(), linkInfo.getVisibility(), linkInfo.getDLLStorage()}) - .to(fn); + ApplyIRLinkage({linkInfo.getLinkage(), + linkInfo.getVisibility(), + linkInfo.getDLLStorage()}) + .to(fn, linkInfo.isForDefinition()); llvm::AttrBuilder initialAttrs; IGM.constructInitialFnAttributes(initialAttrs, FuncOptMode); @@ -2082,7 +2121,7 @@ llvm::GlobalVariable *swift::irgen::createVariable( ApplyIRLinkage({linkInfo.getLinkage(), linkInfo.getVisibility(), linkInfo.getDLLStorage()}) - .to(var); + .to(var, linkInfo.isForDefinition()); var->setAlignment(llvm::MaybeAlign(alignment.getValue())); // Everything externally visible is considered used in Swift. @@ -3864,6 +3903,19 @@ llvm::GlobalValue *IRGenModule::defineAlias(LinkEntity entity, if (entry) { auto existingVal = cast(entry); + for (auto iterator = std::begin(LLVMUsed); iterator < std::end(LLVMUsed); ++iterator) { + llvm::Value *thisValue = *iterator; + if (thisValue == existingVal) { + LLVMUsed.erase(iterator); + } + } + for (auto iterator = std::begin(LLVMCompilerUsed); iterator < std::end(LLVMCompilerUsed); ++iterator) { + llvm::Value *thisValue = *iterator; + if (thisValue == existingVal) { + LLVMCompilerUsed.erase(iterator); + } + } + // FIXME: MC breaks when emitting alias references on some platforms // (rdar://problem/22450593 ). Work around this by referring to the aliasee // instead. @@ -3902,32 +3954,14 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType, return cast(addr); } - /// For concrete metadata, we want to use the initializer on the - /// "full metadata", and define the "direct" address point as an alias. - TypeMetadataAddress addrKind; - unsigned adjustmentIndex; - - auto nominal = concreteType->getAnyNominal(); - - // Native Swift class metadata has a destructor before the address point. - // Foreign class metadata candidates do not, and neither does value type - // metadata. - if (nominal && isa(nominal) && - !requiresForeignTypeMetadata(nominal)) { - addrKind = TypeMetadataAddress::FullMetadata; - adjustmentIndex = MetadataAdjustmentIndex::Class; - } else { - addrKind = TypeMetadataAddress::FullMetadata; - adjustmentIndex = MetadataAdjustmentIndex::ValueType; - } - auto entity = (isPrespecialized && !irgen::isCanonicalInitializableTypeMetadataStaticallyAddressable( *this, concreteType)) ? LinkEntity::forNoncanonicalSpecializedGenericTypeMetadata( concreteType) - : LinkEntity::forTypeMetadata(concreteType, addrKind); + : LinkEntity::forTypeMetadata(concreteType, + TypeMetadataAddress::FullMetadata); auto DbgTy = DebugTypeInfo::getMetadata(MetatypeType::get(concreteType), entity.getDefaultDeclarationType(*this)->getPointerTo(), @@ -3945,30 +3979,35 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType, if (link.isUsed()) addUsedGlobal(var); - // Keep type metadata around for all types. - if (nominal) + /// For concrete metadata, we want to use the initializer on the + /// "full metadata", and define the "direct" address point as an alias. + unsigned adjustmentIndex = MetadataAdjustmentIndex::ValueType; + + if (auto nominal = concreteType->getAnyNominal()) { + // Keep type metadata around for all types. addRuntimeResolvableType(nominal); - // Don't define the alias for foreign type metadata or prespecialized generic - // metadata, since neither is ABI. - if ((nominal && requiresForeignTypeMetadata(nominal)) || isPrespecialized) - return var; + // Don't define the alias for foreign type metadata or prespecialized + // generic metadata, since neither is ABI. + if (requiresForeignTypeMetadata(nominal) || isPrespecialized) + return var; - // For concrete metadata, declare the alias to its address point. - auto directEntity = LinkEntity::forTypeMetadata(concreteType, - TypeMetadataAddress::AddressPoint); + // Native Swift class metadata has a destructor before the address point. + if (isa(nominal)) { + adjustmentIndex = MetadataAdjustmentIndex::Class; + } + } - llvm::Constant *addr = var; - // Do an adjustment if necessary. - if (adjustmentIndex) { - llvm::Constant *indices[] = { + llvm::Constant *indices[] = { llvm::ConstantInt::get(Int32Ty, 0), - llvm::ConstantInt::get(Int32Ty, adjustmentIndex) - }; - addr = llvm::ConstantExpr::getInBoundsGetElementPtr(/*Ty=*/nullptr, - addr, indices); - } + llvm::ConstantInt::get(Int32Ty, adjustmentIndex)}; + auto addr = llvm::ConstantExpr::getInBoundsGetElementPtr(/*Ty=*/nullptr, var, + indices); addr = llvm::ConstantExpr::getBitCast(addr, TypeMetadataPtrTy); + + // For concrete metadata, declare the alias to its address point. + auto directEntity = LinkEntity::forTypeMetadata( + concreteType, TypeMetadataAddress::AddressPoint); return defineAlias(directEntity, addr); } @@ -3989,15 +4028,17 @@ IRGenModule::getAddrOfTypeMetadata(CanType concreteType, auto nominal = concreteType->getAnyNominal(); - llvm::Type *defaultVarTy; - unsigned adjustmentIndex; - bool foreign = nominal && requiresForeignTypeMetadata(nominal); + + // Foreign classes and prespecialized generic types do not use an alias into + // the full metadata and therefore require a GEP. bool fullMetadata = foreign || (concreteType->getAnyGeneric() && concreteType->getAnyGeneric()->isGenericContext()); - // Foreign classes reference the full metadata with a GEP. + llvm::Type *defaultVarTy; + unsigned adjustmentIndex; + if (fullMetadata) { defaultVarTy = FullTypeMetadataStructTy; if (concreteType->getClassOrBoundGenericClass() && !foreign) { @@ -4005,9 +4046,9 @@ IRGenModule::getAddrOfTypeMetadata(CanType concreteType, } else { adjustmentIndex = MetadataAdjustmentIndex::ValueType; } - // The symbol for other nominal type metadata is generated at the address - // point. } else if (nominal) { + // The symbol for native non-generic nominal type metadata is generated at + // the aliased address point (see defineTypeMetadata() above). assert(!nominal->hasClangNode()); defaultVarTy = TypeMetadataStructTy; @@ -4030,7 +4071,8 @@ IRGenModule::getAddrOfTypeMetadata(CanType concreteType, if (shouldPrespecializeGenericMetadata()) { if (auto nominal = concreteType->getAnyNominal()) { if (nominal->isGenericContext()) { - IRGen.noteUseOfSpecializedGenericTypeMetadata(concreteType); + IRGen.noteUseOfSpecializedGenericTypeMetadata(*this, concreteType, + canonicality); } } } @@ -4040,13 +4082,9 @@ IRGenModule::getAddrOfTypeMetadata(CanType concreteType, switch (canonicality) { case TypeMetadataCanonicality::Canonical: - if (fullMetadata) { - entity = LinkEntity::forTypeMetadata(concreteType, - TypeMetadataAddress::FullMetadata); - } else { - entity = LinkEntity::forTypeMetadata(concreteType, - TypeMetadataAddress::AddressPoint); - } + entity = LinkEntity::forTypeMetadata( + concreteType, fullMetadata ? TypeMetadataAddress::FullMetadata + : TypeMetadataAddress::AddressPoint); break; case TypeMetadataCanonicality::Noncanonical: entity = @@ -4753,7 +4791,7 @@ IRGenModule::getAddrOfWitnessTableLazyAccessFunction( LinkInfo link = LinkInfo::get(*this, entity, forDefinition); entry = createFunction(*this, link, signature); ApplyIRLinkage({link.getLinkage(), link.getVisibility(), link.getDLLStorage()}) - .to(entry); + .to(entry, link.isForDefinition()); return entry; } diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp index d0577f975b1fc..19af4890b3bc0 100644 --- a/lib/IRGen/GenKeyPath.cpp +++ b/lib/IRGen/GenKeyPath.cpp @@ -1334,7 +1334,7 @@ void IRGenModule::emitSILProperty(SILProperty *prop) { ApplyIRLinkage({linkInfo.getLinkage(), linkInfo.getVisibility(), llvm::GlobalValue::DLLExportStorageClass}) - .to(GA); + .to(GA, linkInfo.isForDefinition()); } return; } diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 9d28264fec78f..076cc1bea41a1 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -300,7 +300,13 @@ static void buildMethodDescriptorFields(IRGenModule &IGM, void IRGenModule::emitNonoverriddenMethodDescriptor(const SILVTable *VTable, SILDeclRef declRef) { - + auto entity = LinkEntity::forMethodDescriptor(declRef); + auto *var = cast(getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo())); + if (!var->isDeclaration()) { + assert(IRGen.isLazilyReemittingNominalTypeDescriptor(VTable->getClass())); + return; + } + ConstantInitBuilder ib(*this); ConstantStructBuilder sb(ib.beginStruct(MethodDescriptorStructTy)); @@ -308,7 +314,6 @@ void IRGenModule::emitNonoverriddenMethodDescriptor(const SILVTable *VTable, auto init = sb.finishAndCreateFuture(); - auto entity = LinkEntity::forMethodDescriptor(declRef); getAddrOfLLVMVariable(entity, init, DebugTypeInfo()); } @@ -1215,6 +1220,7 @@ namespace { void setCommonFlags(TypeContextDescriptorFlags &flags) { setClangImportedFlags(flags); setMetadataInitializationKind(flags); + setHasCanonicalMetadataPrespecializations(flags); } void setClangImportedFlags(TypeContextDescriptorFlags &flags) { @@ -1248,6 +1254,19 @@ namespace { flags.setMetadataInitialization(MetadataInitialization); } + void setHasCanonicalMetadataPrespecializations(TypeContextDescriptorFlags &flags) { + flags.setHasCanonicalMetadataPrespecializations(hasCanonicalMetadataPrespecializations()); + } + + bool hasCanonicalMetadataPrespecializations() { + return IGM.shouldPrespecializeGenericMetadata() && + llvm::any_of(IGM.IRGen.metadataPrespecializationsForType(Type), + [](auto pair) { + return pair.second == + TypeMetadataCanonicality::Canonical; + }); + } + void maybeAddMetadataInitialization() { switch (MetadataInitialization) { case TypeContextDescriptorFlags::NoMetadataInitialization: @@ -1307,6 +1326,28 @@ namespace { addIncompleteMetadata(); } + void maybeAddCanonicalMetadataPrespecializations() { + if (Type->isGenericContext() && hasCanonicalMetadataPrespecializations()) { + asImpl().addCanonicalMetadataPrespecializations(); + } + } + + void addCanonicalMetadataPrespecializations() { + auto specializations = IGM.IRGen.metadataPrespecializationsForType(Type); + auto count = llvm::count_if(specializations, [](auto pair) { + return pair.second == TypeMetadataCanonicality::Canonical; + }); + B.addInt32(count); + for (auto pair : specializations) { + if (pair.second != TypeMetadataCanonicality::Canonical) { + continue; + } + auto specialization = pair.first; + auto *metadata = IGM.getAddrOfTypeMetadata(specialization); + B.addRelativeAddress(metadata); + } + } + // Subclasses should provide: // ContextDescriptorKind getContextKind(); // void addLayoutInfo(); @@ -1334,6 +1375,11 @@ namespace { FieldVectorOffset = layout.getFieldOffsetVectorOffset().getStatic(); } + void layout() { + super::layout(); + maybeAddCanonicalMetadataPrespecializations(); + } + ContextDescriptorKind getContextKind() { return ContextDescriptorKind::Struct; } @@ -1394,6 +1440,11 @@ namespace { if (layout.hasPayloadSizeOffset()) PayloadSizeOffset = layout.getPayloadSizeOffset().getStatic(); } + + void layout() { + super::layout(); + maybeAddCanonicalMetadataPrespecializations(); + } ContextDescriptorKind getContextKind() { return ContextDescriptorKind::Enum; @@ -1508,6 +1559,7 @@ namespace { addVTable(); addOverrideTable(); addObjCResilientClassStubInfo(); + maybeAddCanonicalMetadataPrespecializations(); } void addIncompleteMetadataOrRelocationFunction() { @@ -1780,6 +1832,19 @@ namespace { getType(), NotForDefinition, TypeMetadataAddress::AddressPoint)); } + + void addCanonicalMetadataPrespecializations() { + super::addCanonicalMetadataPrespecializations(); + auto specializations = IGM.IRGen.metadataPrespecializationsForType(Type); + for (auto pair : specializations) { + if (pair.second != TypeMetadataCanonicality::Canonical) { + continue; + } + auto specialization = pair.first; + auto *function = IGM.getAddrOfCanonicalSpecializedGenericTypeMetadataAccessFunction(specialization, NotForDefinition); + B.addRelativeAddress(function); + } + } }; class OpaqueTypeDescriptorBuilder @@ -3635,7 +3700,7 @@ static void emitObjCClassSymbol(IRGenModule &IGM, ptrTy->getElementType(), ptrTy->getAddressSpace(), link.getLinkage(), link.getName(), metadata, &IGM.Module); ApplyIRLinkage({link.getLinkage(), link.getVisibility(), link.getDLLStorage()}) - .to(alias); + .to(alias, link.isForDefinition()); } /// Emit the type metadata or metadata template for a class. diff --git a/lib/IRGen/GenThunk.cpp b/lib/IRGen/GenThunk.cpp index 74d862df8d567..c3bc0844433ce 100644 --- a/lib/IRGen/GenThunk.cpp +++ b/lib/IRGen/GenThunk.cpp @@ -102,6 +102,9 @@ static FunctionPointer lookupMethod(IRGenFunction &IGF, SILDeclRef declRef) { void IRGenModule::emitDispatchThunk(SILDeclRef declRef) { auto *f = getAddrOfDispatchThunk(declRef, ForDefinition); + if (!f->isDeclaration()) { + return; + } IRGenFunction IGF(*this, f); @@ -163,6 +166,10 @@ IRGenModule::getAddrOfMethodLookupFunction(ClassDecl *classDecl, void IRGenModule::emitMethodLookupFunction(ClassDecl *classDecl) { auto *f = getAddrOfMethodLookupFunction(classDecl, ForDefinition); + if (!f->isDeclaration()) { + assert(IRGen.isLazilyReemittingNominalTypeDescriptor(classDecl)); + return; + } IRGenFunction IGF(*this, f); diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index e1cd39d903dde..65387d02719d7 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -1571,6 +1571,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { case TypeKind::Unresolved: case TypeKind::LValue: case TypeKind::TypeVariable: + case TypeKind::Hole: case TypeKind::Module: case TypeKind::SILBlockStorage: case TypeKind::SILBox: diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h index 772301bd07e97..82590df971d01 100644 --- a/lib/IRGen/IRGenModule.h +++ b/lib/IRGen/IRGenModule.h @@ -192,6 +192,11 @@ enum RequireMetadata_t : bool { RequireMetadata = true }; +enum class TypeMetadataCanonicality : bool { + Noncanonical, + Canonical, +}; + /// The principal singleton which manages all of IR generation. /// /// The IRGenerator delegates the emission of different top-level entities @@ -259,17 +264,22 @@ class IRGenerator { /// queued up. llvm::SmallPtrSet LazilyEmittedFieldMetadata; - /// Maps every generic type that is specialized within the module to its - /// specializations. - llvm::DenseMap> - CanonicalSpecializationsForGenericTypes; + /// Maps every generic type whose metadata is specialized within the module + /// to its specializations. + llvm::DenseMap< + NominalTypeDecl *, + llvm::SmallVector, 4>> + MetadataPrespecializationsForGenericTypes; llvm::DenseMap> CanonicalSpecializedAccessorsForGenericTypes; /// The queue of specialized generic types whose prespecialized metadata to /// emit. - llvm::SmallVector LazySpecializedTypeMetadataRecords; + llvm::SmallVector, 4> + LazySpecializedTypeMetadataRecords; + + llvm::SmallPtrSet LazilyReemittedTypeContextDescriptors; /// The queue of metadata accessors to emit. /// @@ -423,9 +433,18 @@ class IRGenerator { void ensureRelativeSymbolCollocation(SILDefaultWitnessTable &wt); - llvm::SmallVector - canonicalSpecializationsForType(NominalTypeDecl *type) { - return CanonicalSpecializationsForGenericTypes.lookup(type); + llvm::SmallVector, 4> + metadataPrespecializationsForType(NominalTypeDecl *type) { + return MetadataPrespecializationsForGenericTypes.lookup(type); + } + + void noteLazyReemissionOfNominalTypeDescriptor(NominalTypeDecl *decl) { + LazilyReemittedTypeContextDescriptors.insert(decl); + } + + bool isLazilyReemittingNominalTypeDescriptor(NominalTypeDecl *decl) { + return LazilyReemittedTypeContextDescriptors.find(decl) != + std::end(LazilyReemittedTypeContextDescriptors); } void noteUseOfMetadataAccessor(NominalTypeDecl *decl) { @@ -438,7 +457,8 @@ class IRGenerator { noteUseOfTypeGlobals(type, true, RequireMetadata); } - void noteUseOfSpecializedGenericTypeMetadata(CanType type); + void noteUseOfSpecializedGenericTypeMetadata( + IRGenModule &IGM, CanType theType, TypeMetadataCanonicality canonicality); void noteUseOfCanonicalSpecializedMetadataAccessor(CanType forType); void noteUseOfTypeMetadata(CanType type) { @@ -547,11 +567,6 @@ enum class MangledTypeRefRole { DefaultAssociatedTypeWitness, }; -enum class TypeMetadataCanonicality : bool { - Noncanonical, - Canonical, -}; - /// IRGenModule - Primary class for emitting IR for global declarations. /// class IRGenModule { diff --git a/lib/IRGen/IRGenRequests.cpp b/lib/IRGen/IRGenRequests.cpp index 7cff6f7782837..85f9daae3058a 100644 --- a/lib/IRGen/IRGenRequests.cpp +++ b/lib/IRGen/IRGenRequests.cpp @@ -16,8 +16,8 @@ #include "swift/AST/Module.h" #include "swift/AST/SourceFile.h" #include "swift/SIL/SILModule.h" +#include "swift/AST/TBDGenRequests.h" #include "swift/Subsystems.h" -#include "swift/TBDGen/TBDGen.h" #include "llvm/IR/Module.h" #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h" diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index cd6a850512f27..48154c9678dcd 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -1937,12 +1937,12 @@ void IRGenSILFunction:: visitLinearFunctionExtractInst(LinearFunctionExtractInst *i) { unsigned structFieldOffset = i->getExtractee().rawValue; unsigned fieldSize = 1; - auto fnRepr = i->getFunctionOperand()->getType().getFunctionRepresentation(); + auto fnRepr = i->getOperand()->getType().getFunctionRepresentation(); if (fnRepr == SILFunctionTypeRepresentation::Thick) { structFieldOffset *= 2; fieldSize = 2; } - auto diffFnExp = getLoweredExplosion(i->getFunctionOperand()); + auto diffFnExp = getLoweredExplosion(i->getOperand()); assert(diffFnExp.size() == fieldSize * 2); Explosion e; e.add(diffFnExp.getRange(structFieldOffset, structFieldOffset + fieldSize)); diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp index 8ec81868638ce..2a509cbfeeb89 100644 --- a/lib/IRGen/LoadableByAddress.cpp +++ b/lib/IRGen/LoadableByAddress.cpp @@ -2862,7 +2862,7 @@ bool LoadableByAddress::recreateConvInstr(SILInstruction &I, case SILInstructionKind::LinearFunctionExtractInst: { auto instr = cast(convInstr); newInstr = convBuilder.createLinearFunctionExtract( - instr->getLoc(), instr->getExtractee(), instr->getFunctionOperand()); + instr->getLoc(), instr->getExtractee(), instr->getOperand()); break; } default: diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index 87a40476b5912..1efb72618069f 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -45,6 +45,7 @@ #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/IR/Constant.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FormatVariadic.h" #include @@ -845,57 +846,7 @@ bool irgen::isSpecializedNominalTypeMetadataStaticallyAddressable( return !isGenericWithoutPrespecializedConformance() && metadataAccessIsTrivial() && witnessTablesAreReferenceable(); }); - auto anyArgumentIsFromCurrentModule = - llvm::any_of(environment->getGenericParams(), [&](auto parameter) { - auto signature = environment->getGenericSignature(); - const auto protocols = signature->getRequiredProtocols(parameter); - auto argument = ((Type *)parameter)->subst(substitutions); - auto canonicalType = argument->getCanonicalType(); - - auto argumentIsFromCurrentModule = [&]() { - if (auto *argumentNominal = argument->getAnyNominal()) { - return IGM.getSwiftModule() == argumentNominal->getModuleContext(); - } - return false; - }; - auto anyConformanceIsFromCurrentModule = [&]() { - return llvm::any_of(protocols, [&](ProtocolDecl *protocol) { - auto conformance = - signature->lookupConformance(canonicalType, protocol); - if (!conformance.isConcrete()) { - return false; - } - auto rootConformance = - conformance.getConcrete()->getRootConformance(); - return IGM.getSwiftModule() == - rootConformance->getDeclContext()->getParentModule(); - }); - }; - - return argumentIsFromCurrentModule() || - anyConformanceIsFromCurrentModule(); - }); return allArgumentsAreStaticallyAddressable && - // A type's metadata cannot be prespecialized non-canonically if it - // could be specialized canonically. The reasons for that: - // (1) Canonically prespecialized metadata is not registered with the - // runtime; at runtime, whether canonically prespecialized - // metadata exists can only be determined by calling the metadata - // accessor. - // (2) At compile time, there is no way to determine whether the - // defining module has prespecialized metadata at a particular - // argument list. - // (3) Subsequent versions of the defining module may add or remove - // prespecialized metadata. - // - // To account for that, we only allow non-canonical prespecialization - // when at least one of the arguments is from the current module - // where non-canonical prespecialization might occur. Consequently, - // some prespecialization opportunities may be missed (such as when - // an argument comes from a module which it is known the defining - // module does not depend on). - !((canonicality == NoncanonicalSpecializedMetadata) && - !anyArgumentIsFromCurrentModule) && IGM.getTypeInfoForUnlowered(type).isFixedSize( ResilienceExpansion::Maximal); } @@ -2035,168 +1986,6 @@ IRGenFunction::emitGenericTypeMetadataAccessFunctionCall( return MetadataResponse::handle(*this, request, call); } -static void emitCanonicalSpecializationsForGenericTypeMetadataAccessFunction( - IRGenFunction &IGF, llvm::Value *request, NominalTypeDecl *nominal, - GenericArguments &genericArgs, - std::function valueAtIndex) { - auto &IGM = IGF.IGM; - auto specializations = IGF.IGM.IRGen.canonicalSpecializationsForType(nominal); - if (specializations.size() > 0) { - SmallVector conditionBlocks; - for (size_t index = 0; index < specializations.size(); ++index) { - conditionBlocks.push_back(llvm::BasicBlock::Create(IGM.getLLVMContext())); - } - - IGF.Builder.CreateBr(conditionBlocks[0]); - - SmallVector>, - 4> - specializationBlocks; - auto switchDestination = llvm::BasicBlock::Create(IGM.getLLVMContext()); - unsigned long blockIndex = 0; - for (auto specialization : specializations) { - auto conditionBlock = conditionBlocks[blockIndex]; - IGF.Builder.emitBlock(conditionBlock); - auto successorBlock = blockIndex < conditionBlocks.size() - 1 - ? conditionBlocks[blockIndex + 1] - : switchDestination; - auto specializationBlock = llvm::BasicBlock::Create(IGM.getLLVMContext()); - auto substitutions = specialization->getContextSubstitutionMap( - IGM.getSwiftModule(), nominal); - - llvm::Value *condition = llvm::ConstantInt::get(IGM.Int1Ty, 1); - auto nominal = specialization->getAnyNominal(); - auto requirements = GenericTypeRequirements(IGF.IGM, nominal); - int requirementIndex = 0; - for (auto requirement : requirements.getRequirements()) { - auto parameter = requirement.TypeParameter; - auto argument = parameter.subst(substitutions); - if (requirement.Protocol) { - auto conformance = substitutions.lookupConformance( - requirement.TypeParameter->getCanonicalType(), - requirement.Protocol); - ProtocolConformance *concreteConformance = conformance.getConcrete(); - auto argumentNominal = argument->getAnyNominal(); - if (argumentNominal && argumentNominal->isGenericContext()) { - // TODO: Statically specialize the witness table pattern for t's - // conformance. - llvm_unreachable( - "Statically specializing metadata at generic types is " - "not supported."); - } else { - RootProtocolConformance *rootConformance = - concreteConformance->getRootConformance(); - llvm::Value *expectedDescriptor = - IGF.IGM.getAddrOfProtocolConformanceDescriptor(rootConformance); - auto *witnessTable = valueAtIndex(requirementIndex); - auto *witnessBuffer = - IGF.Builder.CreateBitCast(witnessTable, IGM.Int8PtrPtrTy); - auto *uncastProvidedDescriptor = - IGF.Builder.CreateLoad(witnessBuffer, Alignment()); - auto *providedDescriptor = IGF.Builder.CreateBitCast( - uncastProvidedDescriptor, - IGM.ProtocolConformanceDescriptorPtrTy); - - // Auth the stored descriptor. - auto storedScheme = - IGF.IGM.getOptions().PointerAuth.ProtocolConformanceDescriptors; - if (storedScheme) { - auto authInfo = PointerAuthInfo::emit( - IGF, storedScheme, witnessTable, - PointerAuthEntity::Special::ProtocolConformanceDescriptor); - providedDescriptor = - emitPointerAuthAuth(IGF, providedDescriptor, authInfo); - } - - // Sign the descriptors. - auto argScheme = - IGF.IGM.getOptions() - .PointerAuth.ProtocolConformanceDescriptorsAsArguments; - if (argScheme) { - auto authInfo = PointerAuthInfo::emit( - IGF, argScheme, nullptr, - PointerAuthEntity::Special:: - ProtocolConformanceDescriptorAsArgument); - expectedDescriptor = - emitPointerAuthSign(IGF, expectedDescriptor, authInfo); - providedDescriptor = - emitPointerAuthSign(IGF, providedDescriptor, authInfo); - } - - auto *call = IGF.Builder.CreateCall( - IGF.IGM.getCompareProtocolConformanceDescriptorsFn(), - {providedDescriptor, expectedDescriptor}); - call->setDoesNotThrow(); - call->setCallingConv(IGF.IGM.SwiftCC); - call->addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::ReadNone); - condition = IGF.Builder.CreateAnd(condition, call); - } - } else { - llvm::Constant *addr = - IGM.getAddrOfTypeMetadata(argument->getCanonicalType()); - auto addrInt = IGF.Builder.CreateBitCast(addr, IGM.Int8PtrTy); - condition = IGF.Builder.CreateAnd( - condition, IGF.Builder.CreateICmpEQ( - addrInt, valueAtIndex(requirementIndex))); - } - ++requirementIndex; - } - IGF.Builder.CreateCondBr(condition, specializationBlock, successorBlock); - - auto responseBuilder = [](llvm::Value *request, CanType specialization, - IRGenFunction &IGF, IRGenModule &IGM) { - auto nominal = specialization->getAnyNominal(); - llvm::Value *specializedMetadata; - if (isa(nominal)) { - llvm::Function *accessor = - IGF.IGM - .getAddrOfCanonicalSpecializedGenericTypeMetadataAccessFunction( - specialization, NotForDefinition); - - specializedMetadata = - IGF.emitGenericTypeMetadataAccessFunctionCall( - accessor, {}, DynamicMetadataRequest(request)) - .getMetadata(); - } else { - specializedMetadata = IGM.getAddrOfTypeMetadata(specialization); - } - // Construct a MetadataResponse. It has three fields in the following - // order: - // - const Metadata *Metadata; - // - MetadataState (i32) StaticState; - llvm::Value *response = - llvm::UndefValue::get(IGM.TypeMetadataResponseTy); - response = IGF.Builder.CreateInsertValue( - response, specializedMetadata, 0, - "insert metadata address into response"); - auto state = MetadataResponse::getCompletedState(IGM); - response = IGF.Builder.CreateInsertValue( - response, state, 1, "insert metadata state into response"); - return response; - }; - specializationBlocks.push_back(std::make_tuple( - specializationBlock, specialization, responseBuilder)); - ++blockIndex; - } - - for (auto tuple : specializationBlocks) { - llvm::BasicBlock *block; - CanType type; - std::function - builder; - std::tie(block, type, builder) = tuple; - IGF.Builder.emitBlock(block); - IGF.Builder.CreateRet(builder(request, type, IGF, IGM)); - } - IGF.Builder.emitBlock(switchDestination); - } -} - MetadataResponse irgen::emitGenericTypeMetadataAccessFunction( IRGenFunction &IGF, Explosion ¶ms, NominalTypeDecl *nominal, GenericArguments &genericArgs) { @@ -2227,20 +2016,6 @@ MetadataResponse irgen::emitGenericTypeMetadataAccessFunction( llvm::Value *arguments = IGF.Builder.CreateBitCast(argsBuffer.getAddress(), IGM.Int8PtrTy); - llvm::Value *argumentsBuffer = - IGF.Builder.CreateBitCast(argsBuffer.getAddress(), IGM.Int8PtrPtrTy); - - emitCanonicalSpecializationsForGenericTypeMetadataAccessFunction( - IGF, request, nominal, genericArgs, [&](int index) { - llvm::Value *indexValue = llvm::ConstantInt::get(IGM.Int64Ty, index); - llvm::Value *elementPointer = - IGF.Builder.CreateGEP(argumentsBuffer, indexValue); - llvm::LoadInst *retval = IGF.Builder.CreateLoad( - elementPointer, Alignment(), - llvm::formatv("load argument at index {0} from buffer", index)); - return retval; - }); - // Make the call. auto call = IGF.Builder.CreateCall(IGM.getGetGenericMetadataFn(), {request, arguments, descriptor}); @@ -2319,12 +2094,6 @@ MetadataResponse irgen::emitGenericTypeMetadataAccessFunction( ? IGF.Builder.CreateBitCast(params.claimNext(), IGM.Int8PtrTy) : llvm::UndefValue::get(IGM.Int8PtrTy); - std::array argValues = {arg0, arg1, arg2}; - - emitCanonicalSpecializationsForGenericTypeMetadataAccessFunction( - IGF, request, nominal, genericArgs, - [&](int index) { return argValues[index]; }); - auto call = IGF.Builder.CreateCall(thunkFn, {request, arg0, arg1, arg2, descriptor}); call->setDoesNotAccessMemory(); diff --git a/lib/IRGen/ScalarTypeInfo.h b/lib/IRGen/ScalarTypeInfo.h index e3b0f3d03405b..4f9b843575580 100644 --- a/lib/IRGen/ScalarTypeInfo.h +++ b/lib/IRGen/ScalarTypeInfo.h @@ -117,10 +117,33 @@ class SingleScalarTypeInfo : public ScalarTypeInfo { schema.add(ExplosionSchema::Element::forScalar(ty)); } + void storeAsBytes(IRGenFunction &IGF, Explosion &src, Address addr) const { + auto &IGM = IGF.IGM; + + // Store in multiples of bytes to avoid undefined bits. + auto storageTy = addr.getAddress()->getType()->getPointerElementType(); + if (storageTy->isIntegerTy() && (storageTy->getIntegerBitWidth() % 8)) { + auto &Builder = IGF.Builder; + auto nextByteSize = (storageTy->getIntegerBitWidth() + 7) & ~7UL; + auto nextByteSizedIntTy = + llvm::IntegerType::get(IGM.getLLVMContext(), nextByteSize); + auto newAddr = + Address(Builder.CreatePointerCast(addr.getAddress(), + nextByteSizedIntTy->getPointerTo()), + addr.getAlignment()); + auto newValue = Builder.CreateZExt(src.claimNext(), nextByteSizedIntTy); + Builder.CreateStore(newValue, newAddr); + return; + } + + IGF.Builder.CreateStore(src.claimNext(), addr); + } + void initialize(IRGenFunction &IGF, Explosion &src, Address addr, bool isOutlined) const override { addr = asDerived().projectScalar(IGF, addr); - IGF.Builder.CreateStore(src.claimNext(), addr); + + storeAsBytes(IGF, src, addr); } void loadAsCopy(IRGenFunction &IGF, Address addr, @@ -149,8 +172,7 @@ class SingleScalarTypeInfo : public ScalarTypeInfo { } // Store. - llvm::Value *newValue = src.claimNext(); - IGF.Builder.CreateStore(newValue, dest); + storeAsBytes(IGF, src, dest); // Release the old value if we need to. if (!Derived::IsScalarPOD) { diff --git a/lib/Localization/CMakeLists.txt b/lib/Localization/CMakeLists.txt new file mode 100644 index 0000000000000..5de7c352be6c5 --- /dev/null +++ b/lib/Localization/CMakeLists.txt @@ -0,0 +1,6 @@ + +add_swift_host_library(swiftLocalization STATIC + LocalizationFormat.cpp + + LLVM_LINK_COMPONENTS + support) diff --git a/lib/AST/LocalizationFormat.cpp b/lib/Localization/LocalizationFormat.cpp similarity index 99% rename from lib/AST/LocalizationFormat.cpp rename to lib/Localization/LocalizationFormat.cpp index 5bc4f46cf5e64..750a43651301a 100644 --- a/lib/AST/LocalizationFormat.cpp +++ b/lib/Localization/LocalizationFormat.cpp @@ -14,7 +14,7 @@ // //===----------------------------------------------------------------------===// -#include "swift/AST/LocalizationFormat.h" +#include "swift/Localization/LocalizationFormat.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" diff --git a/lib/Migrator/APIDiffMigratorPass.cpp b/lib/Migrator/APIDiffMigratorPass.cpp index f99b28e07dc37..55d0948de6ad4 100644 --- a/lib/Migrator/APIDiffMigratorPass.cpp +++ b/lib/Migrator/APIDiffMigratorPass.cpp @@ -58,9 +58,10 @@ class ChildIndexFinder : public TypeReprVisitor { FoundResult findChild(AbstractFunctionDecl *Parent) { auto NextIndex = consumeNext(); if (!NextIndex) { - if (auto Func = dyn_cast(Parent)) - return findChild(Func->getBodyResultTypeLoc()); - if (auto Init = dyn_cast(Parent)) { + if (auto Func = dyn_cast(Parent)) { + if (auto *const TyRepr = Func->getResultTypeRepr()) + return visit(TyRepr); + } else if (auto Init = dyn_cast(Parent)) { SourceLoc End = Init->getFailabilityLoc(); bool Optional = End.isValid(); if (!Optional) @@ -73,7 +74,7 @@ class ChildIndexFinder : public TypeReprVisitor { for (auto *Param: *Parent->getParameters()) { if (!--NextIndex) { - return findChild(Param->getTypeRepr()); + return visit(Param->getTypeRepr()); } } llvm_unreachable("child index out of bounds"); @@ -100,12 +101,6 @@ class ChildIndexFinder : public TypeReprVisitor { return false; } - FoundResult findChild(TypeLoc Loc) { - if (!Loc.hasLocation()) - return {SourceRange(), false, false, false}; - return visit(Loc.getTypeRepr()); - } - public: template @@ -1257,7 +1252,7 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker { switch (DiffItem->DiffKind) { case NodeAnnotation::GetterToProperty: { auto FuncLoc = FD->getFuncLoc(); - auto ReturnTyLoc = FD->getBodyResultTypeLoc().getSourceRange().Start; + auto ReturnTyLoc = FD->getResultTypeSourceRange().Start; auto NameLoc = FD->getNameLoc(); if (FuncLoc.isInvalid() || ReturnTyLoc.isInvalid() || NameLoc.isInvalid()) break; diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp index 976b3b2aeee92..fef46453c959e 100644 --- a/lib/Parse/Lexer.cpp +++ b/lib/Parse/Lexer.cpp @@ -2706,12 +2706,12 @@ static SourceLoc getLocForStartOfTokenInBuf(SourceManager &SM, // Find the start of the given line. static const char *findStartOfLine(const char *bufStart, const char *current) { while (current != bufStart) { - if (current[0] == '\n' || current[0] == '\r') { + --current; + + if (current[0] == '\n') { ++current; break; } - - --current; } return current; @@ -2779,19 +2779,16 @@ SourceLoc Lexer::getLocForEndOfLine(SourceManager &SM, SourceLoc Loc) { if (BufferID < 0) return SourceLoc(); - // Use fake language options; language options only affect validity - // and the exact token produced. - LangOptions FakeLangOpts; + CharSourceRange entireRange = SM.getRangeForBuffer(BufferID); + StringRef Buffer = SM.extractText(entireRange); - // Here we return comments as tokens because either the caller skipped - // comments and normally we won't be at the beginning of a comment token - // (making this option irrelevant), or the caller lexed comments and - // we need to lex just the comment token. - Lexer L(FakeLangOpts, SM, BufferID, nullptr, LexerMode::Swift, - HashbangMode::Allowed, CommentRetentionMode::ReturnAsTokens); - L.restoreState(State(Loc)); - L.skipToEndOfLine(/*EatNewline=*/true); - return getSourceLoc(L.CurPtr); + // Windows line endings are \r\n. Since we want the start of the next + // line, just look for \n so the \r is skipped through. + size_t Offset = SM.getLocOffsetInBuffer(Loc, BufferID); + Offset = Buffer.find('\n', Offset); + if (Offset == StringRef::npos) + return SourceLoc(); + return getSourceLoc(Buffer.data() + Offset + 1); } StringRef Lexer::getIndentationForLine(SourceManager &SM, SourceLoc Loc, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 28f5e4c2989a9..ac374bee7e53b 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -5234,9 +5234,6 @@ static AccessorDecl *createAccessorFunc(SourceLoc DeclLoc, EndLoc); } - // The typechecker will always fill this in. - TypeLoc ReturnType; - // Start the function. auto *D = AccessorDecl::create(P->Context, /*FIXME FuncLoc=*/DeclLoc, @@ -5247,7 +5244,7 @@ static AccessorDecl *createAccessorFunc(SourceLoc DeclLoc, (GenericParams ? GenericParams->clone(P->CurDeclContext) : nullptr), - ValueArg, ReturnType, + ValueArg, Type(), P->CurDeclContext); return D; @@ -6248,15 +6245,12 @@ void Parser::consumeAbstractFunctionBody(AbstractFunctionDecl *AFD, AFD->setBodyDelayed(BodyRange); - if (isCodeCompletionFirstPass()) { - if (SourceMgr.rangeContainsCodeCompletionLoc(BodyRange)) { - State->setCodeCompletionDelayedDeclState( - SourceMgr, L->getBufferID(), - CodeCompletionDelayedDeclKind::FunctionBody, - PD_Default, AFD, BodyRange, BeginParserPosition.PreviousLoc); - } else { - AFD->setBodySkipped(BodyRange); - } + if (isCodeCompletionFirstPass() && + SourceMgr.rangeContainsCodeCompletionLoc(BodyRange)) { + State->setCodeCompletionDelayedDeclState( + SourceMgr, L->getBufferID(), + CodeCompletionDelayedDeclKind::FunctionBody, + PD_Default, AFD, BodyRange, BeginParserPosition.PreviousLoc); } } @@ -6448,10 +6442,9 @@ ParserResult Parser::parseDeclFunc(SourceLoc StaticLoc, return DCC.fixupParserResult(FD); } -/// Parse a function body for \p AFD and returns it without setting the body -/// to \p AFD . -ParserResult -Parser::parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD) { +/// Parse a function body for \p AFD, setting the body to \p AFD before +/// returning it. +BraceStmt *Parser::parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD) { assert(Tok.is(tok::l_brace)); // Enter the arguments for the function into a new function-body scope. We @@ -6479,13 +6472,70 @@ Parser::parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD) { CodeCompletion->completeAccessorBeginning(CCE); RBraceLoc = Tok.getLoc(); consumeToken(tok::code_complete); - return makeParserCodeCompletionResult( - BraceStmt::create(Context, LBraceLoc, ASTNode(CCE), RBraceLoc, - /*implicit*/ true)); + auto *BS = BraceStmt::create(Context, LBraceLoc, ASTNode(CCE), RBraceLoc, + /*implicit*/ true); + AFD->setBodyParsed(BS); + return BS; } } - return parseBraceItemList(diag::invalid_diagnostic); + ParserResult Body = parseBraceItemList(diag::invalid_diagnostic); + if (Body.isNull()) + return nullptr; + + BraceStmt *BS = Body.get(); + AFD->setBodyParsed(BS); + + // If the body consists of a single expression, turn it into a return + // statement. + // + // But don't do this transformation during code completion, as the source + // may be incomplete and the type mismatch in return statement will just + // confuse the type checker. + if (BS->getNumElements() != 1 || Body.hasCodeCompletion()) + return BS; + + auto Element = BS->getFirstElement(); + if (auto *stmt = Element.dyn_cast()) { + if (isa(AFD)) { + if (auto *returnStmt = dyn_cast(stmt)) { + if (!returnStmt->hasResult()) { + auto returnExpr = TupleExpr::createEmpty(Context, + SourceLoc(), + SourceLoc(), + /*implicit*/true); + returnStmt->setResult(returnExpr); + AFD->setHasSingleExpressionBody(); + AFD->setSingleExpressionBody(returnExpr); + } + } + } + } else if (auto *E = Element.dyn_cast()) { + if (auto SE = dyn_cast(E->getSemanticsProvidingExpr())) { + if (SE->getNumElements() > 1 && isa(SE->getElement(1))) { + // This is an assignment. We don't want to implicitly return + // it. + return BS; + } + } + if (isa(AFD)) { + auto RS = new (Context) ReturnStmt(SourceLoc(), E); + BS->setFirstElement(RS); + AFD->setHasSingleExpressionBody(); + AFD->setSingleExpressionBody(E); + } else if (auto *F = dyn_cast(AFD)) { + if (F->isFailable() && isa(E)) { + // If it's a nil literal, just insert return. This is the only + // legal thing to return. + auto RS = new (Context) ReturnStmt(E->getStartLoc(), E); + BS->setFirstElement(RS); + AFD->setHasSingleExpressionBody(); + AFD->setSingleExpressionBody(E); + } + } + } + + return BS; } /// Parse function body into \p AFD or skip it for delayed parsing. @@ -6510,60 +6560,7 @@ void Parser::parseAbstractFunctionBody(AbstractFunctionDecl *AFD) { } Scope S(this, ScopeKind::FunctionBody); - - ParserResult Body = parseAbstractFunctionBodyImpl(AFD); - if (!Body.isNull()) { - BraceStmt * BS = Body.get(); - AFD->setBodyParsed(BS); - - // If the body consists of a single expression, turn it into a return - // statement. - // - // But don't do this transformation during code completion, as the source - // may be incomplete and the type mismatch in return statement will just - // confuse the type checker. - if (!Body.hasCodeCompletion() && BS->getNumElements() == 1) { - auto Element = BS->getFirstElement(); - if (auto *stmt = Element.dyn_cast()) { - if (isa(AFD)) { - if (auto *returnStmt = dyn_cast(stmt)) { - if (!returnStmt->hasResult()) { - auto returnExpr = TupleExpr::createEmpty(Context, - SourceLoc(), - SourceLoc(), - /*implicit*/true); - returnStmt->setResult(returnExpr); - AFD->setHasSingleExpressionBody(); - AFD->setSingleExpressionBody(returnExpr); - } - } - } - } else if (auto *E = Element.dyn_cast()) { - if (auto SE = dyn_cast(E->getSemanticsProvidingExpr())) { - if (SE->getNumElements() > 1 && isa(SE->getElement(1))) { - // This is an assignment. We don't want to implicitly return - // it. - return; - } - } - if (isa(AFD)) { - auto RS = new (Context) ReturnStmt(SourceLoc(), E); - BS->setFirstElement(RS); - AFD->setHasSingleExpressionBody(); - AFD->setSingleExpressionBody(E); - } else if (auto *F = dyn_cast(AFD)) { - if (F->isFailable() && isa(E)) { - // If it's a nil literal, just insert return. This is the only - // legal thing to return. - auto RS = new (Context) ReturnStmt(E->getStartLoc(), E); - BS->setFirstElement(RS); - AFD->setHasSingleExpressionBody(); - AFD->setSingleExpressionBody(E); - } - } - } - } - } + (void)parseAbstractFunctionBodyImpl(AFD); } BraceStmt *Parser::parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD) { @@ -6595,7 +6592,7 @@ BraceStmt *Parser::parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD) { Scope TopLevelScope(this, ScopeKind::TopLevel); Scope S(this, ScopeKind::FunctionBody); - return parseAbstractFunctionBodyImpl(AFD).getPtrOrNull(); + return parseAbstractFunctionBodyImpl(AFD); } /// Parse a 'enum' declaration, returning true (and doing no token @@ -7269,12 +7266,9 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc, // Build an AST for the subscript declaration. DeclName name = DeclName(Context, DeclBaseName::createSubscript(), argumentNames); - auto *Subscript = new (Context) SubscriptDecl(name, - StaticLoc, StaticSpelling, - SubscriptLoc, Indices.get(), - ArrowLoc, ElementTy.get(), - CurDeclContext, - GenericParams); + auto *const Subscript = SubscriptDecl::create( + Context, name, StaticLoc, StaticSpelling, SubscriptLoc, Indices.get(), + ArrowLoc, ElementTy.get(), CurDeclContext, GenericParams); Subscript->getAttrs() = Attributes; // Let the source file track the opaque return type mapping, if any. diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index d7f77869d6723..7c753b4c2f226 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -330,7 +330,7 @@ ParserResult Parser::parseExprSequence(Diag<> Message, case tok::identifier: { // 'async' followed by 'throws' or '->' implies that we have an arrow // expression. - if (!(Context.LangOpts.EnableExperimentalConcurrency && + if (!(shouldParseExperimentalConcurrency() && Tok.isContextualKeyword("async") && peekToken().isAny(tok::arrow, tok::kw_throws))) goto done; @@ -379,7 +379,7 @@ ParserResult Parser::parseExprSequence(Diag<> Message, /// parseExprSequenceElement /// /// expr-sequence-element(Mode): -/// '__await' expr-sequence-element(Mode) +/// 'await' expr-sequence-element(Mode) /// 'try' expr-sequence-element(Mode) /// 'try' '?' expr-sequence-element(Mode) /// 'try' '!' expr-sequence-element(Mode) @@ -392,9 +392,8 @@ ParserResult Parser::parseExprSequenceElement(Diag<> message, SyntaxParsingContext ElementContext(SyntaxContext, SyntaxContextKind::Expr); - if (Context.LangOpts.EnableExperimentalConcurrency && - Tok.is(tok::kw___await)) { - SourceLoc awaitLoc = consumeToken(tok::kw___await); + if (shouldParseExperimentalConcurrency() && Tok.isContextualKeyword("await")) { + SourceLoc awaitLoc = consumeToken(); ParserResult sub = parseExprUnary(message, isExprBasic); if (!sub.hasCodeCompletion() && !sub.isNull()) { ElementContext.setCreateSyntax(SyntaxKind::AwaitExpr); @@ -803,8 +802,6 @@ ParserResult Parser::parseExprSelector() { parseExpr(selectorKind == ObjCSelectorExpr::Method ? diag::expr_selector_expected_method_expr : diag::expr_selector_expected_property_expr); - if (subExpr.hasCodeCompletion()) - return makeParserCodeCompletionResult(); // Parse the closing ')'. SourceLoc rParenLoc; @@ -820,7 +817,7 @@ ParserResult Parser::parseExprSelector() { } // If the subexpression was in error, just propagate the error. - if (subExpr.isParseError()) + if (subExpr.isParseError() && !subExpr.hasCodeCompletion()) return makeParserResult( new (Context) ErrorExpr(SourceRange(keywordLoc, rParenLoc))); @@ -1613,60 +1610,8 @@ ParserResult Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) { return makeParserErrorResult(new (Context) ErrorExpr(DotLoc)); SyntaxContext->createNodeInPlace(SyntaxKind::MemberAccessExpr); - // Check for a () suffix, which indicates a call when constructing - // this member. Note that this cannot be the start of a new line. - if (Tok.isFollowingLParen()) { - SourceLoc lParenLoc, rParenLoc; - SmallVector args; - SmallVector argLabels; - SmallVector argLabelLocs; - SmallVector trailingClosures; - - ParserStatus status = parseExprList(tok::l_paren, tok::r_paren, - /*isPostfix=*/true, isExprBasic, - lParenLoc, args, argLabels, - argLabelLocs, - rParenLoc, - trailingClosures, - SyntaxKind::TupleExprElementList); - SyntaxContext->createNodeInPlace(SyntaxKind::FunctionCallExpr); - return makeParserResult( - status, - UnresolvedMemberExpr::create(Context, DotLoc, NameLoc, Name, - lParenLoc, args, argLabels, - argLabelLocs, rParenLoc, - trailingClosures, - /*implicit=*/false)); - } - - // Check for a trailing closure, if allowed. - if (Tok.is(tok::l_brace) && isValidTrailingClosure(isExprBasic, *this)) { - if (SyntaxContext->isEnabled()) { - // Add dummy blank argument list to the call expression syntax. - SyntaxContext->addSyntax( - ParsedSyntaxRecorder::makeBlankTupleExprElementList( - leadingTriviaLoc(), *SyntaxContext)); - } - - SmallVector trailingClosures; - auto result = parseTrailingClosures(isExprBasic, NameLoc.getSourceRange(), - trailingClosures); - if (trailingClosures.empty()) - return nullptr; - - SyntaxContext->createNodeInPlace(SyntaxKind::FunctionCallExpr); - // Handle .foo by just making an AST node. - return makeParserResult( - result, UnresolvedMemberExpr::create(Context, DotLoc, NameLoc, Name, - SourceLoc(), {}, {}, {}, - SourceLoc(), trailingClosures, - /*implicit=*/false)); - } - - // Handle .foo by just making an AST node. - return makeParserResult( - UnresolvedMemberExpr::create(Context, DotLoc, NameLoc, Name, - /*implicit=*/false)); + return makeParserResult(new (Context) UnresolvedMemberExpr( + DotLoc, NameLoc, Name, /*implicit=*/false)); } case tok::kw_super: // 'super' @@ -2432,7 +2377,8 @@ bool Parser:: parseClosureSignatureIfPresent(SourceRange &bracketRange, SmallVectorImpl &captureList, VarDecl *&capturedSelfDecl, - ParameterList *¶ms, SourceLoc &throwsLoc, + ParameterList *¶ms, + SourceLoc &asyncLoc, SourceLoc &throwsLoc, SourceLoc &arrowLoc, TypeExpr *&explicitResultType, SourceLoc &inLoc){ // Clear out result parameters. @@ -2444,6 +2390,24 @@ parseClosureSignatureIfPresent(SourceRange &bracketRange, explicitResultType = nullptr; inLoc = SourceLoc(); + // Consume 'async', 'throws', and 'rethrows', but in any order. + auto consumeAsyncThrows = [&] { + bool hadAsync = false; + if (shouldParseExperimentalConcurrency() && + Tok.isContextualKeyword("async")) { + consumeToken(); + hadAsync = true; + } + + if (!consumeIf(tok::kw_throws) && !consumeIf(tok::kw_rethrows)) + return; + + if (shouldParseExperimentalConcurrency() && !hadAsync && + Tok.isContextualKeyword("async")) { + consumeToken(); + } + }; + // If we have a leading token that may be part of the closure signature, do a // speculative parse to validate it and look for 'in'. if (Tok.isAny(tok::l_paren, tok::l_square, tok::identifier, tok::kw__)) { @@ -2465,7 +2429,8 @@ parseClosureSignatureIfPresent(SourceRange &bracketRange, // Consume the ')', if it's there. if (consumeIf(tok::r_paren)) { - consumeIf(tok::kw_throws) || consumeIf(tok::kw_rethrows); + consumeAsyncThrows(); + // Parse the func-signature-result, if present. if (consumeIf(tok::arrow)) { if (!canParseType()) @@ -2485,8 +2450,8 @@ parseClosureSignatureIfPresent(SourceRange &bracketRange, return false; } - - consumeIf(tok::kw_throws) || consumeIf(tok::kw_rethrows); + + consumeAsyncThrows(); // Parse the func-signature-result, if present. if (consumeIf(tok::arrow)) { @@ -2682,11 +2647,10 @@ parseClosureSignatureIfPresent(SourceRange &bracketRange, params = ParameterList::create(Context, elements); } - - if (Tok.is(tok::kw_throws)) { - throwsLoc = consumeToken(); - } else if (Tok.is(tok::kw_rethrows)) { - throwsLoc = consumeToken(); + + bool rethrows = false; + parseAsyncThrows(SourceLoc(), asyncLoc, throwsLoc, &rethrows); + if (rethrows) { diagnose(throwsLoc, diag::rethrowing_function_type) .fixItReplace(throwsLoc, "throws"); } @@ -2803,13 +2767,14 @@ ParserResult Parser::parseExprClosure() { SmallVector captureList; VarDecl *capturedSelfDecl; ParameterList *params = nullptr; + SourceLoc asyncLoc; SourceLoc throwsLoc; SourceLoc arrowLoc; TypeExpr *explicitResultType; SourceLoc inLoc; - parseClosureSignatureIfPresent(bracketRange, captureList, - capturedSelfDecl, params, throwsLoc, - arrowLoc, explicitResultType, inLoc); + parseClosureSignatureIfPresent( + bracketRange, captureList, capturedSelfDecl, params, asyncLoc, throwsLoc, + arrowLoc, explicitResultType, inLoc); // If the closure was created in the context of an array type signature's // size expression, there will not be a local context. A parse error will @@ -2824,10 +2789,9 @@ ParserResult Parser::parseExprClosure() { unsigned discriminator = CurLocalContext->claimNextClosureDiscriminator(); // Create the closure expression and enter its context. - auto *closure = new (Context) ClosureExpr(bracketRange, capturedSelfDecl, - params, throwsLoc, arrowLoc, inLoc, - explicitResultType, discriminator, - CurDeclContext); + auto *closure = new (Context) ClosureExpr( + bracketRange, capturedSelfDecl, params, asyncLoc, throwsLoc, arrowLoc, + inLoc, explicitResultType, discriminator, CurDeclContext); // The arguments to the func are defined in their own scope. Scope S(this, ScopeKind::ClosureParams); ParseFunctionBody cc(*this, closure); diff --git a/lib/Parse/ParseIfConfig.cpp b/lib/Parse/ParseIfConfig.cpp index a1c260f1e38bd..4dd005cb9cef9 100644 --- a/lib/Parse/ParseIfConfig.cpp +++ b/lib/Parse/ParseIfConfig.cpp @@ -603,17 +603,42 @@ static Expr *findAnyLikelySimulatorEnvironmentTest(Expr *Condition) { /// Delegate callback function to parse elements in the blocks. ParserResult Parser::parseIfConfig( llvm::function_ref &, bool)> parseElements) { + assert(Tok.is(tok::pound_if)); SyntaxParsingContext IfConfigCtx(SyntaxContext, SyntaxKind::IfConfigDecl); SmallVector Clauses; Parser::StructureMarkerRAII ParsingDecl( *this, Tok.getLoc(), Parser::StructureMarkerKind::IfConfig); + // Find the region containing code completion token. + SourceLoc codeCompletionClauseLoc; + if (SourceMgr.hasCodeCompletionBuffer() && + SourceMgr.getCodeCompletionBufferID() == L->getBufferID() && + SourceMgr.isBeforeInBuffer(Tok.getLoc(), + SourceMgr.getCodeCompletionLoc())) { + llvm::SaveAndRestore> H(CurrentTokenHash, None); + BacktrackingScope backtrack(*this); + do { + auto startLoc = Tok.getLoc(); + consumeToken(); + skipUntilConditionalBlockClose(); + auto endLoc = PreviousLoc; + if (SourceMgr.rangeContainsTokenLoc(SourceRange(startLoc, endLoc), + SourceMgr.getCodeCompletionLoc())){ + codeCompletionClauseLoc = startLoc; + break; + } + } while (Tok.isNot(tok::pound_endif, tok::eof)); + } + bool shouldEvaluate = // Don't evaluate if it's in '-parse' mode, etc. shouldEvaluatePoundIfDecls() && // If it's in inactive #if ... #endif block, there's no point to do it. - !getScopeInfo().isInactiveConfigBlock(); + !getScopeInfo().isInactiveConfigBlock() && + // If this directive contains code completion location, 'isActive' is + // determined solely by which block has the completion token. + !codeCompletionClauseLoc.isValid(); bool foundActive = false; bool isVersionCondition = false; @@ -658,6 +683,10 @@ ParserResult Parser::parseIfConfig( } } + // Treat the region containing code completion token as "active". + if (codeCompletionClauseLoc.isValid() && !foundActive) + isActive = (ClauseLoc == codeCompletionClauseLoc); + foundActive |= isActive; if (!Tok.isAtStartOfLine() && Tok.isNot(tok::eof)) { diff --git a/lib/Parse/ParsePattern.cpp b/lib/Parse/ParsePattern.cpp index 06b75b7c2df5f..c98ea0c6f04da 100644 --- a/lib/Parse/ParsePattern.cpp +++ b/lib/Parse/ParsePattern.cpp @@ -130,8 +130,10 @@ static ParserStatus parseDefaultArgument( defaultArgs->HasDefaultArgument = true; - if (initR.hasCodeCompletion()) + if (initR.hasCodeCompletion()) { + init = initR.get(); return makeParserCodeCompletionStatus(); + } if (initR.isNull()) return makeParserError(); @@ -824,7 +826,7 @@ Parser::parseFunctionSignature(Identifier SimpleName, void Parser::parseAsyncThrows( SourceLoc existingArrowLoc, SourceLoc &asyncLoc, SourceLoc &throwsLoc, bool *rethrows) { - if (Context.LangOpts.EnableExperimentalConcurrency && + if (shouldParseExperimentalConcurrency() && Tok.isContextualKeyword("async")) { asyncLoc = consumeToken(); @@ -857,7 +859,7 @@ void Parser::parseAsyncThrows( .fixItInsert(existingArrowLoc, (keyword + " ").str()); } - if (Context.LangOpts.EnableExperimentalConcurrency && + if (shouldParseExperimentalConcurrency() && Tok.isContextualKeyword("async")) { asyncLoc = consumeToken(); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index a58f435d8dc1f..c4a64ca54973e 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -898,9 +898,7 @@ ParserResult Parser::parseStmtThrow(SourceLoc tryLoc) { exprLoc = Tok.getLoc(); ParserResult Result = parseExpr(diag::expected_expr_throw); - - if (Result.hasCodeCompletion()) - return makeParserCodeCompletionResult(); + bool hasCodeCompletion = Result.hasCodeCompletion(); if (Result.isNull()) Result = makeParserErrorResult(new (Context) ErrorExpr(throwLoc)); @@ -916,6 +914,9 @@ ParserResult Parser::parseStmtThrow(SourceLoc tryLoc) { Result = makeParserResult(new (Context) TryExpr(exprLoc, Result.get())); } + if (hasCodeCompletion) + Result.setHasCodeCompletion(); + return makeParserResult(Result, new (Context) ThrowStmt(throwLoc, Result.get())); } @@ -943,20 +944,12 @@ ParserResult Parser::parseStmtDefer() { // closure's DeclContext. auto params = ParameterList::createEmpty(Context); DeclName name(Context, Context.getIdentifier("$defer"), params); - auto tempDecl - = FuncDecl::create(Context, - /*StaticLoc=*/ SourceLoc(), - StaticSpellingKind::None, - /*FuncLoc=*/ SourceLoc(), - name, - /*NameLoc=*/ PreviousLoc, - /*Async=*/ false, /*AsyncLoc=*/ SourceLoc(), - /*Throws=*/ false, /*ThrowsLoc=*/ SourceLoc(), - /*generic params*/ nullptr, - params, - TypeLoc(), - CurDeclContext); - tempDecl->setImplicit(); + auto *const tempDecl = FuncDecl::createImplicit( + Context, StaticSpellingKind::None, name, /*NameLoc=*/PreviousLoc, + /*Async=*/false, + /*Throws=*/false, + /*GenericParams*/ nullptr, params, TupleType::getEmpty(Context), + CurDeclContext); setLocalDiscriminator(tempDecl); ParserStatus Status; { @@ -2020,9 +2013,6 @@ ParserResult Parser::parseStmtCatch() { GuardedPattern PatternResult; parseGuardedPattern(*this, PatternResult, status, boundDecls, GuardedPatternContext::Catch, isFirst); - if (status.hasCodeCompletion()) { - return makeParserCodeCompletionResult(); - } caseLabelItems.emplace_back(PatternResult.ThePattern, PatternResult.WhereLoc, PatternResult.Guard); isFirst = false; diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp index aefea2401c15a..8dc5795905458 100644 --- a/lib/Parse/ParseType.cpp +++ b/lib/Parse/ParseType.cpp @@ -412,7 +412,7 @@ ParserResult Parser::parseType(Diag<> MessageID, // Parse an async specifier. SourceLoc asyncLoc; - if (Context.LangOpts.EnableExperimentalConcurrency && + if (shouldParseExperimentalConcurrency() && Tok.isContextualKeyword("async")) { asyncLoc = consumeToken(); } @@ -423,7 +423,7 @@ ParserResult Parser::parseType(Diag<> MessageID, SourceLoc throwsLoc; if (Tok.isAny(tok::kw_throws, tok::kw_rethrows, tok::kw_throw, tok::kw_try) && (peekToken().is(tok::arrow) || - (Context.LangOpts.EnableExperimentalConcurrency && + (shouldParseExperimentalConcurrency() && peekToken().isContextualKeyword("async")))) { if (Tok.isAny(tok::kw_rethrows, tok::kw_throw, tok::kw_try)) { // 'rethrows' is only allowed on function declarations for now. @@ -436,7 +436,7 @@ ParserResult Parser::parseType(Diag<> MessageID, throwsLoc = consumeToken(); // 'async' must preceed 'throws'; accept this but complain. - if (Context.LangOpts.EnableExperimentalConcurrency && + if (shouldParseExperimentalConcurrency() && Tok.isContextualKeyword("async")) { asyncLoc = consumeToken(); @@ -1589,7 +1589,7 @@ bool Parser::canParseType() { } // Handle type-function if we have an 'async'. - if (Context.LangOpts.EnableExperimentalConcurrency && + if (shouldParseExperimentalConcurrency() && Tok.isContextualKeyword("async")) { consumeToken(); @@ -1605,7 +1605,7 @@ bool Parser::canParseType() { // Allow 'async' here even though it is ill-formed, so we can provide // a better error. - if (Context.LangOpts.EnableExperimentalConcurrency && + if (shouldParseExperimentalConcurrency() && Tok.isContextualKeyword("async")) consumeToken(); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 601527fa7ba19..25161aabaa9ee 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -203,7 +203,7 @@ void Parser::performCodeCompletionSecondPassImpl( case CodeCompletionDelayedDeclKind::FunctionBody: { auto *AFD = cast(DC); - AFD->setBodyParsed(parseAbstractFunctionBodyImpl(AFD).getPtrOrNull()); + (void)parseAbstractFunctionBodyImpl(AFD); break; } } @@ -695,8 +695,9 @@ void Parser::skipSingle() { void Parser::skipUntil(tok T1, tok T2) { // tok::NUM_TOKENS is a sentinel that means "don't skip". if (T1 == tok::NUM_TOKENS && T2 == tok::NUM_TOKENS) return; - - while (Tok.isNot(T1, T2, tok::eof, tok::pound_endif, tok::code_complete)) + + while (Tok.isNot(T1, T2, tok::eof, tok::pound_endif, tok::pound_else, + tok::pound_elseif)) skipSingle(); } diff --git a/lib/PrintAsObjC/DeclAndTypePrinter.cpp b/lib/PrintAsObjC/DeclAndTypePrinter.cpp index b848f04627854..4daa75d1faae5 100644 --- a/lib/PrintAsObjC/DeclAndTypePrinter.cpp +++ b/lib/PrintAsObjC/DeclAndTypePrinter.cpp @@ -1339,6 +1339,7 @@ class DeclAndTypePrinter::Implementation return true; } +public: /// If \p nominal is bridged to an Objective-C class (via a conformance to /// _ObjectiveCBridgeable), return that class. /// @@ -1369,6 +1370,7 @@ class DeclAndTypePrinter::Implementation return objcType->getClassOrBoundGenericClass(); } +private: /// If the nominal type is bridged to Objective-C (via a conformance /// to _ObjectiveCBridgeable), print the bridged type. void printObjCBridgeableType(const NominalTypeDecl *swiftNominal, @@ -1570,12 +1572,16 @@ class DeclAndTypePrinter::Implementation } bool printImportedAlias(const TypeAliasDecl *alias, + ArrayRef genericArgs, Optional optionalKind) { if (!alias->hasClangNode()) return false; if (auto *clangTypeDecl = dyn_cast(alias->getClangDecl())) { + assert(!alias->isGeneric() + && "generic typealias backed by clang typedecl?"); + maybePrintTagKeyword(alias); os << getNameForObjC(alias); @@ -1583,12 +1589,19 @@ class DeclAndTypePrinter::Implementation printNullability(optionalKind); } else if (auto *clangObjCClass = dyn_cast(alias->getClangDecl())){ + assert(!alias->isGeneric() + && "generic typealias backed by clang interface?"); + os << clangObjCClass->getName() << " *"; printNullability(optionalKind); } else { auto *clangCompatAlias = cast(alias->getClangDecl()); - os << clangCompatAlias->getName() << " *"; + + os << clangCompatAlias->getName(); + if (!genericArgs.empty()) + printGenericArgs(genericArgs); + os << " *"; printNullability(optionalKind); } @@ -1598,10 +1611,12 @@ class DeclAndTypePrinter::Implementation void visitTypeAliasType(TypeAliasType *aliasTy, Optional optionalKind) { const TypeAliasDecl *alias = aliasTy->getDecl(); + auto genericArgs = aliasTy->getDirectGenericArgs(); + if (printIfKnownSimpleType(alias, optionalKind)) return; - if (printImportedAlias(alias, optionalKind)) + if (printImportedAlias(alias, genericArgs, optionalKind)) return; visitPart(aliasTy->getSinglyDesugaredType(), optionalKind); @@ -1735,8 +1750,12 @@ class DeclAndTypePrinter::Implementation } void printGenericArgs(BoundGenericType *BGT) { + printGenericArgs(BGT->getGenericArgs()); + } + + void printGenericArgs(ArrayRef genericArgs) { os << '<'; - interleave(BGT->getGenericArgs(), + interleave(genericArgs, [this](Type t) { print(t, None); }, [this] { os << ", "; }); os << '>'; @@ -1890,7 +1909,7 @@ class DeclAndTypePrinter::Implementation assert(extension->getGenericSignature().getCanonicalSignature() == extendedClass->getGenericSignature().getCanonicalSignature() && "constrained extensions or custom generic parameters?"); - type = extendedClass->getGenericEnvironment()->getSugaredType(type); + type = extendedClass->getGenericSignature()->getSugaredType(type); decl = type->getDecl(); } @@ -2067,6 +2086,14 @@ bool DeclAndTypePrinter::isEmptyExtensionDecl(const ExtensionDecl *ED) { return getImpl().isEmptyExtensionDecl(ED); } +const TypeDecl *DeclAndTypePrinter::getObjCTypeDecl(const TypeDecl* TD) { + if (auto *nominal = dyn_cast(TD)) + if (auto *bridged = getImpl().getObjCBridgedClass(nominal)) + return bridged; + + return TD; +} + StringRef DeclAndTypePrinter::maybeGetOSObjectBaseName(const clang::NamedDecl *decl) { StringRef name = decl->getName(); diff --git a/lib/PrintAsObjC/DeclAndTypePrinter.h b/lib/PrintAsObjC/DeclAndTypePrinter.h index 933f2ea16a859..c7718faac3e6b 100644 --- a/lib/PrintAsObjC/DeclAndTypePrinter.h +++ b/lib/PrintAsObjC/DeclAndTypePrinter.h @@ -73,6 +73,14 @@ class DeclAndTypePrinter { /// Is \p ED empty of members and protocol conformances to include? bool isEmptyExtensionDecl(const ExtensionDecl *ED); + /// Returns the type that will be printed by PrintAsObjC for a parameter or + /// result type resolved to this declaration. + /// + /// \warning This handles \c _ObjectiveCBridgeable types, but it doesn't + /// currently know about other aspects of PrintAsObjC behavior, like known + /// types. + const TypeDecl *getObjCTypeDecl(const TypeDecl* TD); + /// Prints a category declaring the given members. /// /// All members must have the same parent type. The list must not be empty. diff --git a/lib/PrintAsObjC/ModuleContentsWriter.cpp b/lib/PrintAsObjC/ModuleContentsWriter.cpp index ba703f28937cc..b5b466c2210d0 100644 --- a/lib/PrintAsObjC/ModuleContentsWriter.cpp +++ b/lib/PrintAsObjC/ModuleContentsWriter.cpp @@ -16,6 +16,7 @@ #include "swift/AST/ExistentialLayout.h" #include "swift/AST/Module.h" +#include "swift/AST/PrettyStackTrace.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/SwiftNameTranslation.h" #include "swift/AST/TypeDeclFinder.h" @@ -56,7 +57,6 @@ class ReferencedTypeFinder : public TypeDeclFinder { Action visitTypeAliasType(TypeAliasType *aliasTy) override { if (aliasTy->getDecl()->hasClangNode() && !aliasTy->getDecl()->isCompatibilityAlias()) { - assert(!aliasTy->getDecl()->isGeneric()); Callback(*this, aliasTy->getDecl()); } else { Type(aliasTy->getSinglyDesugaredType()).walk(*this); @@ -235,6 +235,8 @@ class ModuleWriter { } bool forwardDeclareMemberTypes(DeclRange members, const Decl *container) { + PrettyStackTraceDecl + entry("printing forward declarations needed by members of", container); switch (container->getKind()) { case DeclKind::Class: case DeclKind::Protocol: @@ -247,6 +249,7 @@ class ModuleWriter { bool hadAnyDelayedMembers = false; SmallVector nestedTypes; for (auto member : members) { + PrettyStackTraceDecl loopEntry("printing for member", member); auto VD = dyn_cast(member); if (!VD || !printer.shouldInclude(VD)) continue; @@ -269,9 +272,14 @@ class ModuleWriter { ReferencedTypeFinder::walk(VD->getInterfaceType(), [&](ReferencedTypeFinder &finder, const TypeDecl *TD) { + PrettyStackTraceDecl + entry("walking its interface type, currently at", TD); if (TD == container) return; + // Bridge, if necessary. + TD = printer.getObjCTypeDecl(TD); + if (finder.needsDefinition() && isa(TD)) { // We can delay individual members of classes; do so if necessary. if (isa(container)) { @@ -310,8 +318,10 @@ class ModuleWriter { } else if (auto PD = dyn_cast(TD)) { forwardDeclare(PD); } else if (auto TAD = dyn_cast(TD)) { + bool imported = false; if (TAD->hasClangNode()) - (void)addImport(TD); + imported = addImport(TD); + assert((imported || !TAD->isGeneric()) && "referencing non-imported generic typealias?"); } else if (addImport(TD)) { return; } else if (auto ED = dyn_cast(TD)) { diff --git a/lib/RemoteAST/RemoteAST.cpp b/lib/RemoteAST/RemoteAST.cpp index 686a8421f642d..0f937e95cec77 100644 --- a/lib/RemoteAST/RemoteAST.cpp +++ b/lib/RemoteAST/RemoteAST.cpp @@ -632,9 +632,10 @@ class RemoteASTContextConcreteImpl final : public RemoteASTContextImpl { SubstitutionMap substitutions, unsigned ordinal) override { auto underlyingType = Reader - .readUnderlyingTypeForOpaqueTypeDescriptor(opaqueDescriptor.getAddressData(), - ordinal); - + .readUnderlyingTypeForOpaqueTypeDescriptor( + opaqueDescriptor.getAddressData(), ordinal) + .getType(); + if (!underlyingType) return getFailure(); diff --git a/lib/SIL/IR/AbstractionPattern.cpp b/lib/SIL/IR/AbstractionPattern.cpp index 98b35f470a549..5592dd1d3bef4 100644 --- a/lib/SIL/IR/AbstractionPattern.cpp +++ b/lib/SIL/IR/AbstractionPattern.cpp @@ -236,7 +236,7 @@ bool AbstractionPattern::requiresClass() const { // ObjC generics are always class constrained. return true; } - + assert(GenericSig && "Dependent type in pattern without generic signature?"); return GenericSig->requiresClass(type); @@ -250,30 +250,23 @@ bool AbstractionPattern::requiresClass() const { } LayoutConstraint AbstractionPattern::getLayoutConstraint() const { - // TODO: `ArchetypeType::getLayoutConstraint` and - // `GenericSignature::getLayoutConstraint` don't always propagate implied - // layout constraints from protocol/class constraints. `requiresClass` - // is, for the time being, the only one we really care about, though, and - // it behaves correctly. - if (requiresClass()) { - return LayoutConstraint::getLayoutConstraint(LayoutConstraintKind::Class); - } - return LayoutConstraint(); - -#if GET_LAYOUT_CONSTRAINT_WORKED_THE_WAY_I_WANT switch (getKind()) { case Kind::Opaque: return LayoutConstraint(); case Kind::Type: - case Kind::Discard: { + case Kind::Discard: + case Kind::ClangType: { auto type = getType(); if (auto archetype = dyn_cast(type)) { - auto archetypeSig = archetype->getGenericEnvironment() - ->getGenericSignature(); - return archetypeSig->getLayoutConstraint(archetype->getInterfaceType()); - } - else if (isa(type) || - isa(type)) { + return archetype->getLayoutConstraint(); + } else if (isa(type) || + isa(type)) { + if (getKind() == Kind::ClangType) { + // ObjC generics are always class constrained. + return LayoutConstraint::getLayoutConstraint( + LayoutConstraintKind::Class); + } + assert(GenericSig && "Dependent type in pattern without generic signature?"); return GenericSig->getLayoutConstraint(type); @@ -283,7 +276,6 @@ LayoutConstraint AbstractionPattern::getLayoutConstraint() const { default: return LayoutConstraint(); } -#endif } bool AbstractionPattern::matchesTuple(CanTupleType substType) { diff --git a/lib/SIL/IR/SILFunction.cpp b/lib/SIL/IR/SILFunction.cpp index f5e27bbd56c1b..dd118be43c2ae 100644 --- a/lib/SIL/IR/SILFunction.cpp +++ b/lib/SIL/IR/SILFunction.cpp @@ -107,7 +107,7 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage, StringRef Name, ExactSelfClass(isExactSelfClass), Inlined(false), Zombie(false), HasOwnership(true), WasDeserializedCanonical(false), IsWithoutActuallyEscapingThunk(false), - IsAsync(false), OptMode(unsigned(OptimizationMode::NotSet)), + OptMode(unsigned(OptimizationMode::NotSet)), EffectsKindAttr(unsigned(E)) { assert(!Transparent || !IsDynamicReplaceable); validateSubclassScope(classSubclassScope, isThunk, nullptr); @@ -629,7 +629,7 @@ void SILFunction::setObjCReplacement(Identifier replacedFunc) { // linkage dependency. struct SILFunctionTraceFormatter : public UnifiedStatsReporter::TraceFormatter { - void traceName(const void *Entity, raw_ostream &OS) const { + void traceName(const void *Entity, raw_ostream &OS) const override { if (!Entity) return; const SILFunction *F = static_cast(Entity); @@ -637,7 +637,7 @@ struct SILFunctionTraceFormatter : public UnifiedStatsReporter::TraceFormatter { } void traceLoc(const void *Entity, SourceManager *SM, - clang::SourceManager *CSM, raw_ostream &OS) const { + clang::SourceManager *CSM, raw_ostream &OS) const override { if (!Entity) return; const SILFunction *F = static_cast(Entity); diff --git a/lib/SIL/IR/SILFunctionBuilder.cpp b/lib/SIL/IR/SILFunctionBuilder.cpp index c28ba05090b1b..0ec7e74dbb4d2 100644 --- a/lib/SIL/IR/SILFunctionBuilder.cpp +++ b/lib/SIL/IR/SILFunctionBuilder.cpp @@ -54,7 +54,7 @@ void SILFunctionBuilder::addFunctionAttributes( ? SILSpecializeAttr::SpecializationKind::Full : SILSpecializeAttr::SpecializationKind::Partial; F->addSpecializeAttr( - SILSpecializeAttr::create(M, SA->getSpecializedSgnature(), + SILSpecializeAttr::create(M, SA->getSpecializedSignature(), SA->isExported(), kind)); } @@ -217,10 +217,6 @@ SILFunction *SILFunctionBuilder::getOrCreateFunction( } addFunctionAttributes(F, decl->getAttrs(), mod, getOrCreateDeclaration, constant); - - if (auto *funcDecl = dyn_cast(decl)) { - F->setAsync(funcDecl->hasAsync()); - } } return F; diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index 60f7584418787..29a40a911d107 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -407,6 +407,7 @@ static CanSILFunctionType getAutoDiffDifferentialType( // result's convention is indirect. if (tl.isAddressOnly() && !isIndirectFormalResult(origResConv)) { switch (origResConv) { + case ResultConvention::Unowned: case ResultConvention::Owned: return ResultConvention::Indirect; default: @@ -1214,8 +1215,6 @@ class SubstFunctionTypeCollector { substRequirements.push_back( Requirement(RequirementKind::Layout, param, layout)); } - } else { - (void)0; } for (unsigned i : indices(upperBoundConformances)) { @@ -1304,7 +1303,7 @@ class SubstFunctionTypeCollector { if (origContextType->hasTypeParameter()) { origContextType = origSig->getGenericEnvironment() ->mapTypeIntoContext(origContextType) - ->getCanonicalType(origSig); + ->getCanonicalType(); } auto result = origContextType @@ -1313,12 +1312,7 @@ class SubstFunctionTypeCollector { CanType binding, ArchetypeType *upperBound, ArrayRef bindingConformances) -> CanType { - // TODO: ArchetypeType::getLayoutConstraint sometimes misses out on - // implied layout constraints. For now AnyObject is the only one we - // care about. - return addSubstitution(archetype->requiresClass() - ? LayoutConstraint::getLayoutConstraint(LayoutConstraintKind::Class) - : LayoutConstraint(), + return addSubstitution(archetype->getLayoutConstraint(), binding, upperBound, bindingConformances); @@ -2400,6 +2394,12 @@ static CanSILFunctionType getNativeSILFunctionType( Optional reqtSubs, ProtocolConformanceRef witnessMethodConformance) { assert(bool(origConstant) == bool(constant)); + auto getSILFunctionTypeForConventions = + [&](const Conventions &convs) -> CanSILFunctionType { + return getSILFunctionType(TC, context, origType, substInterfaceType, + extInfo, convs, ForeignInfo(), origConstant, + constant, reqtSubs, witnessMethodConformance); + }; switch (extInfo.getSILRepresentation()) { case SILFunctionType::Representation::Block: case SILFunctionType::Representation::CFunctionPointer: @@ -2416,42 +2416,29 @@ static CanSILFunctionType getNativeSILFunctionType( switch (constant ? constant->kind : SILDeclRef::Kind::Func) { case SILDeclRef::Kind::Initializer: case SILDeclRef::Kind::EnumElement: - return getSILFunctionType(TC, context, origType, substInterfaceType, - extInfo, DefaultInitializerConventions(), - ForeignInfo(), origConstant, constant, reqtSubs, - witnessMethodConformance); + return getSILFunctionTypeForConventions(DefaultInitializerConventions()); case SILDeclRef::Kind::Allocator: - return getSILFunctionType(TC, context, origType, substInterfaceType, - extInfo, DefaultAllocatorConventions(), - ForeignInfo(), origConstant, constant, reqtSubs, - witnessMethodConformance); - case SILDeclRef::Kind::Func: + return getSILFunctionTypeForConventions(DefaultAllocatorConventions()); + case SILDeclRef::Kind::Func: { // If we have a setter, use the special setter convention. This ensures // that we take normal parameters at +1. if (constant && constant->isSetter()) { - return getSILFunctionType(TC, context, origType, substInterfaceType, - extInfo, DefaultSetterConventions(), - ForeignInfo(), origConstant, constant, - reqtSubs, witnessMethodConformance); + return getSILFunctionTypeForConventions(DefaultSetterConventions()); } - LLVM_FALLTHROUGH; + return getSILFunctionTypeForConventions( + DefaultConventions(NormalParameterConvention::Guaranteed)); + } case SILDeclRef::Kind::Destroyer: case SILDeclRef::Kind::GlobalAccessor: case SILDeclRef::Kind::DefaultArgGenerator: case SILDeclRef::Kind::StoredPropertyInitializer: case SILDeclRef::Kind::PropertyWrapperBackingInitializer: case SILDeclRef::Kind::IVarInitializer: - case SILDeclRef::Kind::IVarDestroyer: { - auto conv = DefaultConventions(NormalParameterConvention::Guaranteed); - return getSILFunctionType(TC, context, origType, substInterfaceType, - extInfo, conv, ForeignInfo(), origConstant, - constant, reqtSubs, witnessMethodConformance); - } + case SILDeclRef::Kind::IVarDestroyer: + return getSILFunctionTypeForConventions( + DefaultConventions(NormalParameterConvention::Guaranteed)); case SILDeclRef::Kind::Deallocator: - return getSILFunctionType(TC, context, origType, substInterfaceType, - extInfo, DeallocatorConventions(), - ForeignInfo(), origConstant, constant, reqtSubs, - witnessMethodConformance); + return getSILFunctionTypeForConventions(DeallocatorConventions()); } } } @@ -3997,27 +3984,17 @@ SILFunctionType::substituteOpaqueArchetypes(TypeConverter &TC, CanAnyFunctionType TypeConverter::getBridgedFunctionType(AbstractionPattern pattern, CanAnyFunctionType t, - AnyFunctionType::ExtInfo extInfo, Bridgeability bridging) { // Pull out the generic signature. CanGenericSignature genericSig = t.getOptGenericSignature(); - switch (auto rep = t->getExtInfo().getSILRepresentation()) { - case SILFunctionTypeRepresentation::Thick: - case SILFunctionTypeRepresentation::Thin: - case SILFunctionTypeRepresentation::Method: - case SILFunctionTypeRepresentation::Closure: - case SILFunctionTypeRepresentation::WitnessMethod: { + auto rep = t->getExtInfo().getSILRepresentation(); + switch (getSILFunctionLanguage(rep)) { + case SILFunctionLanguage::Swift: { // No bridging needed for native functions. - if (t->getExtInfo().isEqualTo(extInfo, useClangTypes(t))) - return t; - return CanAnyFunctionType::get(genericSig, t.getParams(), t.getResult(), - extInfo); + return t; } - - case SILFunctionTypeRepresentation::CFunctionPointer: - case SILFunctionTypeRepresentation::Block: - case SILFunctionTypeRepresentation::ObjCMethod: { + case SILFunctionLanguage::C: { SmallVector params; getBridgedParams(rep, pattern, t->getParams(), params, bridging); @@ -4029,7 +4006,7 @@ TypeConverter::getBridgedFunctionType(AbstractionPattern pattern, suppressOptional); return CanAnyFunctionType::get(genericSig, llvm::makeArrayRef(params), - result, extInfo); + result, t->getExtInfo()); } } llvm_unreachable("bad calling convention"); @@ -4111,7 +4088,6 @@ TypeConverter::getLoweredFormalTypes(SILDeclRef constant, auto bridging = Bridgeability::Full; unsigned numParameterLists = constant.getParameterListCount(); - auto extInfo = fnType->getExtInfo(); // Form an abstraction pattern for bridging purposes. AbstractionPattern bridgingFnPattern = @@ -4121,12 +4097,13 @@ TypeConverter::getLoweredFormalTypes(SILDeclRef constant, // Fast path: no uncurrying required. if (numParameterLists == 1) { auto bridgedFnType = - getBridgedFunctionType(bridgingFnPattern, fnType, extInfo, bridging); + getBridgedFunctionType(bridgingFnPattern, fnType, bridging); bridgingFnPattern.rewriteType(bridgingFnPattern.getGenericSignature(), bridgedFnType); return { bridgingFnPattern, bridgedFnType }; } + auto extInfo = fnType->getExtInfo(); SILFunctionTypeRepresentation rep = extInfo.getSILRepresentation(); assert(rep != SILFunctionType::Representation::Block && "objc blocks cannot be curried"); @@ -4477,19 +4454,9 @@ StringRef SILFunctionType::ABICompatibilityCheckResult::getMessage() const { llvm_unreachable("Covered switch isn't completely covered?!"); } -static DeclContext *getDeclContextForExpansion(const SILFunction &f) { - auto *dc = f.getDeclContext(); - if (!dc) - dc = f.getModule().getSwiftModule(); - auto *currentModule = f.getModule().getSwiftModule(); - if (!dc || !dc->isChildContextOf(currentModule)) - dc = currentModule; - return dc; -} - TypeExpansionContext::TypeExpansionContext(const SILFunction &f) : expansion(f.getResilienceExpansion()), - inContext(getDeclContextForExpansion(f)), + inContext(f.getModule().getAssociatedContext()), isContextWholeModule(f.getModule().isWholeModule()) {} CanSILFunctionType SILFunction::getLoweredFunctionTypeInContext( diff --git a/lib/SIL/IR/SILGlobalVariable.cpp b/lib/SIL/IR/SILGlobalVariable.cpp index 609a8318b153d..85407811bae76 100644 --- a/lib/SIL/IR/SILGlobalVariable.cpp +++ b/lib/SIL/IR/SILGlobalVariable.cpp @@ -272,7 +272,7 @@ SILFunction *swift::findInitializer(SILFunction *AddrF, if (!CallToOnce) return nullptr; SILFunction *callee = getCalleeOfOnceCall(CallToOnce); - if (!callee->getName().startswith("globalinit_")) + if (!callee->isGlobalInitOnceFunction()) return nullptr; return callee; } diff --git a/lib/SIL/IR/SILInstructions.cpp b/lib/SIL/IR/SILInstructions.cpp index 1faa9ec6ae6a1..bef2b17c534bc 100644 --- a/lib/SIL/IR/SILInstructions.cpp +++ b/lib/SIL/IR/SILInstructions.cpp @@ -762,10 +762,10 @@ getExtracteeType( LinearFunctionExtractInst::LinearFunctionExtractInst( SILModule &module, SILDebugLocation debugLoc, - LinearDifferentiableFunctionTypeComponent extractee, SILValue theFunction) - : InstructionBase(debugLoc, - getExtracteeType(theFunction, extractee, module)), - extractee(extractee), operands(this, theFunction) {} + LinearDifferentiableFunctionTypeComponent extractee, SILValue function) + : UnaryInstructionBase(debugLoc, function, + getExtracteeType(function, extractee, module)), + extractee(extractee) {} SILType DifferentiabilityWitnessFunctionInst::getDifferentiabilityWitnessType( SILModule &module, DifferentiabilityWitnessFunctionKind witnessKind, diff --git a/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index bb84c23ef1e4c..17c3810556b77 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -462,18 +462,20 @@ static void printSILFunctionNameAndType( llvm::DenseMap &sugaredTypeNames) { function->printName(OS); OS << " : $"; - auto genSig = - function->getLoweredFunctionType()->getInvocationGenericSignature(); auto *genEnv = function->getGenericEnvironment(); - // If `genSig` and `genEnv` are both defined, get sugared names of generic + const GenericSignatureImpl *genSig = nullptr; + + // If `genEnv` is defined, get sugared names of generic // parameter types for printing. - if (genSig && genEnv) { + if (genEnv) { + genSig = genEnv->getGenericSignature().getPointer(); + llvm::DenseSet usedNames; llvm::SmallString<16> disambiguatedNameBuf; unsigned disambiguatedNameCounter = 1; for (auto *paramTy : genSig->getGenericParams()) { // Get a uniqued sugared name for the generic parameter type. - auto sugaredTy = genEnv->getSugaredType(paramTy); + auto sugaredTy = genEnv->getGenericSignature()->getSugaredType(paramTy); Identifier name = sugaredTy->getName(); while (!usedNames.insert(name).second) { disambiguatedNameBuf.clear(); @@ -495,7 +497,7 @@ static void printSILFunctionNameAndType( } } auto printOptions = PrintOptions::printSIL(); - printOptions.GenericEnv = genEnv; + printOptions.GenericSig = genSig; printOptions.AlternativeTypeNames = sugaredTypeNames.empty() ? nullptr : &sugaredTypeNames; function->getLoweredFunctionType()->print(OS, printOptions); @@ -2397,7 +2399,7 @@ class SILPrinter : public SILInstructionVisitor { break; } *this << "] "; - *this << getIDAndType(lfei->getFunctionOperand()); + *this << getIDAndType(lfei->getOperand()); } void visitDifferentiabilityWitnessFunctionInst( @@ -2598,15 +2600,15 @@ void SILFunction::print(SILPrintContext &PrintCtx) const { if (isWithoutActuallyEscapingThunk()) OS << "[without_actually_escaping] "; - if (isAsync()) - OS << "[async] "; - switch (getSpecialPurpose()) { case SILFunction::Purpose::None: break; case SILFunction::Purpose::GlobalInit: OS << "[global_init] "; break; + case SILFunction::Purpose::GlobalInitOnceFunction: + OS << "[global_init_once_fn] "; + break; case SILFunction::Purpose::LazyPropertyGetter: OS << "[lazy_getter] "; break; @@ -3248,8 +3250,9 @@ void SILWitnessTable::print(llvm::raw_ostream &OS, bool Verbose) const { OS << "[serialized] "; getConformance()->printName(OS, Options); - Options.GenericEnv = - getConformance()->getDeclContext()->getGenericEnvironmentOfContext(); + Options.GenericSig = + getConformance()->getDeclContext()->getGenericSignatureOfContext() + .getPointer(); if (isDeclaration()) { OS << "\n\n"; @@ -3292,7 +3295,7 @@ void SILDefaultWitnessTable::print(llvm::raw_ostream &OS, bool Verbose) const { OS << getProtocol()->getName() << " {\n"; PrintOptions options = PrintOptions::printSIL(); - options.GenericEnv = Protocol->getGenericEnvironmentOfContext(); + options.GenericSig = Protocol->getGenericSignatureOfContext().getPointer(); for (auto &witness : getEntries()) { witness.print(OS, Verbose, options); @@ -3443,12 +3446,17 @@ void SILSpecializeAttr::print(llvm::raw_ostream &OS) const { OS << "exported: " << exported << ", "; OS << "kind: " << kind << ", "; + auto *genericEnv = getFunction()->getGenericEnvironment(); + GenericSignature genericSig; + if (genericEnv) + genericSig = genericEnv->getGenericSignature(); + ArrayRef requirements; SmallVector requirementsScratch; if (auto specializedSig = getSpecializedSignature()) { - if (auto env = getFunction()->getGenericEnvironment()) { + if (genericSig) { requirementsScratch = specializedSig->requirementsNotSatisfiedBy( - env->getGenericSignature()); + genericSig); requirements = requirementsScratch; } else { requirements = specializedSig->getRequirements(); @@ -3458,19 +3466,18 @@ void SILSpecializeAttr::print(llvm::raw_ostream &OS) const { OS << "where "; SILFunction *F = getFunction(); assert(F); - auto GenericEnv = F->getGenericEnvironment(); interleave(requirements, [&](Requirement req) { - if (!GenericEnv) { + if (!genericSig) { req.print(OS, SubPrinter); return; } // Use GenericEnvironment to produce user-friendly // names instead of something like t_0_0. - auto FirstTy = GenericEnv->getSugaredType(req.getFirstType()); + auto FirstTy = genericSig->getSugaredType(req.getFirstType()); if (req.getKind() != RequirementKind::Layout) { auto SecondTy = - GenericEnv->getSugaredType(req.getSecondType()); + genericSig->getSugaredType(req.getSecondType()); Requirement ReqWithDecls(req.getKind(), FirstTy, SecondTy); ReqWithDecls.print(OS, SubPrinter); } else { diff --git a/lib/SIL/IR/TypeLowering.cpp b/lib/SIL/IR/TypeLowering.cpp index aa007ad5c7d66..e06cb1ec471a1 100644 --- a/lib/SIL/IR/TypeLowering.cpp +++ b/lib/SIL/IR/TypeLowering.cpp @@ -421,10 +421,6 @@ namespace { RetTy visitArchetypeType(CanArchetypeType type, AbstractionPattern origType) { - if (type->requiresClass()) { - return asImpl().handleReference(type); - } - auto LayoutInfo = type->getLayoutConstraint(); if (LayoutInfo) { if (LayoutInfo->isFixedSizeTrivial()) { @@ -1623,7 +1619,7 @@ namespace { for (auto field : D->getStoredProperties()) { auto substFieldType = field->getInterfaceType().subst(subMap) - ->getCanonicalType(D->getGenericSignature()); + ->getCanonicalType(); // We are determining the recursive properties of the struct here, // not the lowered types of the fields, so instead of lowering the @@ -1676,7 +1672,7 @@ namespace { auto substEltType = elt->getArgumentInterfaceType().subst(subMap) - ->getCanonicalType(D->getGenericSignature()); + ->getCanonicalType(); auto origEltType = origType.unsafeGetSubstFieldType(elt, elt->getArgumentInterfaceType() @@ -1968,7 +1964,7 @@ TypeConverter::computeLoweredRValueType(TypeExpansionContext forExpansion, // Bridge the parameters and result of the function type. auto bridgedFnType = - TC.getBridgedFunctionType(origType, substFnType, extInfo, bridging); + TC.getBridgedFunctionType(origType, substFnType, bridging); substFnType = bridgedFnType; // Also rewrite the type of the abstraction pattern. diff --git a/lib/SIL/Parser/ParseSIL.cpp b/lib/SIL/Parser/ParseSIL.cpp index 00ceaf52ca02e..f12b216fe0802 100644 --- a/lib/SIL/Parser/ParseSIL.cpp +++ b/lib/SIL/Parser/ParseSIL.cpp @@ -919,7 +919,6 @@ static bool parseDeclSILOptional(bool *isTransparent, bool *isWeakImported, AvailabilityContext *availability, bool *isWithoutActuallyEscapingThunk, - bool *isAsync, SmallVectorImpl *Semantics, SmallVectorImpl *SpecAttrs, ValueDecl **ClangDecl, @@ -958,12 +957,12 @@ static bool parseDeclSILOptional(bool *isTransparent, else if (isWithoutActuallyEscapingThunk && SP.P.Tok.getText() == "without_actually_escaping") *isWithoutActuallyEscapingThunk = true; - else if (isAsync && SP.P.Tok.getText() == "async") - *isAsync = true; else if (specialPurpose && SP.P.Tok.getText() == "global_init") *specialPurpose = SILFunction::Purpose::GlobalInit; else if (specialPurpose && SP.P.Tok.getText() == "lazy_getter") *specialPurpose = SILFunction::Purpose::LazyPropertyGetter; + else if (specialPurpose && SP.P.Tok.getText() == "global_init_once_fn") + *specialPurpose = SILFunction::Purpose::GlobalInitOnceFunction; else if (isWeakImported && SP.P.Tok.getText() == "weak_imported") { if (M.getASTContext().LangOpts.Target.isOSBinFormatCOFF()) SP.P.diagnose(SP.P.Tok, diag::attr_unsupported_on_target, @@ -5682,7 +5681,6 @@ bool SILParserState::parseDeclSIL(Parser &P) { bool isWeakImported = false; AvailabilityContext availability = AvailabilityContext::alwaysAvailable(); bool isWithoutActuallyEscapingThunk = false; - bool isAsync = false; Inline_t inlineStrategy = InlineDefault; OptimizationMode optimizationMode = OptimizationMode::NotSet; SmallVector Semantics; @@ -5697,8 +5695,8 @@ bool SILParserState::parseDeclSIL(Parser &P) { &isThunk, &isDynamic, &isExactSelfClass, &DynamicallyReplacedFunction, &objCReplacementFor, &specialPurpose, &inlineStrategy, &optimizationMode, nullptr, &isWeakImported, &availability, - &isWithoutActuallyEscapingThunk, &isAsync, &Semantics, &SpecAttrs, - &ClangDecl, &MRK, FunctionState, M) || + &isWithoutActuallyEscapingThunk, &Semantics, + &SpecAttrs, &ClangDecl, &MRK, FunctionState, M) || P.parseToken(tok::at_sign, diag::expected_sil_function_name) || P.parseIdentifier(FnName, FnNameLoc, diag::expected_sil_function_name) || P.parseToken(tok::colon, diag::expected_sil_type)) @@ -5736,7 +5734,6 @@ bool SILParserState::parseDeclSIL(Parser &P) { FunctionState.F->setAvailabilityForLinkage(availability); FunctionState.F->setWithoutActuallyEscapingThunk( isWithoutActuallyEscapingThunk); - FunctionState.F->setAsync(isAsync); FunctionState.F->setInlineStrategy(inlineStrategy); FunctionState.F->setOptimizationMode(optimizationMode); FunctionState.F->setEffectsKind(MRK); @@ -5922,9 +5919,10 @@ bool SILParserState::parseSILGlobal(Parser &P) { SILParser State(P); if (parseSILLinkage(GlobalLinkage, P) || parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, &isLet, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, State, M) || + nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, + &isLet, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, State, M) || P.parseToken(tok::at_sign, diag::expected_sil_value_name) || P.parseIdentifier(GlobalName, NameLoc, diag::expected_sil_value_name) || P.parseToken(tok::colon, diag::expected_sil_type)) @@ -5973,7 +5971,7 @@ bool SILParserState::parseSILProperty(Parser &P) { if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, SP, M)) + nullptr, nullptr, nullptr, SP, M)) return true; ValueDecl *VD; @@ -6043,7 +6041,8 @@ bool SILParserState::parseSILVTable(Parser &P) { if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, VTableState, M)) + nullptr, nullptr, nullptr, + VTableState, M)) return true; // Parse the class name. @@ -6579,7 +6578,8 @@ bool SILParserState::parseSILWitnessTable(Parser &P) { if (parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, WitnessState, M)) + nullptr, nullptr, nullptr, + WitnessState, M)) return true; Scope S(&P, ScopeKind::TopLevel); diff --git a/lib/SIL/Utils/OptimizationRemark.cpp b/lib/SIL/Utils/OptimizationRemark.cpp index 00da367598e31..6a778f0266c16 100644 --- a/lib/SIL/Utils/OptimizationRemark.cpp +++ b/lib/SIL/Utils/OptimizationRemark.cpp @@ -152,6 +152,8 @@ static SourceLoc inferOptRemarkSearchForwards(SILInstruction &i) { for (auto &inst : llvm::make_range(std::next(i.getIterator()), i.getParent()->end())) { auto newLoc = inst.getLoc().getSourceLoc(); + if (auto inlinedLoc = inst.getDebugScope()->getOutermostInlineLocation()) + newLoc = inlinedLoc.getSourceLoc(); if (newLoc.isValid()) return newLoc; } @@ -167,7 +169,9 @@ static SourceLoc inferOptRemarkSearchBackwards(SILInstruction &i) { for (auto &inst : llvm::make_range(std::next(i.getReverseIterator()), i.getParent()->rend())) { auto loc = inst.getLoc(); - if (!bool(loc)) + if (auto inlinedLoc = inst.getDebugScope()->getOutermostInlineLocation()) + loc = inlinedLoc; + if (!loc.getSourceLoc().isValid()) continue; auto range = loc.getSourceRange(); @@ -180,12 +184,16 @@ static SourceLoc inferOptRemarkSearchBackwards(SILInstruction &i) { SourceLoc swift::OptRemark::inferOptRemarkSourceLoc( SILInstruction &i, SourceLocInferenceBehavior inferBehavior) { - auto loc = i.getLoc().getSourceLoc(); - - // Do a quick check if we already have a valid loc. In such a case, just - // return. Otherwise, we try to infer using one of our heuristics below. - if (loc.isValid()) - return loc; + // Do a quick check if we already have a valid loc and it isnt an inline + // loc. In such a case, just return. Otherwise, we try to infer using one of + // our heuristics below. + auto loc = i.getLoc(); + if (loc.getSourceLoc().isValid()) { + // Before we do anything, if we do not have an inlined call site, just + // return our loc. + if (!i.getDebugScope() || !i.getDebugScope()->InlinedCallSite) + return loc.getSourceLoc(); + } // Otherwise, try to handle the individual behavior cases, returning loc at // the end of each case (its invalid, so it will get ignored). If loc is not @@ -193,18 +201,18 @@ SourceLoc swift::OptRemark::inferOptRemarkSourceLoc( // was missed. switch (inferBehavior) { case SourceLocInferenceBehavior::None: - return loc; + return SourceLoc(); case SourceLocInferenceBehavior::ForwardScanOnly: { SourceLoc newLoc = inferOptRemarkSearchForwards(i); if (newLoc.isValid()) return newLoc; - return loc; + return SourceLoc(); } case SourceLocInferenceBehavior::BackwardScanOnly: { SourceLoc newLoc = inferOptRemarkSearchBackwards(i); if (newLoc.isValid()) return newLoc; - return loc; + return SourceLoc(); } case SourceLocInferenceBehavior::ForwardThenBackward: { SourceLoc newLoc = inferOptRemarkSearchForwards(i); @@ -213,7 +221,7 @@ SourceLoc swift::OptRemark::inferOptRemarkSourceLoc( newLoc = inferOptRemarkSearchBackwards(i); if (newLoc.isValid()) return newLoc; - return loc; + return SourceLoc(); } case SourceLocInferenceBehavior::BackwardThenForward: { SourceLoc newLoc = inferOptRemarkSearchBackwards(i); @@ -222,7 +230,7 @@ SourceLoc swift::OptRemark::inferOptRemarkSourceLoc( newLoc = inferOptRemarkSearchForwards(i); if (newLoc.isValid()) return newLoc; - return loc; + return SourceLoc(); } } diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 83912db313ffb..297019bbf66d4 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -4730,7 +4730,7 @@ class SILVerifier : public SILVerifierBase { } void checkLinearFunctionExtractInst(LinearFunctionExtractInst *lfei) { - auto fnTy = lfei->getFunctionOperand()->getType().getAs(); + auto fnTy = lfei->getOperand()->getType().getAs(); require(fnTy, "The function operand must have a function type"); require(fnTy->getDifferentiabilityKind() == DifferentiabilityKind::Linear, "The function operand must be a '@differentiable(linear)' " diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index cd36b343f0e58..ecd8482d96768 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -415,6 +415,7 @@ SILGenModule::getKeyPathProjectionCoroutine(bool isReadAccess, SILFunctionType::ExtInfoBuilder(SILFunctionTypeRepresentation::Thin, /*pseudogeneric*/ false, /*non-escaping*/ false, + /*async*/ false, DifferentiabilityKind::NonDifferentiable, /*clangFunctionType*/ nullptr) .build(); @@ -1366,6 +1367,7 @@ SILFunction *SILGenModule::emitLazyGlobalInitializer(StringRef funcName, auto *f = builder.createFunction( SILLinkage::Private, funcName, initSILType, nullptr, SILLocation(binding), IsNotBare, IsNotTransparent, IsNotSerialized, IsNotDynamic); + f->setSpecialPurpose(SILFunction::Purpose::GlobalInitOnceFunction); f->setDebugScope(new (M) SILDebugScope(RegularLocation(binding), f)); auto dc = binding->getDeclContext(); SILGenFunction(*this, *f, dc).emitLazyGlobalInitializer(binding, pbdEntry); diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index bffecc2c2c187..22d3136ca776c 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -76,7 +76,6 @@ getIndirectApplyAbstractionPattern(SILGenFunction &SGF, // bridged to a foreign type. auto bridgedType = SGF.SGM.Types.getBridgedFunctionType(pattern, fnType, - fnType->getExtInfo(), Bridgeability::Full); pattern.rewriteType(CanGenericSignature(), bridgedType); return pattern; diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index 7eedc3b1975fa..0c1bb7d417a89 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -350,8 +350,7 @@ getParameterTypes(AnyFunctionType::CanParamArrayRef params) { static CanAnyFunctionType getBridgedBlockType(SILGenModule &SGM, CanAnyFunctionType blockType) { return SGM.Types.getBridgedFunctionType(AbstractionPattern(blockType), - blockType, blockType->getExtInfo(), - Bridgeability::Full); + blockType, Bridgeability::Full); } static void buildFuncToBlockInvokeBody(SILGenFunction &SGF, diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp index 0aef4de8034b3..0f4866879fb90 100644 --- a/lib/SILGen/SILGenConstructor.cpp +++ b/lib/SILGen/SILGenConstructor.cpp @@ -216,11 +216,9 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF, .forwardInto(SGF, Loc, init.get()); ++elti; } else { -#ifndef NDEBUG - assert( - field->getType()->isEqual(field->getParentInitializer()->getType()) - && "Checked by sema"); -#endif + assert(field->getType()->getReferenceStorageReferent()->isEqual( + field->getParentInitializer()->getType()) && + "Initialization of field with mismatched type!"); // Cleanup after this initialization. FullExpr scope(SGF.Cleanups, field->getParentPatternBinding()); diff --git a/lib/SILGen/SILGenGlobalVariable.cpp b/lib/SILGen/SILGenGlobalVariable.cpp index 551b438f461f0..a43ce63f99508 100644 --- a/lib/SILGen/SILGenGlobalVariable.cpp +++ b/lib/SILGen/SILGenGlobalVariable.cpp @@ -178,20 +178,8 @@ void SILGenModule::emitGlobalInitialization(PatternBindingDecl *pd, ->areAllParamsConcrete()); } - // Emit the lazy initialization token for the initialization expression. - auto counter = anonymousSymbolCounter++; - - // Pick one variable of the pattern. Usually it's only one variable, but it - // can also be something like: var (a, b) = ... - Pattern *pattern = pd->getPattern(pbdEntry); - VarDecl *varDecl = nullptr; - pattern->forEachVariable([&](VarDecl *D) { - varDecl = D; - }); - assert(varDecl); - Mangle::ASTMangler TokenMangler; - std::string onceTokenBuffer = TokenMangler.mangleGlobalInit(varDecl, counter, + std::string onceTokenBuffer = TokenMangler.mangleGlobalInit(pd, pbdEntry, false); auto onceTy = BuiltinIntegerType::getWordType(M.getASTContext()); @@ -207,7 +195,7 @@ void SILGenModule::emitGlobalInitialization(PatternBindingDecl *pd, // Emit the initialization code into a function. Mangle::ASTMangler FuncMangler; - std::string onceFuncBuffer = FuncMangler.mangleGlobalInit(varDecl, counter, + std::string onceFuncBuffer = FuncMangler.mangleGlobalInit(pd, pbdEntry, true); SILFunction *onceFunc = emitLazyGlobalInitializer(onceFuncBuffer, pd, diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp index b7ee169fc9faf..a63b0bd512862 100644 --- a/lib/SILGen/SILGenPattern.cpp +++ b/lib/SILGen/SILGenPattern.cpp @@ -1038,20 +1038,35 @@ void PatternMatchEmission::emitDispatch(ClauseMatrix &clauses, ArgArray args, SGF.eraseBasicBlock(contBB); return; } - + // Otherwise, if there is no fallthrough, then the next row is - // unreachable: emit a dead code diagnostic. + // unreachable: emit a dead code diagnostic if: + // 1) It's for a 'default' case (since Space Engine already handles + // unreachable enum case patterns) or it's for a enum case which + // has expression patterns since redundancy checking for such + // patterns isn't sufficiently done by the Space Engine. + // 2) It's for a case statement in a do-catch. if (!clauses[firstRow].hasFallthroughTo()) { SourceLoc Loc; bool isDefault = false; + bool isParentDoCatch = false; + bool caseHasExprPattern = false; if (auto *S = clauses[firstRow].getClientData()) { Loc = S->getStartLoc(); - if (auto *CS = dyn_cast(S)) + if (auto *CS = dyn_cast(S)) { + caseHasExprPattern = llvm::any_of( + CS->getCaseLabelItems(), [&](const CaseLabelItem item) { + return item.getPattern()->getKind() == PatternKind::Expr; + }); + isParentDoCatch = CS->getParentKind() == CaseParentKind::DoCatch; isDefault = CS->isDefault(); + } } else { Loc = clauses[firstRow].getCasePattern()->getStartLoc(); } - SGF.SGM.diagnose(Loc, diag::unreachable_case, isDefault); + if (isParentDoCatch || isDefault || caseHasExprPattern) { + SGF.SGM.diagnose(Loc, diag::unreachable_case, isDefault); + } } } } diff --git a/lib/SILOptimizer/ARC/ARCLoopOpts.cpp b/lib/SILOptimizer/ARC/ARCLoopOpts.cpp index 2cadf6426c013..aa54592497e51 100644 --- a/lib/SILOptimizer/ARC/ARCLoopOpts.cpp +++ b/lib/SILOptimizer/ARC/ARCLoopOpts.cpp @@ -47,7 +47,7 @@ class ARCLoopOpts : public SILFunctionTransform { return; // Skip global init functions. - if (F->getName().startswith("globalinit_")) + if (F->isGlobalInitOnceFunction()) return; auto *LA = getAnalysis(); diff --git a/lib/SILOptimizer/ARC/ARCMatchingSet.cpp b/lib/SILOptimizer/ARC/ARCMatchingSet.cpp index 442a4c9011b89..fc603c690f747 100644 --- a/lib/SILOptimizer/ARC/ARCMatchingSet.cpp +++ b/lib/SILOptimizer/ARC/ARCMatchingSet.cpp @@ -68,8 +68,6 @@ ARCMatchingSetBuilder::matchIncrementsToDecrements() { continue; } - // We need to be known safe over all increments/decrements we are matching - // up to ignore insertion points. bool BUIsKnownSafe = (*BURefCountState)->second.isKnownSafe(); LLVM_DEBUG(llvm::dbgs() << " BOTTOM UP KNOWNSAFE: " << (BUIsKnownSafe ? "true" : "false") << "\n"); @@ -152,8 +150,6 @@ ARCMatchingSetBuilder::matchDecrementsToIncrements() { continue; } - // We need to be known safe over all increments/decrements we are matching - // up to ignore insertion points. bool TDIsKnownSafe = (*TDRefCountState)->second.isKnownSafe(); LLVM_DEBUG(llvm::dbgs() << " TOP DOWN KNOWNSAFE: " << (TDIsKnownSafe ? "true" : "false") << "\n"); @@ -223,7 +219,7 @@ bool ARCMatchingSetBuilder::matchUpIncDecSetsForPtr() { LLVM_DEBUG(llvm::dbgs() << "Attempting to match up increments -> " "decrements:\n"); // For each increment in our list of new increments, attempt to match them - // up with decrements and gather the insertion points of the decrements. + // up with decrements. auto Result = matchIncrementsToDecrements(); if (!Result) { LLVM_DEBUG(llvm::dbgs() << " FAILED TO MATCH INCREMENTS -> " @@ -287,8 +283,6 @@ bool ARCMatchingSetBuilder::matchUpIncDecSetsForPtr() { assert(MatchSet.Increments.empty() == MatchSet.Decrements.empty() && "Match set without increments or decrements"); - // If we do not have any insertion points but we do have increments, we must - // be eliminating pairs. if (!MatchSet.Increments.empty()) MatchedPair = true; diff --git a/lib/SILOptimizer/ARC/ARCRegionState.cpp b/lib/SILOptimizer/ARC/ARCRegionState.cpp index f654bbeb6e485..0f60f59fb34b8 100644 --- a/lib/SILOptimizer/ARC/ARCRegionState.cpp +++ b/lib/SILOptimizer/ARC/ARCRegionState.cpp @@ -12,6 +12,7 @@ #define DEBUG_TYPE "arc-sequence-opts" #include "ARCRegionState.h" +#include "ARCSequenceOptUtils.h" #include "RCStateTransitionVisitors.h" #include "swift/Basic/Range.h" #include "swift/SILOptimizer/Analysis/LoopRegionAnalysis.h" @@ -155,77 +156,6 @@ void ARCRegionState::mergePredTopDown(ARCRegionState &PredRegionState) { // Bottom Up Dataflow // -static bool isARCSignificantTerminator(TermInst *TI) { - switch (TI->getTermKind()) { - case TermKind::UnreachableInst: - // br is a forwarding use for its arguments. It cannot in of itself extend - // the lifetime of an object (just like a phi-node) cannot. - case TermKind::BranchInst: - // A cond_br is a forwarding use for its non-operand arguments in a similar - // way to br. Its operand must be an i1 that has a different lifetime from any - // ref counted object. - case TermKind::CondBranchInst: - return false; - // Be conservative for now. These actually perform some sort of operation - // against the operand or can use the value in some way. - case TermKind::ThrowInst: - case TermKind::ReturnInst: - case TermKind::UnwindInst: - case TermKind::YieldInst: - case TermKind::TryApplyInst: - case TermKind::SwitchValueInst: - case TermKind::SwitchEnumInst: - case TermKind::SwitchEnumAddrInst: - case TermKind::DynamicMethodBranchInst: - case TermKind::CheckedCastBranchInst: - case TermKind::CheckedCastValueBranchInst: - case TermKind::CheckedCastAddrBranchInst: - return true; - } - - llvm_unreachable("Unhandled TermKind in switch."); -} - -// Visit each one of our predecessor regions and see if any are blocks that can -// use reference counted values. If any of them do, we advance the sequence for -// the pointer and create an insertion point here. This state will be propagated -// into all of our predecessors, allowing us to be conservatively correct in all -// cases. -// -// The key thing to notice is that in general this cannot happen due to -// critical edge splitting. To trigger this, one would need a terminator that -// uses a reference counted value and only has one successor due to critical -// edge splitting. This is just to be conservative when faced with the unknown -// of future changes. -// -// We do not need to worry about loops here, since a loop exit block can only -// have predecessors in the loop itself implying that loop exit blocks at the -// loop region level always have only one predecessor, the loop itself. -void ARCRegionState::processBlockBottomUpPredTerminators( - const LoopRegion *R, AliasAnalysis *AA, LoopRegionFunctionInfo *LRFI, - ImmutablePointerSetFactory &SetFactory) { - llvm::TinyPtrVector PredTerminators; - for (unsigned PredID : R->getPreds()) { - auto *PredRegion = LRFI->getRegion(PredID); - if (!PredRegion->isBlock()) - continue; - - auto *TermInst = PredRegion->getBlock()->getTerminator(); - if (!isARCSignificantTerminator(TermInst)) - continue; - PredTerminators.push_back(TermInst); - } - - for (auto &OtherState : getBottomupStates()) { - // If the other state's value is blotted, skip it. - if (!OtherState.hasValue()) - continue; - - OtherState->second.updateForPredTerminators(PredTerminators, - SetFactory, AA); - } -} - static bool processBlockBottomUpInsts( ARCRegionState &State, SILBasicBlock &BB, BottomUpDataflowRCStateVisitor &DataflowVisitor, @@ -239,9 +169,9 @@ static bool processBlockBottomUpInsts( if (II == IE) return false; - // If II is the terminator, skip it since our terminator was already processed - // in our successors. - if (*II == BB.getTerminator()) + // If II is not an arc significant terminator, skip it. + if (*II == BB.getTerminator() && + !isARCSignificantTerminator(cast(*II))) ++II; bool NestingDetected = false; @@ -298,29 +228,19 @@ bool ARCRegionState::processBlockBottomUp( RCIA, EAFI, *this, FreezeOwnedArgEpilogueReleases, IncToDecStateMap, SetFactory); - // Visit each non-terminator arc relevant instruction I in BB visited in - // reverse... + // Visit each arc relevant instruction I in BB visited in reverse... bool NestingDetected = processBlockBottomUpInsts(*this, BB, DataflowVisitor, AA, SetFactory); - // Now visit each one of our predecessor regions and see if any are blocks - // that can use reference counted values. If any of them do, we advance the - // sequence for the pointer and create an insertion point here. This state - // will be propagated into all of our predecessors, allowing us to be - // conservatively correct in all cases. - processBlockBottomUpPredTerminators(R, AA, LRFI, SetFactory); - return NestingDetected; } -// Find the relevant insertion points for the loop region R in its -// successors. Returns true if we succeeded. Returns false if any of the -// non-local successors of the region are not leaking blocks. We currently do -// not handle early exits, but do handle trapping blocks. -static bool getInsertionPtsForLoopRegionExits( +// Returns true if any of the non-local successors of the region are leaking +// blocks. We currently do not handle early exits, but do handle trapping +// blocks. Returns false if otherwise +static bool hasEarlyExits( const LoopRegion *R, LoopRegionFunctionInfo *LRFI, - llvm::DenseMap &RegionStateInfo, - llvm::SmallVectorImpl &InsertPts) { + llvm::DenseMap &RegionStateInfo) { assert(R->isLoop() && "Expected a loop region that is representing a loop"); // Go through all of our non local successors. If any of them cannot be @@ -329,23 +249,10 @@ static bool getInsertionPtsForLoopRegionExits( if (any_of(R->getNonLocalSuccs(), [&](unsigned SuccID) -> bool { return !RegionStateInfo[LRFI->getRegion(SuccID)]->allowsLeaks(); })) { - return false; - } - - // We assume that all of our loops have been canonicalized so that /all/ loop - // exit blocks only have exiting blocks as predecessors. This means that all - // successor regions of any region /cannot/ be a region representing a loop. - for (unsigned SuccID : R->getLocalSuccs()) { - auto *SuccRegion = LRFI->getRegion(SuccID); - assert(SuccRegion->isBlock() && "Loop canonicalization failed?!"); - InsertPts.push_back(&*SuccRegion->getBlock()->begin()); + return true; } - // Sort and unique the insert points so we can put them into - // ImmutablePointerSets. - sortUnique(InsertPts); - - return true; + return false; } bool ARCRegionState::processLoopBottomUp( @@ -354,11 +261,9 @@ bool ARCRegionState::processLoopBottomUp( ImmutablePointerSetFactory &SetFactory) { ARCRegionState *State = RegionStateInfo[R]; - llvm::SmallVector InsertPts; - // Try to lookup insertion points for this region. If when checking for - // insertion points, we find that we have non-leaking early exits, clear state + // If we find that we have non-leaking early exits, clear state // and bail. We do not handle these for now. - if (!getInsertionPtsForLoopRegionExits(R, LRFI, RegionStateInfo, InsertPts)) { + if (hasEarlyExits(R, LRFI, RegionStateInfo)) { clearBottomUpState(); return false; } diff --git a/lib/SILOptimizer/ARC/ARCSequenceOptUtils.cpp b/lib/SILOptimizer/ARC/ARCSequenceOptUtils.cpp new file mode 100644 index 0000000000000..ff04e27b99264 --- /dev/null +++ b/lib/SILOptimizer/ARC/ARCSequenceOptUtils.cpp @@ -0,0 +1,48 @@ +//===--- ARCSequenceOptUtils.cpp - ARCSequenceOpt utilities ------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#include "ARCSequenceOptUtils.h" + +using namespace swift; +namespace swift { +bool isARCSignificantTerminator(TermInst *TI) { + switch (TI->getTermKind()) { + case TermKind::UnreachableInst: + // br is a forwarding use for its arguments. It cannot in of itself extend + // the lifetime of an object (just like a phi-node) cannot. + case TermKind::BranchInst: + // A cond_br is a forwarding use for its non-operand arguments in a similar + // way to br. Its operand must be an i1 that has a different lifetime from any + // ref counted object. + case TermKind::CondBranchInst: + return false; + // Be conservative for now. These actually perform some sort of operation + // against the operand or can use the value in some way. + case TermKind::ThrowInst: + case TermKind::ReturnInst: + case TermKind::UnwindInst: + case TermKind::YieldInst: + case TermKind::TryApplyInst: + case TermKind::SwitchValueInst: + case TermKind::SwitchEnumInst: + case TermKind::SwitchEnumAddrInst: + case TermKind::DynamicMethodBranchInst: + case TermKind::CheckedCastBranchInst: + case TermKind::CheckedCastValueBranchInst: + case TermKind::CheckedCastAddrBranchInst: + return true; + } + + llvm_unreachable("Unhandled TermKind in switch."); +} + +} // end namespace 'swift' diff --git a/lib/SILOptimizer/ARC/ARCSequenceOptUtils.h b/lib/SILOptimizer/ARC/ARCSequenceOptUtils.h new file mode 100644 index 0000000000000..b94af73cc1aab --- /dev/null +++ b/lib/SILOptimizer/ARC/ARCSequenceOptUtils.h @@ -0,0 +1,27 @@ +//===--- ARCSequenceOptUtils.h - ARCSequenceOpts utilities ----*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +/// +/// Utilities used by the ARCSequenceOpts for analyzing and transforming +/// SILInstructions. +/// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_SILOPTIMIZER_ARC_ARCSEQUENCEOPTUTILS_H +#define SWIFT_SILOPTIMIZER_ARC_ARCSEQUENCEOPTUTILS_H + +#include "swift/SIL/SILInstruction.h" + +namespace swift { +bool isARCSignificantTerminator(TermInst *TI); +} // end namespace swift + +#endif diff --git a/lib/SILOptimizer/ARC/ARCSequenceOpts.cpp b/lib/SILOptimizer/ARC/ARCSequenceOpts.cpp index 00d284761f6a7..f628be8b5b29c 100644 --- a/lib/SILOptimizer/ARC/ARCSequenceOpts.cpp +++ b/lib/SILOptimizer/ARC/ARCSequenceOpts.cpp @@ -45,12 +45,10 @@ llvm::cl::opt EnableLoopARC("enable-loop-arc", llvm::cl::init(false)); // Code Motion //===----------------------------------------------------------------------===// -// This routine takes in the ARCMatchingSet \p MatchSet and inserts new -// increments, decrements at the insertion points and adds the old increment, -// decrements to the delete list. Sets changed to true if anything was moved or -// deleted. +// This routine takes in the ARCMatchingSet \p MatchSet and adds the increments +// and decrements to the delete list. void ARCPairingContext::optimizeMatchingSet( - ARCMatchingSet &MatchSet, llvm::SmallVectorImpl &NewInsts, + ARCMatchingSet &MatchSet, llvm::SmallVectorImpl &DeadInsts) { LLVM_DEBUG(llvm::dbgs() << "**** Optimizing Matching Set ****\n"); // Add the old increments to the delete list. @@ -71,7 +69,6 @@ void ARCPairingContext::optimizeMatchingSet( } bool ARCPairingContext::performMatching( - llvm::SmallVectorImpl &NewInsts, llvm::SmallVectorImpl &DeadInsts) { bool MatchedPair = false; @@ -99,10 +96,7 @@ bool ARCPairingContext::performMatching( for (auto *I : Set.Decrements) DecToIncStateMap.erase(I); - // Add the Set to the callback. *NOTE* No instruction destruction can - // happen here since we may remove instructions that are insertion points - // for other instructions. - optimizeMatchingSet(Set, NewInsts, DeadInsts); + optimizeMatchingSet(Set, DeadInsts); } } @@ -136,7 +130,6 @@ void LoopARCPairingContext::runOnFunction(SILFunction *F) { bool LoopARCPairingContext::processRegion(const LoopRegion *Region, bool FreezePostDomReleases, bool RecomputePostDomReleases) { - llvm::SmallVector NewInsts; llvm::SmallVector DeadInsts; // We have already summarized all subloops of this loop. Now summarize our @@ -150,16 +143,7 @@ bool LoopARCPairingContext::processRegion(const LoopRegion *Region, do { NestingDetected = Evaluator.runOnLoop(Region, FreezePostDomReleases, RecomputePostDomReleases); - MatchedPair = Context.performMatching(NewInsts, DeadInsts); - - if (!NewInsts.empty()) { - LLVM_DEBUG(llvm::dbgs() << "Adding new interesting insts!\n"); - do { - auto *I = NewInsts.pop_back_val(); - LLVM_DEBUG(llvm::dbgs() << " " << *I); - Evaluator.addInterestingInst(I); - } while (!NewInsts.empty()); - } + MatchedPair = Context.performMatching(DeadInsts); if (!DeadInsts.empty()) { LLVM_DEBUG(llvm::dbgs() << "Removing dead interesting insts!\n"); @@ -199,7 +183,7 @@ processFunctionWithoutLoopSupport(SILFunction &F, bool FreezePostDomReleases, // globalinit_func. Since that is not *that* interesting from an ARC // perspective (i.e. no ref count operations in a loop), disable it on such // functions temporarily in order to unblock others. This should be removed. - if (F.getName().startswith("globalinit_")) + if (F.isGlobalInitOnceFunction()) return false; LLVM_DEBUG(llvm::dbgs() << "***** Processing " << F.getName() << " *****\n"); @@ -247,7 +231,7 @@ static bool processFunctionWithLoopSupport( // globalinit_func. Since that is not *that* interesting from an ARC // perspective (i.e. no ref count operations in a loop), disable it on such // functions temporarily in order to unblock others. This should be removed. - if (F.getName().startswith("globalinit_")) + if (F.isGlobalInitOnceFunction()) return false; LLVM_DEBUG(llvm::dbgs() << "***** Processing " << F.getName() << " *****\n"); diff --git a/lib/SILOptimizer/ARC/ARCSequenceOpts.h b/lib/SILOptimizer/ARC/ARCSequenceOpts.h index 36d7eb57f2548..9be3af2cc3620 100644 --- a/lib/SILOptimizer/ARC/ARCSequenceOpts.h +++ b/lib/SILOptimizer/ARC/ARCSequenceOpts.h @@ -39,11 +39,9 @@ struct ARCPairingContext { ARCPairingContext(SILFunction &F, RCIdentityFunctionInfo *RCIA) : F(F), DecToIncStateMap(), IncToDecStateMap(), RCIA(RCIA) {} - bool performMatching(llvm::SmallVectorImpl &NewInsts, - llvm::SmallVectorImpl &DeadInsts); + bool performMatching(llvm::SmallVectorImpl &DeadInsts); void optimizeMatchingSet(ARCMatchingSet &MatchSet, - llvm::SmallVectorImpl &NewInsts, llvm::SmallVectorImpl &DeadInsts); }; @@ -68,10 +66,8 @@ struct BlockARCPairingContext { bool NestingDetected = Evaluator.run(FreezePostDomReleases); Evaluator.clear(); - llvm::SmallVector NewInsts; llvm::SmallVector DeadInsts; - bool MatchedPair = Context.performMatching(NewInsts, DeadInsts); - NewInsts.clear(); + bool MatchedPair = Context.performMatching(DeadInsts); while (!DeadInsts.empty()) DeadInsts.pop_back_val()->eraseFromParent(); return NestingDetected && MatchedPair; diff --git a/lib/SILOptimizer/ARC/CMakeLists.txt b/lib/SILOptimizer/ARC/CMakeLists.txt index 2d3c592834b1b..bc14ca17698ac 100644 --- a/lib/SILOptimizer/ARC/CMakeLists.txt +++ b/lib/SILOptimizer/ARC/CMakeLists.txt @@ -4,6 +4,7 @@ target_sources(swiftSILOptimizer PRIVATE ARCMatchingSet.cpp ARCRegionState.cpp ARCSequenceOpts.cpp + ARCSequenceOptUtils.cpp GlobalARCSequenceDataflow.cpp GlobalLoopARCSequenceDataflow.cpp RCStateTransition.cpp diff --git a/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp b/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp index 777548d884bdd..5d080626d7a19 100644 --- a/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp +++ b/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp @@ -13,6 +13,7 @@ #define DEBUG_TYPE "arc-sequence-opts" #include "GlobalARCSequenceDataflow.h" #include "ARCBBState.h" +#include "ARCSequenceOptUtils.h" #include "RCStateTransitionVisitors.h" #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" #include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h" @@ -117,7 +118,6 @@ bool ARCSequenceDataflowEvaluator::processBBTopDown(ARCBBState &BBState) { void ARCSequenceDataflowEvaluator::mergePredecessors( ARCBBStateInfoHandle &DataHandle) { bool HasAtLeastOnePred = false; - llvm::SmallVector BBThatNeedInsertPts; SILBasicBlock *BB = DataHandle.getBB(); ARCBBState &BBState = DataHandle.getState(); @@ -195,39 +195,6 @@ bool ARCSequenceDataflowEvaluator::processTopDown() { // Bottom Up Dataflow //===----------------------------------------------------------------------===// -// This is temporary code duplication. This will be removed when Loop ARC is -// finished and Block ARC is removed. -static bool isARCSignificantTerminator(TermInst *TI) { - switch (TI->getTermKind()) { - case TermKind::UnreachableInst: - // br is a forwarding use for its arguments. It cannot in of itself extend - // the lifetime of an object (just like a phi-node) cannot. - case TermKind::BranchInst: - // A cond_br is a forwarding use for its non-operand arguments in a similar - // way to br. Its operand must be an i1 that has a different lifetime from any - // ref counted object. - case TermKind::CondBranchInst: - return false; - // Be conservative for now. These actually perform some sort of operation - // against the operand or can use the value in some way. - case TermKind::ThrowInst: - case TermKind::ReturnInst: - case TermKind::UnwindInst: - case TermKind::YieldInst: - case TermKind::TryApplyInst: - case TermKind::SwitchValueInst: - case TermKind::SwitchEnumInst: - case TermKind::SwitchEnumAddrInst: - case TermKind::DynamicMethodBranchInst: - case TermKind::CheckedCastBranchInst: - case TermKind::CheckedCastValueBranchInst: - case TermKind::CheckedCastAddrBranchInst: - return true; - } - - llvm_unreachable("Unhandled TermKind in switch."); -} - /// Analyze a single BB for refcount inc/dec instructions. /// /// If anything was found it will be added to DecToIncStateMap. @@ -254,8 +221,13 @@ bool ARCSequenceDataflowEvaluator::processBBBottomUp( RCIA, EAFI, BBState, FreezeOwnedArgEpilogueReleases, IncToDecStateMap, SetFactory); - // For each terminator instruction I in BB visited in reverse... - for (auto II = std::next(BB.rbegin()), IE = BB.rend(); II != IE;) { + auto II = BB.rbegin(); + if (!isARCSignificantTerminator(&cast(*II))) { + II++; + } + + // For each instruction I in BB visited in reverse... + for (auto IE = BB.rend(); II != IE;) { SILInstruction &I = *II; ++II; @@ -292,31 +264,6 @@ bool ARCSequenceDataflowEvaluator::processBBBottomUp( } } - // This is ignoring the possibility that we may have a loop with an - // interesting terminator but for which, we are going to clear all state - // (since it is a loop boundary). We may in such a case, be too conservative - // with our other predecessors. Luckily this cannot happen since cond_br is - // the only terminator that allows for critical edges and all other - // "interesting terminators" always having multiple successors. This means - // that this block could not have multiple predecessors since otherwise, the - // edge would be broken. - llvm::TinyPtrVector PredTerminators; - for (SILBasicBlock *PredBB : BB.getPredecessorBlocks()) { - auto *TermInst = PredBB->getTerminator(); - if (!isARCSignificantTerminator(TermInst)) - continue; - PredTerminators.push_back(TermInst); - } - - for (auto &OtherState : BBState.getBottomupStates()) { - // If the other state's value is blotted, skip it. - if (!OtherState.hasValue()) - continue; - - OtherState->second.updateForPredTerminators(PredTerminators, - SetFactory, AA); - } - return NestingDetected; } diff --git a/lib/SILOptimizer/ARC/GlobalLoopARCSequenceDataflow.cpp b/lib/SILOptimizer/ARC/GlobalLoopARCSequenceDataflow.cpp index c090a645eb6bd..46715ddabf139 100644 --- a/lib/SILOptimizer/ARC/GlobalLoopARCSequenceDataflow.cpp +++ b/lib/SILOptimizer/ARC/GlobalLoopARCSequenceDataflow.cpp @@ -200,40 +200,14 @@ bool LoopARCSequenceDataflowEvaluator::processLoopBottomUp( bool NestingDetected = false; // For each BB in our post order... - auto Start = R->subregion_begin(), End = R->subregion_end(); - if (Start == End) - return false; - - --End; - while (Start != End) { - unsigned SubregionIndex = *End; + for (unsigned SubregionIndex : R->getReverseSubregions()) { auto *Subregion = LRFI->getRegion(SubregionIndex); auto &SubregionData = getARCState(Subregion); // This will always succeed since we have an entry for each BB in our post // order. - LLVM_DEBUG(llvm::dbgs() << "Processing Subregion#: " << SubregionIndex - << "\n"); - - LLVM_DEBUG(llvm::dbgs() << "Merging Successors!\n"); - mergeSuccessors(Subregion, SubregionData); - - // Then perform the region optimization. - NestingDetected |= SubregionData.processBottomUp( - AA, RCFI, EAFI, LRFI, FreezeOwnedArgEpilogueReleases, IncToDecStateMap, - RegionStateInfo, SetFactory); - --End; - } - - { - unsigned SubregionIndex = *End; - auto *Subregion = LRFI->getRegion(SubregionIndex); - auto &SubregionData = getARCState(Subregion); - - // This will always succeed since we have an entry for each BB in our post - // order. - LLVM_DEBUG(llvm::dbgs() << "Processing Subregion#: " << SubregionIndex - << "\n"); + LLVM_DEBUG(llvm::dbgs() + << "Processing Subregion#: " << SubregionIndex << "\n"); LLVM_DEBUG(llvm::dbgs() << "Merging Successors!\n"); mergeSuccessors(Subregion, SubregionData); diff --git a/lib/SILOptimizer/ARC/RefCountState.cpp b/lib/SILOptimizer/ARC/RefCountState.cpp index e0c43fed19040..76337390c162f 100644 --- a/lib/SILOptimizer/ARC/RefCountState.cpp +++ b/lib/SILOptimizer/ARC/RefCountState.cpp @@ -241,14 +241,11 @@ bool BottomUpRefCountState::handleGuaranteedUser( // Advance the sequence... switch (LatState) { - // If were decremented, insert the insertion point. case LatticeState::Decremented: { LatState = LatticeState::MightBeDecremented; return true; } case LatticeState::MightBeUsed: - // If we have a might be used, we already created an insertion point - // earlier. Just move to MightBeDecremented. LatState = LatticeState::MightBeDecremented; return true; case LatticeState::MightBeDecremented: @@ -288,9 +285,6 @@ handleRefCountInstMatch(SILInstruction *RefCountInst) { return false; case LatticeState::Decremented: case LatticeState::MightBeUsed: - // Unset InsertPt so we remove retain release pairs instead of - // performing code motion. - LLVM_FALLTHROUGH; case LatticeState::MightBeDecremented: return true; } @@ -503,40 +497,6 @@ void BottomUpRefCountState::updateForDifferentLoopInst( << getRCRoot()); } -void BottomUpRefCountState::updateForPredTerminators( - ArrayRef Terms, - ImmutablePointerSetFactory &SetFactory, AliasAnalysis *AA) { - // If this state is not tracking anything, there is nothing to update. - if (!isTrackingRefCount()) - return; - - if (valueCanBeGuaranteedUsedGivenLatticeState() && - std::any_of(Terms.begin(), Terms.end(), - [this, &AA](SILInstruction *I) -> bool { - return mayGuaranteedUseValue(I, getRCRoot(), AA); - })) { - handleGuaranteedUser(getRCRoot(), SetFactory, AA); - return; - } - - if (valueCanBeDecrementedGivenLatticeState() && - std::any_of(Terms.begin(), Terms.end(), - [this, &AA](SILInstruction *I) -> bool { - return mayDecrementRefCount(I, getRCRoot(), AA); - })) { - handleDecrement(); - return; - } - - if (!valueCanBeUsedGivenLatticeState() || - std::none_of(Terms.begin(), Terms.end(), - [this, &AA](SILInstruction *I) - -> bool { return mayHaveSymmetricInterference(I, getRCRoot(), AA); })) - return; - - handleUser(getRCRoot(), SetFactory, AA); -} - //===----------------------------------------------------------------------===// // Top Down Ref Count State //===----------------------------------------------------------------------===// @@ -705,14 +665,11 @@ bool TopDownRefCountState::handleGuaranteedUser( "Must be able to be used at this point of the lattice."); // Advance the sequence... switch (LatState) { - // If were decremented, insert the insertion point. case LatticeState::Incremented: { LatState = LatticeState::MightBeUsed; return true; } case LatticeState::MightBeDecremented: - // If we have a might be used, we already created an insertion point - // earlier. Just move to MightBeDecremented. LatState = LatticeState::MightBeUsed; return true; case LatticeState::MightBeUsed: diff --git a/lib/SILOptimizer/ARC/RefCountState.h b/lib/SILOptimizer/ARC/RefCountState.h index 1bfb1ab44e133..c234ce0680327 100644 --- a/lib/SILOptimizer/ARC/RefCountState.h +++ b/lib/SILOptimizer/ARC/RefCountState.h @@ -185,17 +185,13 @@ class BottomUpRefCountState : public RefCountState { bool initWithMutatorInst(ImmutablePointerSet *I, RCIdentityFunctionInfo *RCFI); - /// Update this reference count's state given the instruction \p I. \p - /// InsertPt is the point furthest up the CFG where we can move the currently - /// tracked reference count. + /// Update this reference count's state given the instruction \p I. void updateForSameLoopInst(SILInstruction *I, ImmutablePointerSetFactory &SetFactory, AliasAnalysis *AA); - /// Update this reference count's state given the instruction \p I. \p - /// InsertPts are the points furthest up the CFG where we can move the - /// currently tracked reference count. + /// Update this reference count's state given the instruction \p I. // /// The main difference in between this routine and update for same loop inst /// is that if we see any decrements on a value, we treat it as being @@ -205,13 +201,6 @@ class BottomUpRefCountState : public RefCountState { ImmutablePointerSetFactory &SetFactory, AliasAnalysis *AA); - // Determine the conservative effect of the given list of predecessor - // terminators upon this reference count. - void updateForPredTerminators( - ArrayRef PredTerms, - ImmutablePointerSetFactory &SetFactory, - AliasAnalysis *AA); - /// Attempt to merge \p Other into this ref count state. Return true if we /// succeed and false otherwise. bool merge(const BottomUpRefCountState &Other); @@ -251,9 +240,7 @@ class BottomUpRefCountState : public RefCountState { bool valueCanBeUsedGivenLatticeState() const; /// Given the current lattice state, if we have seen a use, advance the - /// lattice state. Return true if we do so and false otherwise. \p InsertPt is - /// the location where if \p PotentialUser is a user of this ref count, we - /// would insert a release. + /// lattice state. Return true if we do so and false otherwise. bool handleUser(SILValue RCIdentity, ImmutablePointerSetFactory &SetFactory, AliasAnalysis *AA); @@ -271,9 +258,7 @@ class BottomUpRefCountState : public RefCountState { bool valueCanBeGuaranteedUsedGivenLatticeState() const; /// Given the current lattice state, if we have seen a use, advance the - /// lattice state. Return true if we do so and false otherwise. \p InsertPt is - /// the location where if \p PotentialUser is a user of this ref count, we - /// would insert a release. + /// lattice state. Return true if we do so and false otherwise. bool handleGuaranteedUser(SILValue RCIdentity, ImmutablePointerSetFactory &SetFactory, @@ -345,17 +330,13 @@ class TopDownRefCountState : public RefCountState { /// Uninitialize the current state. void clear(); - /// Update this reference count's state given the instruction \p I. \p - /// InsertPt is the point furthest up the CFG where we can move the currently - /// tracked reference count. + /// Update this reference count's state given the instruction \p I. void updateForSameLoopInst(SILInstruction *I, ImmutablePointerSetFactory &SetFactory, AliasAnalysis *AA); - /// Update this reference count's state given the instruction \p I. \p - /// InsertPts are the points furthest up the CFG where we can move the - /// currently tracked reference count. + /// Update this reference count's state given the instruction \p I. /// /// The main difference in between this routine and update for same loop inst /// is that if we see any decrements on a value, we treat it as being diff --git a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp index 594cb81485a8c..c651cb5bf2943 100644 --- a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp @@ -1623,6 +1623,13 @@ void EscapeAnalysis::ConnectionGraph::verify() const { if (auto ai = dyn_cast(&i)) { if (EA->canOptimizeArrayUninitializedCall(ai).isValid()) continue; + // Ignore checking CGNode mapping for result of apply to a no return + // function that will have a null ReturnNode + if (auto *callee = ai->getReferencedFunctionOrNull()) { + if (EA->getFunctionInfo(callee)->isValid()) + if (!EA->getConnectionGraph(callee)->getReturnNodeOrNull()) + continue; + } } for (auto result : i.getResults()) { if (EA->getPointerBase(result)) diff --git a/lib/SILOptimizer/Analysis/LoopRegionAnalysis.cpp b/lib/SILOptimizer/Analysis/LoopRegionAnalysis.cpp index ad6a9f10327b5..2050c2d9c9b2d 100644 --- a/lib/SILOptimizer/Analysis/LoopRegionAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/LoopRegionAnalysis.cpp @@ -45,8 +45,8 @@ LoopRegion::FunctionTy *LoopRegion::getFunction() const { return Ptr.get(); } -void LoopRegion::dump() const { - print(llvm::outs()); +void LoopRegion::dump(bool isVerbose) const { + print(llvm::outs(), false, isVerbose); llvm::outs() << "\n"; } @@ -69,7 +69,8 @@ void LoopRegion::printName(llvm::raw_ostream &os) const { return; } -void LoopRegion::print(llvm::raw_ostream &os, bool isShort) const { +void LoopRegion::print(llvm::raw_ostream &os, bool isShort, + bool isVerbose) const { os << "(region id:" << ID; if (isShort) { os << ")"; @@ -88,6 +89,20 @@ void LoopRegion::print(llvm::raw_ostream &os, bool isShort) const { os << " ucfh:" << (IsUnknownControlFlowEdgeHead? "true " : "false") << " ucft:" << (IsUnknownControlFlowEdgeTail? "true " : "false"); + + if (!isVerbose) { + return; + } + os << "\n"; + if (isBlock()) { + getBlock()->dump(); + } else if (isLoop()) { + getLoop()->dump(); + } else if (isFunction()) { + getFunction()->dump(); + } else { + llvm_unreachable("Unknown region type"); + } } llvm::raw_ostream &llvm::operator<<(llvm::raw_ostream &os, LoopRegion &LR) { diff --git a/lib/SILOptimizer/CMakeLists.txt b/lib/SILOptimizer/CMakeLists.txt index 4bf45e0ebd8db..ec1440d2b06a1 100644 --- a/lib/SILOptimizer/CMakeLists.txt +++ b/lib/SILOptimizer/CMakeLists.txt @@ -12,6 +12,7 @@ add_subdirectory(LoopTransforms) add_subdirectory(Mandatory) add_subdirectory(PassManager) add_subdirectory(SILCombiner) +add_subdirectory(SemanticARC) add_subdirectory(Transforms) add_subdirectory(UtilityPasses) add_subdirectory(Utils) diff --git a/lib/SILOptimizer/Differentiation/JVPCloner.cpp b/lib/SILOptimizer/Differentiation/JVPCloner.cpp index 8152f409d7592..2586e5ac6ad2e 100644 --- a/lib/SILOptimizer/Differentiation/JVPCloner.cpp +++ b/lib/SILOptimizer/Differentiation/JVPCloner.cpp @@ -455,18 +455,6 @@ class JVPCloner::Implementation final return; } - // Diagnose functions with active inout arguments. - // TODO(TF-129): Support `inout` argument differentiation. - for (auto inoutArg : ai->getInoutArguments()) { - if (activityInfo.isActive(inoutArg, getIndices())) { - context.emitNondifferentiabilityError( - ai, invoker, - diag::autodiff_cannot_differentiate_through_inout_arguments); - errorOccurred = true; - return; - } - } - auto loc = ai->getLoc(); auto &builder = getBuilder(); auto origCallee = getOpValue(ai->getCallee()); @@ -565,9 +553,14 @@ class JVPCloner::Implementation final if (!originalFnTy->getParameters()[paramIndex] .getSILStorageInterfaceType() .isDifferentiable(getModule())) { - context.emitNondifferentiabilityError( - ai->getArgumentsWithoutIndirectResults()[paramIndex], - invoker, diag::autodiff_nondifferentiable_argument); + auto arg = ai->getArgumentsWithoutIndirectResults()[paramIndex]; + auto startLoc = arg.getLoc().getStartSourceLoc(); + auto endLoc = arg.getLoc().getEndSourceLoc(); + context + .emitNondifferentiabilityError( + arg, invoker, diag::autodiff_nondifferentiable_argument) + .fixItInsert(startLoc, "withoutDerivative(at: ") + .fixItInsertAfter(endLoc, ")"); errorOccurred = true; return true; } @@ -585,9 +578,14 @@ class JVPCloner::Implementation final .getSILStorageInterfaceType(); } if (!remappedResultType.isDifferentiable(getModule())) { - context.emitNondifferentiabilityError( - origCallee, invoker, - diag::autodiff_nondifferentiable_result); + auto startLoc = ai->getLoc().getStartSourceLoc(); + auto endLoc = ai->getLoc().getEndSourceLoc(); + context + .emitNondifferentiabilityError( + origCallee, invoker, + diag::autodiff_nondifferentiable_result) + .fixItInsert(startLoc, "withoutDerivative(at: ") + .fixItInsertAfter(endLoc, ")"); errorOccurred = true; return true; } @@ -704,9 +702,11 @@ class JVPCloner::Implementation final getModule(), jvpSubstMap, TypeExpansionContext::minimal()); differentialType = differentialType.subst(getModule(), jvpSubstMap); auto differentialFnType = differentialType.castTo(); - auto differentialSubstType = differentialPartialApply->getType().castTo(); + + // If necessary, convert the differential value to the returned differential + // function type. SILValue differentialValue; if (differentialSubstType == differentialFnType) { differentialValue = differentialPartialApply; @@ -717,11 +717,8 @@ class JVPCloner::Implementation final loc, differentialPartialApply, differentialType, /*withoutActuallyEscaping*/ false); } else { - // When `diag::autodiff_loadable_value_addressonly_tangent_unsupported` - // applies, the return type may be ABI-incomaptible with the type of the - // partially applied differential. In these cases, produce an undef and - // rely on other code to emit a diagnostic. - differentialValue = SILUndef::get(differentialType, *jvp); + llvm::report_fatal_error("Differential value type is not ABI-compatible " + "with the returned differential type"); } // Return a tuple of the original result and differential. @@ -1242,6 +1239,10 @@ class JVPCloner::Implementation final SmallVector differentialAllResults; collectAllActualResultsInTypeOrder( differentialCall, differentialDirectResults, differentialAllResults); + for (auto inoutArg : ai->getInoutArguments()) + origAllResults.push_back(inoutArg); + for (auto inoutArg : differentialCall->getInoutArguments()) + differentialAllResults.push_back(inoutArg); assert(applyIndices.results->getNumIndices() == differentialAllResults.size()); @@ -1485,11 +1486,14 @@ void JVPCloner::Implementation::prepareForDifferentialGeneration() { auto origIndResults = original->getIndirectResults(); auto diffIndResults = differential.getIndirectResults(); #ifndef NDEBUG - unsigned numInoutParameters = llvm::count_if( - original->getLoweredFunctionType()->getParameters(), - [](SILParameterInfo paramInfo) { return paramInfo.isIndirectInOut(); }); - assert(origIndResults.size() + numInoutParameters == diffIndResults.size()); + unsigned numNonWrtInoutParameters = llvm::count_if( + range(original->getLoweredFunctionType()->getNumParameters()), + [&] (unsigned i) { + auto ¶mInfo = original->getLoweredFunctionType()->getParameters()[i]; + return paramInfo.isIndirectInOut() && !getIndices().parameters->contains(i); + }); #endif + assert(origIndResults.size() + numNonWrtInoutParameters == diffIndResults.size()); for (auto &origBB : *original) for (auto i : indices(origIndResults)) setTangentBuffer(&origBB, origIndResults[i], diffIndResults[i]); @@ -1522,23 +1526,10 @@ void JVPCloner::Implementation::prepareForDifferentialGeneration() { auto origParams = origTy->getParameters(); auto indices = witness->getSILAutoDiffIndices(); - // Add differential results. - Optional inoutDiffParam = None; - for (auto origParam : origTy->getParameters()) { - if (!origParam.isIndirectInOut()) - continue; - inoutDiffParam = origParam; - } - - if (inoutDiffParam) { - dfResults.push_back( - SILResultInfo(inoutDiffParam->getInterfaceType() - ->getAutoDiffTangentSpace(lookupConformance) - ->getType() - ->getCanonicalType(witnessCanGenSig), - ResultConvention::Indirect)); - } else { - for (auto resultIndex : indices.results->getIndices()) { + + for (auto resultIndex : indices.results->getIndices()) { + if (resultIndex < origTy->getNumResults()) { + // Handle formal original result. auto origResult = origTy->getResults()[resultIndex]; origResult = origResult.getWithInterfaceType( origResult.getInterfaceType()->getCanonicalType(witnessCanGenSig)); @@ -1549,6 +1540,25 @@ void JVPCloner::Implementation::prepareForDifferentialGeneration() { ->getCanonicalType(witnessCanGenSig), origResult.getConvention())); } + else { + // Handle original `inout` parameter. + auto inoutParamIndex = resultIndex - origTy->getNumResults(); + auto inoutParamIt = std::next( + origTy->getIndirectMutatingParameters().begin(), inoutParamIndex); + auto paramIndex = + std::distance(origTy->getParameters().begin(), &*inoutParamIt); + // If the original `inout` parameter is a differentiability parameter, then + // it already has a corresponding differential parameter. Skip adding a + // corresponding differential result. + if (indices.parameters->contains(paramIndex)) + continue; + auto inoutParam = origTy->getParameters()[paramIndex]; + auto paramTan = inoutParam.getInterfaceType()->getAutoDiffTangentSpace( + lookupConformance); + assert(paramTan && "Parameter type does not have a tangent space?"); + dfResults.push_back( + {paramTan->getCanonicalType(), ResultConvention::Indirect}); + } } // Add differential parameters for the requested wrt parameters. diff --git a/lib/SILOptimizer/Differentiation/PullbackCloner.cpp b/lib/SILOptimizer/Differentiation/PullbackCloner.cpp index 79611c38eaaf4..7b0c3c62fda76 100644 --- a/lib/SILOptimizer/Differentiation/PullbackCloner.cpp +++ b/lib/SILOptimizer/Differentiation/PullbackCloner.cpp @@ -1721,22 +1721,36 @@ bool PullbackCloner::Implementation::run() { domOrder.pushChildren(bb); } - // Create pullback blocks and arguments, visiting original blocks in - // post-order post-dominance order. - SmallVector postOrderPostDomOrder; - // Start from the root node, which may have a marker `nullptr` block if - // there are multiple roots. - PostOrderPostDominanceOrder postDomOrder(postDomInfo->getRootNode(), - postOrderInfo, original.size()); - while (auto *origNode = postDomOrder.getNext()) { - auto *origBB = origNode->getBlock(); - postDomOrder.pushChildren(origNode); - // If node is the `nullptr` marker basic block, do not push it. - if (!origBB) - continue; - postOrderPostDomOrder.push_back(origBB); + // Create pullback blocks and arguments, visiting original blocks using BFS + // starting from the original exit block. Unvisited original basic blocks + // (e.g unreachable blocks) are not relevant for pullback generation and thus + // ignored. + // The original blocks in traversal order for pullback generation. + SmallVector originalBlocks; + // The set of visited original blocks. + SmallDenseSet visitedBlocks; + + // Perform BFS from the original exit block. + { + std::deque worklist = {}; + worklist.push_back(origExit); + visitedBlocks.insert(origExit); + while (!worklist.empty()) { + auto *BB = worklist.front(); + worklist.pop_front(); + + originalBlocks.push_back(BB); + + for (auto *nextBB : BB->getPredecessorBlocks()) { + if (!visitedBlocks.count(nextBB)) { + worklist.push_back(nextBB); + visitedBlocks.insert(nextBB); + } + } + } } - for (auto *origBB : postOrderPostDomOrder) { + + for (auto *origBB : originalBlocks) { auto *pullbackBB = pullback.createBasicBlock(); pullbackBBMap.insert({origBB, pullbackBB}); auto pbStructLoweredType = @@ -1801,6 +1815,9 @@ bool PullbackCloner::Implementation::run() { // struct argument. They branch from a pullback successor block to the // pullback original block, passing adjoint values of active values. for (auto *succBB : origBB->getSuccessorBlocks()) { + // Skip generating pullback block for original unreachable blocks. + if (!visitedBlocks.count(succBB)) + continue; auto *pullbackTrampolineBB = pullback.createBasicBlockBefore(pullbackBB); pullbackTrampolineBBMap.insert({{origBB, succBB}, pullbackTrampolineBB}); // Get the enum element type (i.e. the pullback struct type). The enum @@ -1870,7 +1887,7 @@ bool PullbackCloner::Implementation::run() { // Visit original blocks blocks in post-order and perform differentiation // in corresponding pullback blocks. If errors occurred, back out. else { - for (auto *bb : postOrderPostDomOrder) { + for (auto *bb : originalBlocks) { visitSILBasicBlock(bb); if (errorOccurred) return true; @@ -2018,12 +2035,10 @@ void PullbackCloner::Implementation::accumulateAdjointForOptional( SILBasicBlock *bb, SILValue optionalValue, SILValue wrappedAdjoint) { auto pbLoc = getPullback().getLocation(); // Handle `switch_enum` on `Optional`. - auto *optionalEnumDecl = getASTContext().getOptionalDecl(); - auto optionalTy = optionalValue->getType(); - assert(optionalTy.getASTType().getEnumOrBoundGenericEnum() == - optionalEnumDecl); // `Optional` - optionalTy = remapType(optionalTy); + auto optionalTy = remapType(optionalValue->getType()); + assert(optionalTy.getASTType().getEnumOrBoundGenericEnum() == + getASTContext().getOptionalDecl()); // `T` auto wrappedType = optionalTy.getOptionalObjectType(); // `T.TangentVector` @@ -2056,8 +2071,8 @@ void PullbackCloner::Implementation::accumulateAdjointForOptional( // Find `Optional.some` EnumElementDecl. auto someEltDecl = builder.getASTContext().getOptionalSomeDecl(); - // Initialize a `Optional` buffer from `wrappedAdjoint`as the - // input for `Optional.TangentVector.init`. + // Initialize an `Optional` buffer from `wrappedAdjoint` as + // the input for `Optional.TangentVector.init`. auto *optArgBuf = builder.createAllocStack(pbLoc, optionalOfWrappedTanType); if (optionalOfWrappedTanType.isLoadableOrOpaque(builder.getFunction())) { // %enum = enum $Optional, #Optional.some!enumelt, @@ -2066,7 +2081,7 @@ void PullbackCloner::Implementation::accumulateAdjointForOptional( optionalOfWrappedTanType); // store %enum to %optArgBuf builder.emitStoreValueOperation(pbLoc, enumInst, optArgBuf, - StoreOwnershipQualifier::Trivial); + StoreOwnershipQualifier::Init); } else { // %enumAddr = init_enum_data_addr %optArgBuf $Optional, // #Optional.some!enumelt @@ -2279,14 +2294,15 @@ void PullbackCloner::Implementation::visitSILBasicBlock(SILBasicBlock *bb) { for (auto pair : incomingValues) { auto *predBB = std::get<0>(pair); auto incomingValue = std::get<1>(pair); - blockTemporaries[getPullbackBlock(predBB)].insert(concreteBBArgAdjCopy); // Handle `switch_enum` on `Optional`. auto termInst = bbArg->getSingleTerminator(); - if (isSwitchEnumInstOnOptional(termInst)) + if (isSwitchEnumInstOnOptional(termInst)) { accumulateAdjointForOptional(bb, incomingValue, concreteBBArgAdjCopy); - else + } else { + blockTemporaries[getPullbackBlock(predBB)].insert(concreteBBArgAdjCopy); setAdjointValue(predBB, incomingValue, makeConcreteAdjointValue(concreteBBArgAdjCopy)); + } } break; } @@ -2413,7 +2429,7 @@ bool PullbackCloner::Implementation::runForSemanticMemberGetter() { // Switch based on the base tangent struct's value category. // TODO(TF-1255): Simplify using unified adjoint value data structure. - switch (tangentVectorSILTy.getCategory()) { + switch (getTangentValueCategory(origSelf)) { case SILValueCategory::Object: { auto adjResult = getAdjointValue(origEntry, origResult); switch (adjResult.getKind()) { @@ -2454,7 +2470,7 @@ bool PullbackCloner::Implementation::runForSemanticMemberGetter() { if (field == tanField) { // Switch based on the property's value category. // TODO(TF-1255): Simplify using unified adjoint value data structure. - switch (origResult->getType().getCategory()) { + switch (getTangentValueCategory(origResult)) { case SILValueCategory::Object: { auto adjResult = getAdjointValue(origEntry, origResult); auto adjResultValue = materializeAdjointDirect(adjResult, pbLoc); diff --git a/lib/SILOptimizer/Differentiation/VJPCloner.cpp b/lib/SILOptimizer/Differentiation/VJPCloner.cpp index ef3980436d9d1..f58db200debe9 100644 --- a/lib/SILOptimizer/Differentiation/VJPCloner.cpp +++ b/lib/SILOptimizer/Differentiation/VJPCloner.cpp @@ -201,9 +201,11 @@ class VJPCloner::Implementation final getModule(), vjpSubstMap, TypeExpansionContext::minimal()); pullbackType = pullbackType.subst(getModule(), vjpSubstMap); auto pullbackFnType = pullbackType.castTo(); - auto pullbackSubstType = pullbackPartialApply->getType().castTo(); + + // If necessary, convert the pullback value to the returned pullback + // function type. SILValue pullbackValue; if (pullbackSubstType == pullbackFnType) { pullbackValue = pullbackPartialApply; @@ -213,11 +215,8 @@ class VJPCloner::Implementation final builder.createConvertFunction(loc, pullbackPartialApply, pullbackType, /*withoutActuallyEscaping*/ false); } else { - // When `diag::autodiff_loadable_value_addressonly_tangent_unsupported` - // applies, the return type may be ABI-incomaptible with the type of the - // partially applied pullback. In these cases, produce an undef and rely - // on other code to emit a diagnostic. - pullbackValue = SILUndef::get(pullbackType, *vjp); + llvm::report_fatal_error("Pullback value type is not ABI-compatible " + "with the returned pullback type"); } // Return a tuple of the original result and pullback. @@ -458,9 +457,14 @@ class VJPCloner::Implementation final if (!originalFnTy->getParameters()[paramIndex] .getSILStorageInterfaceType() .isDifferentiable(getModule())) { - context.emitNondifferentiabilityError( - ai->getArgumentsWithoutIndirectResults()[paramIndex], invoker, - diag::autodiff_nondifferentiable_argument); + auto arg = ai->getArgumentsWithoutIndirectResults()[paramIndex]; + auto startLoc = arg.getLoc().getStartSourceLoc(); + auto endLoc = arg.getLoc().getEndSourceLoc(); + context + .emitNondifferentiabilityError( + arg, invoker, diag::autodiff_nondifferentiable_argument) + .fixItInsert(startLoc, "withoutDerivative(at: ") + .fixItInsertAfter(endLoc, ")"); errorOccurred = true; return true; } @@ -478,8 +482,14 @@ class VJPCloner::Implementation final .getSILStorageInterfaceType(); } if (!remappedResultType.isDifferentiable(getModule())) { - context.emitNondifferentiabilityError( - origCallee, invoker, diag::autodiff_nondifferentiable_result); + auto startLoc = ai->getLoc().getStartSourceLoc(); + auto endLoc = ai->getLoc().getEndSourceLoc(); + context + .emitNondifferentiabilityError( + origCallee, invoker, + diag::autodiff_nondifferentiable_result) + .fixItInsert(startLoc, "withoutDerivative(at: ") + .fixItInsertAfter(endLoc, ")"); errorOccurred = true; return true; } @@ -618,6 +628,18 @@ class VJPCloner::Implementation final getOpValue(origCallee)->getDefiningInstruction()); } + void visitTryApplyInst(TryApplyInst *tai) { + // Build pullback struct value for original block. + auto *pbStructVal = buildPullbackValueStructValue(tai); + // Create a new `try_apply` instruction. + auto args = getOpValueArray<8>(tai->getArguments()); + getBuilder().createTryApply( + tai->getLoc(), getOpValue(tai->getCallee()), + getOpSubstitutionMap(tai->getSubstitutionMap()), args, + createTrampolineBasicBlock(tai, pbStructVal, tai->getNormalBB()), + createTrampolineBasicBlock(tai, pbStructVal, tai->getErrorBB())); + } + void visitDifferentiableFunctionInst(DifferentiableFunctionInst *dfi) { // Clone `differentiable_function` from original to VJP, then add the cloned // instruction to the `differentiable_function` worklist. diff --git a/lib/SILOptimizer/IPO/CrossModuleSerializationSetup.cpp b/lib/SILOptimizer/IPO/CrossModuleSerializationSetup.cpp index ea8429c854876..ce00fdd8b8e43 100644 --- a/lib/SILOptimizer/IPO/CrossModuleSerializationSetup.cpp +++ b/lib/SILOptimizer/IPO/CrossModuleSerializationSetup.cpp @@ -337,9 +337,6 @@ bool CrossModuleSerializationSetup::canSerialize(SILInstruction *inst, }); return canUse; } - if (auto *GAI = dyn_cast(inst)) { - return !GAI->getReferencedGlobal()->getName().startswith("globalinit_"); - } if (auto *MI = dyn_cast(inst)) { return !MI->getMember().isForeign; } diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp index 113d71ccb32b8..1c34038499262 100644 --- a/lib/SILOptimizer/IPO/GlobalOpt.cpp +++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp @@ -260,7 +260,7 @@ void SILGlobalOpt::collectOnceCall(BuiltinInst *BI) { UnhandledOnceCallee = true; return; } - if (!Callee->getName().startswith("globalinit_")) + if (!Callee->isGlobalInitOnceFunction()) return; // We currently disable optimizing the initializer if a globalinit_func diff --git a/lib/SILOptimizer/LoopTransforms/LICM.cpp b/lib/SILOptimizer/LoopTransforms/LICM.cpp index e4be5ac35f5fa..69a0f32be343d 100644 --- a/lib/SILOptimizer/LoopTransforms/LICM.cpp +++ b/lib/SILOptimizer/LoopTransforms/LICM.cpp @@ -214,8 +214,8 @@ static void getDominatingBlocks(SmallVectorImpl &domBlocks, SILLoop *Loop, DominanceInfo *DT) { auto HeaderBB = Loop->getHeader(); auto DTRoot = DT->getNode(HeaderBB); - SmallVector ExitingBBs; - Loop->getExitingBlocks(ExitingBBs); + SmallVector ExitingAndLatchBBs; + Loop->getExitingAndLatchBlocks(ExitingAndLatchBBs); for (llvm::df_iterator It = llvm::df_begin(DTRoot), E = llvm::df_end(DTRoot); It != E;) { @@ -223,7 +223,7 @@ static void getDominatingBlocks(SmallVectorImpl &domBlocks, // Don't decent into control-dependent code. Only traverse into basic blocks // that dominate all exits. - if (!std::all_of(ExitingBBs.begin(), ExitingBBs.end(), + if (!std::all_of(ExitingAndLatchBBs.begin(), ExitingAndLatchBBs.end(), [=](SILBasicBlock *ExitBB) { return DT->dominates(CurBB, ExitBB); })) { diff --git a/lib/SILOptimizer/Mandatory/Differentiation.cpp b/lib/SILOptimizer/Mandatory/Differentiation.cpp index 5156ffac9e792..083f840e892e7 100644 --- a/lib/SILOptimizer/Mandatory/Differentiation.cpp +++ b/lib/SILOptimizer/Mandatory/Differentiation.cpp @@ -158,8 +158,7 @@ static bool diagnoseNoReturn(ADContext &context, SILFunction *original, /// flow unsupported" error at appropriate source locations. Returns true if /// error is emitted. /// -/// Update as control flow support is added. Currently, branching terminators -/// other than `br`, `cond_br`, `switch_enum` are not supported. +/// Update as control flow support is added. static bool diagnoseUnsupportedControlFlow(ADContext &context, SILFunction *original, DifferentiationInvoker invoker) { @@ -173,7 +172,7 @@ static bool diagnoseUnsupportedControlFlow(ADContext &context, isa(term) || isa(term) || isa(term) || isa(term) || - isa(term)) + isa(term) || isa(term)) continue; // If terminator is an unsupported branching terminator, emit an error. if (term->isBranch()) { @@ -1330,7 +1329,7 @@ bool DifferentiationTransformer::processLinearFunctionInst( cast(lfi)); PrettyStackTraceSILFunction fnTrace("...in", lfi->getFunction()); LLVM_DEBUG({ - auto &s = getADDebugStream() << "Processing LinearFunctoinInst:\n"; + auto &s = getADDebugStream() << "Processing LinearFunctionInst:\n"; lfi->printInContext(s); }); @@ -1385,8 +1384,8 @@ void Differentiation::run() { if (auto *dfi = dyn_cast(&i)) { context.getDifferentiableFunctionInstWorklist().push_back(dfi); } else if (auto *lfi = dyn_cast(&i)) { - // If linear map transposition is not enable and an uncanonical - // `linear_function` instruction is encounter, emit a diagnostic. + // If linear map transposition is not enabled and an uncanonical + // `linear_function` instruction is encountered, emit a diagnostic. // FIXME(SR-11850): Finish support for linear map transposition. if (!EnableExperimentalLinearMapTransposition) { if (!lfi->hasTransposeFunction()) { diff --git a/lib/SILOptimizer/SemanticARC/CMakeLists.txt b/lib/SILOptimizer/SemanticARC/CMakeLists.txt new file mode 100644 index 0000000000000..7ae8f36a2bbde --- /dev/null +++ b/lib/SILOptimizer/SemanticARC/CMakeLists.txt @@ -0,0 +1,2 @@ +target_sources(swiftSILOptimizer PRIVATE + SemanticARCOpts.cpp) diff --git a/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp b/lib/SILOptimizer/SemanticARC/SemanticARCOpts.cpp similarity index 97% rename from lib/SILOptimizer/Transforms/SemanticARCOpts.cpp rename to lib/SILOptimizer/SemanticARC/SemanticARCOpts.cpp index 45a05e6c0db3c..180f3882a7807 100644 --- a/lib/SILOptimizer/Transforms/SemanticARCOpts.cpp +++ b/lib/SILOptimizer/SemanticARC/SemanticARCOpts.cpp @@ -245,6 +245,10 @@ class OwnershipLiveRange { TransformRange, OperandToUser>; DestroyingInstsRange getDestroyingInsts() const; + using ConsumingInstsRange = + TransformRange, OperandToUser>; + ConsumingInstsRange getAllConsumingInsts() const; + /// If this LiveRange has a single destroying use, return that use. Otherwise, /// return nullptr. Operand *getSingleDestroyingUse() const { @@ -335,6 +339,11 @@ OwnershipLiveRange::getDestroyingInsts() const { return DestroyingInstsRange(getDestroyingUses(), OperandToUser()); } +OwnershipLiveRange::ConsumingInstsRange +OwnershipLiveRange::getAllConsumingInsts() const { + return ConsumingInstsRange(consumingUses, OperandToUser()); +} + OwnershipLiveRange::OwnershipLiveRange(SILValue value) : introducer(*OwnedValueIntroducer::get(value)), destroyingUses(), ownershipForwardingUses(), unknownConsumingUses() { @@ -464,36 +473,17 @@ void OwnershipLiveRange::insertEndBorrowsAtDestroys( // // TODO: Hoist this out? SILInstruction *inst = introducer.value->getDefiningInstruction(); + Optional analysis; if (!inst) { - // If our introducer was not for an inst, it should be from an arg. In such - // a case, we handle one of two cases: - // - // 1. If we have one destroy and that destroy is the initial instruction in - // the arguments block, we just insert the end_borrow here before the - // destroy_value and bail. If the destroy is not the initial instruction in - // the arg block, we delegate to the ValueLifetimeAnalysis code. - // - // 2. If we have multiple destroys, by the properties of owned values having - // a linear lifetime, we know that the destroys can not both be first in the - // args block since the only way that we could have two such destroys in the - // arg's block is if we destructured the arg. In such a case, the - // destructure instruction would have to be between the argument and any - // destroy meaning the destroys could not be first. In such a case, we - // delegate to the ValueLifetimeAnalysis code. - auto *arg = cast(introducer.value); - auto *beginInst = &*arg->getParent()->begin(); - if (auto *singleDestroyingUse = getSingleDestroyingUse()) { - if (singleDestroyingUse->getUser() == beginInst) { - auto loc = RegularLocation::getAutoGeneratedLocation(); - SILBuilderWithScope builder(beginInst); - builder.createEndBorrow(loc, newGuaranteedValue); - return; - } - } - inst = beginInst; + analysis.emplace(cast(introducer.value), + getAllConsumingInsts()); + } else { + analysis.emplace(inst, getAllConsumingInsts()); } - ValueLifetimeAnalysis analysis(inst, getDestroyingInsts()); - bool foundCriticalEdges = !analysis.computeFrontier( + + // Use all consuming uses in our value lifetime analysis to ensure correctness + // in the face of unreachable code. + bool foundCriticalEdges = !analysis->computeFrontier( scratch, ValueLifetimeAnalysis::DontModifyCFG, &deadEndBlocks); (void)foundCriticalEdges; assert(!foundCriticalEdges); @@ -1044,8 +1034,8 @@ struct SemanticARCOptVisitor } // end anonymous namespace static llvm::cl::opt -VerifyAfterTransform("sil-semantic-arc-opts-verify-after-transform", - llvm::cl::init(false), llvm::cl::Hidden); + VerifyAfterTransform("sil-semantic-arc-opts-verify-after-transform", + llvm::cl::init(false), llvm::cl::Hidden); static bool canEliminatePhi( SemanticARCOptVisitor::FrozenMultiMapRange optimizableIntroducerRange, @@ -1446,7 +1436,8 @@ bool SemanticARCOptVisitor::visitBeginBorrowInst(BeginBorrowInst *bbi) { // are within the borrow scope. // // TODO: This needs a better name. -bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst *cvi) { +bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization( + CopyValueInst *cvi) { // For now, do not run this optimization. This is just to be careful. if (onlyGuaranteedOpts) return false; @@ -1627,7 +1618,8 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst /// If cvi only has destroy value users, then cvi is a dead live range. Lets /// eliminate all such dead live ranges. -bool SemanticARCOptVisitor::eliminateDeadLiveRangeCopyValue(CopyValueInst *cvi) { +bool SemanticARCOptVisitor::eliminateDeadLiveRangeCopyValue( + CopyValueInst *cvi) { // This is a cheap optimization generally. // See if we are lucky and have a simple case. @@ -1867,8 +1859,7 @@ namespace { /// written to again. In both cases, we can convert load [copy] -> load_borrow /// safely. class StorageGuaranteesLoadVisitor - : public AccessUseDefChainVisitor -{ + : public AccessUseDefChainVisitor { // The outer SemanticARCOptVisitor. SemanticARCOptVisitor &ARCOpt; @@ -1877,7 +1868,7 @@ class StorageGuaranteesLoadVisitor // The current address being visited. SILValue currentAddress; - + Optional isWritten; public: @@ -1890,11 +1881,9 @@ class StorageGuaranteesLoadVisitor currentAddress = nullptr; isWritten = written; } - - void next(SILValue address) { - currentAddress = address; - } - + + void next(SILValue address) { currentAddress = address; } + void visitNestedAccess(BeginAccessInst *access) { // First see if we have read/modify. If we do not, just look through the // nested access. @@ -1911,9 +1900,7 @@ class StorageGuaranteesLoadVisitor // scope. If so, we may be able to use a load_borrow here! SmallVector endScopeUses; transform(access->getEndAccesses(), std::back_inserter(endScopeUses), - [](EndAccessInst *eai) { - return &eai->getAllOperands()[0]; - }); + [](EndAccessInst *eai) { return &eai->getAllOperands()[0]; }); SmallPtrSet visitedBlocks; LinearLifetimeChecker checker(visitedBlocks, ARCOpt.getDeadEndBlocks()); if (!checker.validateLifetime(access, endScopeUses, @@ -1940,7 +1927,7 @@ class StorageGuaranteesLoadVisitor return answer(true); } - + void visitArgumentAccess(SILFunctionArgument *arg) { // If this load_copy is from an indirect in_guaranteed argument, then we // know for sure that it will never be written to. @@ -2017,15 +2004,15 @@ class StorageGuaranteesLoadVisitor // able to also to promote load [copy] from such args to load_borrow. return answer(true); } - + void visitGlobalAccess(SILValue global) { return answer(!AccessedStorage(global, AccessedStorage::Global) - .isLetAccess(&ARCOpt.F)); + .isLetAccess(&ARCOpt.F)); } - + void visitClassAccess(RefElementAddrInst *field) { currentAddress = nullptr; - + // We know a let property won't be written to if the base object is // guaranteed for the duration of the access. // For non-let properties conservatively assume they may be written to. @@ -2081,15 +2068,13 @@ class StorageGuaranteesLoadVisitor baseObject, endScopeInsts, liveRange.getAllConsumingUses()); return answer(foundError); } - + // TODO: Handle other access kinds? void visitBase(SILValue base, AccessedStorage::Kind kind) { return answer(true); } - void visitNonAccess(SILValue addr) { - return answer(true); - } + void visitNonAccess(SILValue addr) { return answer(true); } void visitCast(SingleValueInstruction *cast, Operand *parentAddr) { return next(parentAddr->get()); diff --git a/lib/SILOptimizer/Transforms/CMakeLists.txt b/lib/SILOptimizer/Transforms/CMakeLists.txt index c51043a1910c3..ac3718b6cf20f 100644 --- a/lib/SILOptimizer/Transforms/CMakeLists.txt +++ b/lib/SILOptimizer/Transforms/CMakeLists.txt @@ -31,7 +31,6 @@ target_sources(swiftSILOptimizer PRIVATE RedundantLoadElimination.cpp RedundantOverflowCheckRemoval.cpp ReleaseDevirtualizer.cpp - SemanticARCOpts.cpp SILCodeMotion.cpp SILLowerAggregateInstrs.cpp SILMem2Reg.cpp diff --git a/lib/SILOptimizer/Transforms/CSE.cpp b/lib/SILOptimizer/Transforms/CSE.cpp index af2cef2882e4a..f62fa49cb3719 100644 --- a/lib/SILOptimizer/Transforms/CSE.cpp +++ b/lib/SILOptimizer/Transforms/CSE.cpp @@ -428,9 +428,6 @@ bool llvm::DenseMapInfo::isEqual(SimpleValue LHS, return false; // ... and other constraints are equal. - if (LHSArchetypeTy->requiresClass() != RHSArchetypeTy->requiresClass()) - return false; - if (LHSArchetypeTy->getSuperclass().getPointer() != RHSArchetypeTy->getSuperclass().getPointer()) return false; diff --git a/lib/SILOptimizer/Transforms/CopyForwarding.cpp b/lib/SILOptimizer/Transforms/CopyForwarding.cpp index f930a10dc92e0..ad7a41d52f5ad 100644 --- a/lib/SILOptimizer/Transforms/CopyForwarding.cpp +++ b/lib/SILOptimizer/Transforms/CopyForwarding.cpp @@ -537,7 +537,7 @@ class CopyForwarding { public: CopySrcUserVisitor(CopyForwarding &CPF) : CPF(CPF) {} - virtual bool visitNormalUse(SILInstruction *user) { + virtual bool visitNormalUse(SILInstruction *user) override { if (isa(user)) CPF.IsSrcLoadedFrom = true; @@ -549,18 +549,18 @@ class CopyForwarding { // Bail on multiple uses in the same instruction to avoid complexity. return CPF.SrcUserInsts.insert(user).second; } - virtual bool visitTake(CopyAddrInst *take) { + virtual bool visitTake(CopyAddrInst *take) override { if (take->getSrc() == take->getDest()) return false; CPF.TakePoints.push_back(take); return true; } - virtual bool visitDestroy(DestroyAddrInst *destroy) { + virtual bool visitDestroy(DestroyAddrInst *destroy) override { CPF.DestroyPoints.push_back(destroy); return true; } - virtual bool visitDebugValue(DebugValueAddrInst *debugValue) { + virtual bool visitDebugValue(DebugValueAddrInst *debugValue) override { return CPF.SrcDebugValueInsts.insert(debugValue).second; } }; @@ -635,17 +635,17 @@ class CopyDestUserVisitor : public AddressUserVisitor { CopyDestUserVisitor(SmallPtrSetImpl &DestUsers) : DestUsers(DestUsers) {} - virtual bool visitNormalUse(SILInstruction *user) { + virtual bool visitNormalUse(SILInstruction *user) override { // Bail on multiple uses in the same instruction to avoid complexity. return DestUsers.insert(user).second; } - virtual bool visitTake(CopyAddrInst *take) { + virtual bool visitTake(CopyAddrInst *take) override { return DestUsers.insert(take).second; } - virtual bool visitDestroy(DestroyAddrInst *destroy) { + virtual bool visitDestroy(DestroyAddrInst *destroy) override { return DestUsers.insert(destroy).second; } - virtual bool visitDebugValue(DebugValueAddrInst *debugValue) { + virtual bool visitDebugValue(DebugValueAddrInst *debugValue) override { return DestUsers.insert(debugValue).second; } }; diff --git a/lib/SILOptimizer/Transforms/OptRemarkGenerator.cpp b/lib/SILOptimizer/Transforms/OptRemarkGenerator.cpp index b20890a6b1cfd..987c36ed0cc36 100644 --- a/lib/SILOptimizer/Transforms/OptRemarkGenerator.cpp +++ b/lib/SILOptimizer/Transforms/OptRemarkGenerator.cpp @@ -30,12 +30,19 @@ #include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" using namespace swift; +static llvm::cl::opt ForceVisitImplicitAutogeneratedFunctions( + "optremarkgen-visit-implicit-autogen-funcs", llvm::cl::Hidden, + llvm::cl::desc( + "Emit opt remarks even on implicit and autogenerated functions"), + llvm::cl::init(false)); + //===----------------------------------------------------------------------===// -// Utility +// Value To Decl Inferrer //===----------------------------------------------------------------------===// namespace { @@ -64,7 +71,10 @@ struct ValueToDeclInferrer { void ValueToDeclInferrer::printNote(llvm::raw_string_ostream &stream, const ValueDecl *decl) { + assert(decl && + "We assume for now that this is always called with a non-null decl"); stream << "of '" << decl->getBaseName(); + for (auto &pair : accessPath) { auto baseType = pair.first; auto &proj = pair.second; @@ -126,6 +136,12 @@ static SingleValueInstruction *isSupportedProjection(Projection p, SILValue v) { llvm_unreachable("Covered switch is not covered?!"); } +static bool hasNonInlinedDebugScope(SILInstruction *i) { + if (auto *scope = i->getDebugScope()) + return !scope->InlinedCallSite; + return false; +} + bool ValueToDeclInferrer::infer( ArgumentKeyKind keyKind, SILValue value, SmallVectorImpl &resultingInferredDecls) { @@ -160,6 +176,46 @@ bool ValueToDeclInferrer::infer( return true; } + if (auto *ari = dyn_cast(value)) { + if (auto *decl = ari->getDecl()) { + std::string msg; + { + llvm::raw_string_ostream stream(msg); + printNote(stream, decl); + } + resultingInferredDecls.push_back( + Argument({keyKind, "InferredValue"}, std::move(msg), decl)); + return true; + } + } + + if (auto *abi = dyn_cast(value)) { + if (auto *decl = abi->getDecl()) { + std::string msg; + { + llvm::raw_string_ostream stream(msg); + printNote(stream, decl); + } + + resultingInferredDecls.push_back( + Argument({keyKind, "InferredValue"}, std::move(msg), decl)); + return true; + } + } + + if (auto *asi = dyn_cast(value)) { + if (auto *decl = asi->getDecl()) { + std::string msg; + { + llvm::raw_string_ostream stream(msg); + printNote(stream, decl); + } + resultingInferredDecls.push_back( + Argument({keyKind, "InferredValue"}, std::move(msg), decl)); + return true; + } + } + // Then visit our users and see if we can find a debug_value that provides // us with a decl we can use to construct an argument. bool foundDeclFromUse = false; @@ -169,15 +225,19 @@ bool ValueToDeclInferrer::infer( continue; if (auto *dvi = dyn_cast(use->getUser())) { - if (auto *decl = dvi->getDecl()) { - std::string msg; - { - llvm::raw_string_ostream stream(msg); - printNote(stream, decl); + // Check if our debug_value has a decl and was not inlined into the + // current function. + if (hasNonInlinedDebugScope(dvi)) { + if (auto *decl = dvi->getDecl()) { + std::string msg; + { + llvm::raw_string_ostream stream(msg); + printNote(stream, decl); + } + resultingInferredDecls.push_back( + Argument({keyKind, "InferredValue"}, std::move(msg), decl)); + foundDeclFromUse = true; } - resultingInferredDecls.push_back( - Argument({keyKind, "InferredValue"}, std::move(msg), decl)); - foundDeclFromUse = true; } } } @@ -203,6 +263,8 @@ bool ValueToDeclInferrer::infer( } } + // TODO: We could emit at this point a msg for temporary allocations. + // If we reached this point, we finished falling through the loop and return // true. return true; @@ -232,6 +294,8 @@ struct OptRemarkGeneratorInstructionVisitor void visitStrongReleaseInst(StrongReleaseInst *sri); void visitRetainValueInst(RetainValueInst *rvi); void visitReleaseValueInst(ReleaseValueInst *rvi); + void visitAllocRefInst(AllocRefInst *ari); + void visitAllocBoxInst(AllocBoxInst *abi); void visitSILInstruction(SILInstruction *) {} }; @@ -320,6 +384,64 @@ void OptRemarkGeneratorInstructionVisitor::visitReleaseValueInst( }); } +void OptRemarkGeneratorInstructionVisitor::visitAllocRefInst( + AllocRefInst *ari) { + if (ari->canAllocOnStack()) { + return ORE.emit([&]() { + using namespace OptRemark; + SmallVector inferredArgs; + bool foundArgs = + valueToDeclInferrer.infer(ArgumentKeyKind::Note, ari, inferredArgs); + (void)foundArgs; + auto resultRemark = + RemarkPassed("memory", *ari, + SourceLocInferenceBehavior::ForwardScanOnly) + << "stack allocated ref of type '" << NV("ValueType", ari->getType()) + << "'"; + for (auto &arg : inferredArgs) + resultRemark << arg; + return resultRemark; + }); + } + + return ORE.emit([&]() { + using namespace OptRemark; + SmallVector inferredArgs; + bool foundArgs = + valueToDeclInferrer.infer(ArgumentKeyKind::Note, ari, inferredArgs); + (void)foundArgs; + + auto resultRemark = + RemarkMissed("memory", *ari, + SourceLocInferenceBehavior::ForwardScanOnly) + << "heap allocated ref of type '" << NV("ValueType", ari->getType()) + << "'"; + for (auto &arg : inferredArgs) + resultRemark << arg; + return resultRemark; + }); +} + +void OptRemarkGeneratorInstructionVisitor::visitAllocBoxInst( + AllocBoxInst *abi) { + return ORE.emit([&]() { + using namespace OptRemark; + SmallVector inferredArgs; + bool foundArgs = + valueToDeclInferrer.infer(ArgumentKeyKind::Note, abi, inferredArgs); + (void)foundArgs; + + auto resultRemark = + RemarkMissed("memory", *abi, + SourceLocInferenceBehavior::ForwardScanOnly) + << "heap allocated box of type '" << NV("ValueType", abi->getType()) + << "'"; + for (auto &arg : inferredArgs) + resultRemark << arg; + return resultRemark; + }); +} + //===----------------------------------------------------------------------===// // Top Level Entrypoint //===----------------------------------------------------------------------===// @@ -347,6 +469,21 @@ class OptRemarkGenerator : public SILFunctionTransform { return; auto *fn = getFunction(); + + // Skip top level implicit functions and top level autogenerated functions, + // unless we were asked by the user to emit them. + if (!ForceVisitImplicitAutogeneratedFunctions) { + // Skip implicit functions generated by Sema. + if (auto *ctx = fn->getDeclContext()) + if (auto *decl = ctx->getAsDecl()) + if (decl->isImplicit()) + return; + // Skip autogenerated functions generated by SILGen. + if (auto loc = fn->getDebugScope()->getLoc()) + if (loc.isAutoGenerated()) + return; + } + LLVM_DEBUG(llvm::dbgs() << "Visiting: " << fn->getName() << "\n"); auto &rcfi = *getAnalysis()->get(fn); OptRemarkGeneratorInstructionVisitor visitor(*fn, rcfi); diff --git a/lib/SILOptimizer/Transforms/Outliner.cpp b/lib/SILOptimizer/Transforms/Outliner.cpp index e052a6b000f3c..b5a89537fbe0e 100644 --- a/lib/SILOptimizer/Transforms/Outliner.cpp +++ b/lib/SILOptimizer/Transforms/Outliner.cpp @@ -298,7 +298,7 @@ CanSILFunctionType BridgedProperty::getOutlinedFunctionType(SILModule &M) { auto ExtInfo = SILFunctionType::ExtInfoBuilder( SILFunctionType::Representation::Thin, /*pseudogeneric*/ false, /*noescape*/ false, - DifferentiabilityKind::NonDifferentiable, + /*async*/ false, DifferentiabilityKind::NonDifferentiable, /*clangFunctionType*/ nullptr) .build(); auto FunctionType = SILFunctionType::get( @@ -1181,6 +1181,7 @@ CanSILFunctionType ObjCMethodCall::getOutlinedFunctionType(SILModule &M) { SILFunctionType::ExtInfoBuilder(SILFunctionType::Representation::Thin, /*pseudogeneric*/ false, /*noescape*/ false, + /*async*/ false, DifferentiabilityKind::NonDifferentiable, /*clangFunctionType*/ nullptr) .build(); diff --git a/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp b/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp index a8f823e584d5a..9ef7e2d70befd 100644 --- a/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp +++ b/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp @@ -86,7 +86,8 @@ class BugReducerTester : public SILFunctionTransform { nullptr, SILFunctionType::ExtInfoBuilder( SILFunctionType::Representation::Thin, false /*isPseudoGeneric*/, - false /*noescape*/, DifferentiabilityKind::NonDifferentiable, + false /*noescape*/, false /*async*/, + DifferentiabilityKind::NonDifferentiable, nullptr /*clangFunctionType*/) .build(), SILCoroutineKind::None, ParameterConvention::Direct_Unowned, diff --git a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp index 21f4bc6f5a24c..f8bcce57b36d7 100644 --- a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp +++ b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp @@ -622,14 +622,20 @@ static bool isCallerAndCalleeLayoutConstraintsCompatible(FullApplySite AI) { // The generic parameter has a layout constraint. // Check that the substitution has the same constraint. auto AIReplacement = Type(Param).subst(AISubs); - auto AIArchetype = AIReplacement->getAs(); - if (!AIArchetype) - return false; - auto AILayout = AIArchetype->getLayoutConstraint(); - if (!AILayout) - return false; - if (AILayout != Layout) - return false; + + if (Layout->isClass()) { + if (!AIReplacement->satisfiesClassConstraint()) + return false; + } else { + auto AIArchetype = AIReplacement->getAs(); + if (!AIArchetype) + return false; + auto AILayout = AIArchetype->getLayoutConstraint(); + if (!AILayout) + return false; + if (AILayout != Layout) + return false; + } } return true; } diff --git a/lib/SILOptimizer/Utils/ValueLifetime.cpp b/lib/SILOptimizer/Utils/ValueLifetime.cpp index 5fc8b0228b62b..4f90e9cc0bd80 100644 --- a/lib/SILOptimizer/Utils/ValueLifetime.cpp +++ b/lib/SILOptimizer/Utils/ValueLifetime.cpp @@ -11,17 +11,23 @@ //===----------------------------------------------------------------------===// #include "swift/SILOptimizer/Utils/ValueLifetime.h" +#include "swift/Basic/STLExtras.h" #include "swift/SIL/BasicBlockUtils.h" #include "swift/SILOptimizer/Utils/CFGOptUtils.h" using namespace swift; void ValueLifetimeAnalysis::propagateLiveness() { + bool defIsInstruction = defValue.is(); assert(liveBlocks.empty() && "frontier computed twice"); - assert(!userSet.count(defValue) && "definition cannot be its own use"); + assert( + (!defIsInstruction || !userSet.count(defValue.get())) && + "definition cannot be its own use"); - auto defBB = defValue->getParentBlock(); - llvm::SmallVector worklist; + // Compute the def block only if we have a SILInstruction. If we have a + // SILArgument, this will be nullptr. + auto *defBB = getDefValueParentBlock(); + SmallVector worklist; int numUsersBeforeDef = 0; // Find the initial set of blocks where the value is live, because @@ -31,20 +37,28 @@ void ValueLifetimeAnalysis::propagateLiveness() { if (liveBlocks.insert(userBlock)) worklist.push_back(userBlock); - // A user in the defBB could potentially be located before the defValue. - if (userBlock == defBB) + // A user in the defBB could potentially be located before the defValue. If + // we had a SILArgument, defBB will be nullptr, so we should always have + // numUsersBeforeDef is 0. We assert this at the end of the loop. + if (defIsInstruction && userBlock == defBB) ++numUsersBeforeDef; } - // Don't count any users in the defBB which are actually located _after_ - // the defValue. - auto instIter = defValue->getIterator(); - while (numUsersBeforeDef > 0 && ++instIter != defBB->end()) { - if (userSet.count(&*instIter)) - --numUsersBeforeDef; + assert((defValue.is() || (numUsersBeforeDef == 0)) && + "Non SILInstruction defValue with users before the def?!"); + + // Don't count any users in the defBB which are actually located _after_ the + // defValue. + if (defIsInstruction) { + auto instIter = defValue.get()->getIterator(); + while (numUsersBeforeDef > 0 && ++instIter != defBB->end()) { + if (userSet.count(&*instIter)) + --numUsersBeforeDef; + } } // Initialize the hasUsersBeforeDef field. hasUsersBeforeDef = numUsersBeforeDef > 0; + assert(defIsInstruction || !hasUsersBeforeDef); // Now propagate liveness backwards until we hit the block that defines the // value. @@ -55,30 +69,31 @@ void ValueLifetimeAnalysis::propagateLiveness() { if (bb == defBB && !hasUsersBeforeDef) continue; - for (SILBasicBlock *Pred : bb->getPredecessorBlocks()) { + for (auto *predBB : bb->getPredecessorBlocks()) { // If it's already in the set, then we've already queued and/or // processed the predecessors. - if (liveBlocks.insert(Pred)) - worklist.push_back(Pred); + if (liveBlocks.insert(predBB)) + worklist.push_back(predBB); } } } SILInstruction *ValueLifetimeAnalysis::findLastUserInBlock(SILBasicBlock *bb) { // Walk backwards in bb looking for last use of the value. - for (auto ii = bb->rbegin(); ii != bb->rend(); ++ii) { - assert(defValue != &*ii && "Found def before finding use!"); + for (auto &inst : llvm::reverse(*bb)) { + assert(defValue.dyn_cast() != &inst && + "Found def before finding use!"); - if (userSet.count(&*ii)) - return &*ii; + if (userSet.count(&inst)) + return &inst; } llvm_unreachable("Expected to find use of value in block!"); } bool ValueLifetimeAnalysis::computeFrontier(Frontier &frontier, Mode mode, DeadEndBlocks *deBlocks) { - assert(!isAliveAtBeginOfBlock(defValue->getFunction()->getEntryBlock()) - && "Can't compute frontier for def which does not dominate all uses"); + assert(!isAliveAtBeginOfBlock(getFunction()->getEntryBlock()) && + "Can't compute frontier for def which does not dominate all uses"); bool noCriticalEdges = true; @@ -101,10 +116,16 @@ bool ValueLifetimeAnalysis::computeFrontier(Frontier &frontier, Mode mode, for (const SILSuccessor &succ : bb->getSuccessors()) { if (isAliveAtBeginOfBlock(succ)) { liveInSucc = true; - if (succ == defValue->getParent()) { + if (succ == getDefValueParentBlock()) { // Here, the basic block bb uses the value but also redefines the // value inside bb. The new value could be used by the successors // of succ and therefore could be live at the end of succ as well. + // + // This should never happen if we have a SILArgument since the + // SILArgument can not have any uses before it in a block. + assert(defValue.is() && + "SILArguments dominate all instructions in their defining " + "blocks"); usedAndRedefinedInSucc = true; } } else if (!deBlocks || !deBlocks->isDeadEnd(succ)) { @@ -115,7 +136,10 @@ bool ValueLifetimeAnalysis::computeFrontier(Frontier &frontier, Mode mode, // Here, the basic block bb uses the value and later redefines the value. // Therefore, this value's lifetime ends after its last use preceding the // re-definition of the value. - auto ii = defValue->getReverseIterator(); + // + // We know that we can not have a SILArgument here since the SILArgument + // dominates all instructions in the same block. + auto ii = defValue.get()->getReverseIterator(); for (; ii != bb->rend(); ++ii) { if (userSet.count(&*ii)) { frontier.push_back(&*std::next(ii)); @@ -245,15 +269,19 @@ bool ValueLifetimeAnalysis::isWithinLifetime(SILInstruction *inst) { // Searches \p bb backwards from the instruction before \p frontierInst // to the beginning of the list and returns true if we find a dealloc_ref // /before/ we find \p defValue (the instruction that defines our target value). -static bool blockContainsDeallocRef(SILBasicBlock *bb, SILInstruction *defValue, - SILInstruction *frontierInst) { +static bool +blockContainsDeallocRef(SILBasicBlock *bb, + PointerUnion defValue, + SILInstruction *frontierInst) { SILBasicBlock::reverse_iterator End = bb->rend(); SILBasicBlock::reverse_iterator iter = frontierInst->getReverseIterator(); for (++iter; iter != End; ++iter) { SILInstruction *inst = &*iter; if (isa(inst)) return true; - if (inst == defValue) + // We know that inst is not a nullptr, so if we have a SILArgument, this + // will always fail as we want. + if (inst == defValue.dyn_cast()) return false; } return false; @@ -281,9 +309,14 @@ bool ValueLifetimeAnalysis::containsDeallocRef(const Frontier &frontier) { } void ValueLifetimeAnalysis::dump() const { - llvm::errs() << "lifetime of def: " << *defValue; - for (SILInstruction *Use : userSet) { - llvm::errs() << " use: " << *Use; + llvm::errs() << "lifetime of def: "; + if (auto *ii = defValue.dyn_cast()) { + llvm::errs() << *ii; + } else { + llvm::errs() << *defValue.get(); + } + for (SILInstruction *use : userSet) { + llvm::errs() << " use: " << *use; } llvm::errs() << " live blocks:"; for (SILBasicBlock *bb : liveBlocks) { diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index 4c976d26a0f1d..c4a1dd048911f 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -146,7 +146,11 @@ class BuilderClosureVisitor } bool found = false; - for (auto decl : builder->lookupDirect(fnName)) { + SmallVector foundDecls; + dc->lookupQualified( + builderType, DeclNameRef(fnName), + NL_QualifiedDefault | NL_ProtocolMembers, foundDecls); + for (auto decl : foundDecls) { if (auto func = dyn_cast(decl)) { // Function must be static. if (!func->isStatic()) @@ -306,10 +310,6 @@ class BuilderClosureVisitor } VarDecl *visitBraceStmt(BraceStmt *braceStmt) { - return visitBraceStmt(braceStmt, ctx.Id_buildBlock); - } - - VarDecl *visitBraceStmt(BraceStmt *braceStmt, Identifier builderFunction) { SmallVector expressions; auto addChild = [&](VarDecl *childVar) { if (!childVar) @@ -376,7 +376,7 @@ class BuilderClosureVisitor // Call Builder.buildBlock(... args ...) auto call = buildCallIfWanted(braceStmt->getStartLoc(), - builderFunction, expressions, + ctx.Id_buildBlock, expressions, /*argLabels=*/{ }); if (!call) return nullptr; @@ -391,13 +391,7 @@ class BuilderClosureVisitor } VarDecl *visitDoStmt(DoStmt *doStmt) { - if (!builderSupports(ctx.Id_buildDo)) { - if (!unhandledNode) - unhandledNode = doStmt; - return nullptr; - } - - auto childVar = visitBraceStmt(doStmt->getBody(), ctx.Id_buildDo); + auto childVar = visitBraceStmt(doStmt->getBody()); if (!childVar) return nullptr; @@ -902,6 +896,26 @@ class BuilderClosureVisitor return finalForEachVar; } + /// Visit a throw statement, which never produces a result. + VarDecl *visitThrowStmt(ThrowStmt *throwStmt) { + Type exnType = ctx.getErrorDecl()->getDeclaredInterfaceType(); + if (!exnType) { + hadError = true; + } + + if (cs) { + SolutionApplicationTarget target( + throwStmt->getSubExpr(), dc, CTP_ThrowStmt, exnType, + /*isDiscarded=*/false); + if (cs->generateConstraints(target, FreeTypeVariableBinding::Disallow)) + hadError = true; + + cs->setSolutionApplicationTarget(throwStmt, target); + } + + return nullptr; + } + CONTROL_FLOW_STMT(Guard) CONTROL_FLOW_STMT(While) CONTROL_FLOW_STMT(DoCatch) @@ -911,7 +925,6 @@ class BuilderClosureVisitor CONTROL_FLOW_STMT(Continue) CONTROL_FLOW_STMT(Fallthrough) CONTROL_FLOW_STMT(Fail) - CONTROL_FLOW_STMT(Throw) CONTROL_FLOW_STMT(PoundAssert) #undef CONTROL_FLOW_STMT @@ -1147,6 +1160,14 @@ class BuilderClosureRewriter } if (auto stmt = node.dyn_cast()) { + // "throw" statements produce no value. Transform them directly. + if (auto throwStmt = dyn_cast(stmt)) { + if (auto newStmt = visitThrowStmt(throwStmt)) { + newElements.push_back(stmt); + } + continue; + } + // Each statement turns into a (potential) temporary variable // binding followed by the statement itself. auto captured = takeCapturedStmt(stmt); @@ -1435,6 +1456,22 @@ class BuilderClosureRewriter ctx, forEachStmt->getStartLoc(), outerBodySteps, newBody->getEndLoc()); } + Stmt *visitThrowStmt(ThrowStmt *throwStmt) { + // Rewrite the error. + auto target = *solution.getConstraintSystem() + .getSolutionApplicationTarget(throwStmt); + if (auto result = rewriteTarget(target)) + throwStmt->setSubExpr(result->getAsExpr()); + else + return nullptr; + + return throwStmt; + } + + Stmt *visitThrowStmt(ThrowStmt *throwStmt, FunctionBuilderTarget target) { + llvm_unreachable("Throw statements produce no value"); + } + #define UNHANDLED_FUNCTION_BUILDER_STMT(STMT) \ Stmt *visit##STMT##Stmt(STMT##Stmt *stmt, FunctionBuilderTarget target) { \ llvm_unreachable("Function builders do not allow statement of kind " \ @@ -1452,7 +1489,6 @@ class BuilderClosureRewriter UNHANDLED_FUNCTION_BUILDER_STMT(Continue) UNHANDLED_FUNCTION_BUILDER_STMT(Fallthrough) UNHANDLED_FUNCTION_BUILDER_STMT(Fail) - UNHANDLED_FUNCTION_BUILDER_STMT(Throw) UNHANDLED_FUNCTION_BUILDER_STMT(PoundAssert) #undef UNHANDLED_FUNCTION_BUILDER_STMT }; @@ -1485,9 +1521,11 @@ Optional TypeChecker::applyFunctionBuilderBodyTransform( // If we encountered an error or there was an explicit result type, // bail out and report that to the caller. auto &ctx = func->getASTContext(); - auto request = PreCheckFunctionBuilderRequest{AnyFunctionRef(func)}; - switch (evaluateOrDefault( - ctx.evaluator, request, FunctionBuilderBodyPreCheck::Error)) { + auto request = + PreCheckFunctionBuilderRequest{{AnyFunctionRef(func), + /*SuppressDiagnostics=*/false}}; + switch (evaluateOrDefault(ctx.evaluator, request, + FunctionBuilderBodyPreCheck::Error)) { case FunctionBuilderBodyPreCheck::Okay: // If the pre-check was okay, apply the function-builder transform. break; @@ -1619,16 +1657,24 @@ ConstraintSystem::matchFunctionBuilder( // Pre-check the body: pre-check any expressions in it and look // for return statements. - auto request = PreCheckFunctionBuilderRequest{fn}; + auto request = + PreCheckFunctionBuilderRequest{{fn, /*SuppressDiagnostics=*/true}}; switch (evaluateOrDefault(getASTContext().evaluator, request, FunctionBuilderBodyPreCheck::Error)) { case FunctionBuilderBodyPreCheck::Okay: // If the pre-check was okay, apply the function-builder transform. break; - case FunctionBuilderBodyPreCheck::Error: - // If the pre-check had an error, flag that. - return getTypeMatchFailure(locator); + case FunctionBuilderBodyPreCheck::Error: { + if (!shouldAttemptFixes()) + return getTypeMatchFailure(locator); + + if (recordFix(IgnoreInvalidFunctionBuilderBody::create( + *this, getConstraintLocator(fn.getBody())))) + return getTypeMatchFailure(locator); + + return getTypeMatchSuccess(); + } case FunctionBuilderBodyPreCheck::HasReturnStmt: // If the body has a return statement, suppress the transform but @@ -1705,14 +1751,17 @@ namespace { class PreCheckFunctionBuilderApplication : public ASTWalker { AnyFunctionRef Fn; bool SkipPrecheck = false; + bool SuppressDiagnostics = false; std::vector ReturnStmts; bool HasError = false; bool hasReturnStmt() const { return !ReturnStmts.empty(); } public: - PreCheckFunctionBuilderApplication(AnyFunctionRef fn, bool skipPrecheck) - : Fn(fn), SkipPrecheck(skipPrecheck) {} + PreCheckFunctionBuilderApplication(AnyFunctionRef fn, bool skipPrecheck, + bool suppressDiagnostics) + : Fn(fn), SkipPrecheck(skipPrecheck), + SuppressDiagnostics(suppressDiagnostics) {} const std::vector getReturnStmts() const { return ReturnStmts; } @@ -1736,16 +1785,28 @@ class PreCheckFunctionBuilderApplication : public ASTWalker { } std::pair walkToExprPre(Expr *E) override { + if (SkipPrecheck) + return std::make_pair(false, E); + // Pre-check the expression. If this fails, abort the walk immediately. // Otherwise, replace the expression with the result of pre-checking. // In either case, don't recurse into the expression. - if (!SkipPrecheck && - ConstraintSystem::preCheckExpression(E, /*DC*/ Fn.getAsDeclContext())) { - HasError = true; - return std::make_pair(false, nullptr); - } + { + auto *DC = Fn.getAsDeclContext(); + auto &diagEngine = DC->getASTContext().Diags; - return std::make_pair(false, E); + // Suppress any diangostics which could be produced by this expression. + DiagnosticTransaction transaction(diagEngine); + + HasError |= ConstraintSystem::preCheckExpression( + E, DC, /*replaceInvalidRefsWithErrors=*/false); + HasError |= transaction.hasDiagnostics(); + + if (SuppressDiagnostics) + transaction.abort(); + + return std::make_pair(false, HasError ? nullptr : E); + } } std::pair walkToStmtPre(Stmt *S) override { @@ -1778,11 +1839,15 @@ FunctionBuilderBodyPreCheck PreCheckFunctionBuilderRequest::evaluate( owner.Fn.getAbstractClosureExpr())) skipPrecheck = shouldTypeCheckInEnclosingExpression(closure); - return PreCheckFunctionBuilderApplication(owner.Fn, false).run(); + return PreCheckFunctionBuilderApplication( + owner.Fn, /*skipPrecheck=*/false, + /*suppressDiagnostics=*/owner.SuppressDiagnostics) + .run(); } std::vector TypeChecker::findReturnStatements(AnyFunctionRef fn) { - PreCheckFunctionBuilderApplication precheck(fn, true); + PreCheckFunctionBuilderApplication precheck(fn, /*skipPreCheck=*/true, + /*SuppressDiagnostics=*/true); (void)precheck.run(); return precheck.getReturnStmts(); } diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 3c0e373e81c6b..d35c849fb435f 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -41,12 +41,13 @@ add_swift_host_library(swiftSema STATIC TypeCheckCaptures.cpp TypeCheckCircularity.cpp TypeCheckCodeCompletion.cpp + TypeCheckConcurrency.cpp TypeCheckConstraints.cpp TypeCheckDecl.cpp TypeCheckDeclObjC.cpp TypeCheckDeclOverride.cpp TypeCheckDeclPrimary.cpp - TypeCheckError.cpp + TypeCheckEffects.cpp TypeCheckExpr.cpp TypeCheckExprObjC.cpp TypeCheckGeneric.cpp diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index c5715942de0c6..762a493182b78 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -176,12 +176,46 @@ bool ConstraintSystem::isTypeReference(Expr *E) { }); } +bool Solution::isTypeReference(Expr *E) const { + return E->isTypeReference( + [&](Expr *expr) -> Type { return simplifyType(getType(expr)); }, + [&](Expr *expr) -> Decl * { + ConstraintLocator *locator = nullptr; + if (auto *UDE = dyn_cast(E)) { + locator = getConstraintLocator(UDE, {ConstraintLocator::Member}); + } + + if (auto *UME = dyn_cast(E)) { + locator = + getConstraintLocator(UME, {ConstraintLocator::UnresolvedMember}); + } + + if (isa(E)) + locator = getConstraintLocator(const_cast(E)); + + if (locator) { + if (auto selectedOverload = getOverloadChoiceIfAvailable(locator)) { + const auto &choice = selectedOverload->choice; + return choice.getDeclOrNull(); + } + } + + return nullptr; + }); +} + bool ConstraintSystem::isStaticallyDerivedMetatype(Expr *E) { return E->isStaticallyDerivedMetatype( [&](Expr *E) -> Type { return simplifyType(getType(E)); }, [&](Expr *E) -> bool { return isTypeReference(E); }); } +bool Solution::isStaticallyDerivedMetatype(Expr *E) const { + return E->isStaticallyDerivedMetatype( + [&](Expr *E) -> Type { return simplifyType(getType(E)); }, + [&](Expr *E) -> bool { return isTypeReference(E); }); +} + Type ConstraintSystem::getInstanceType(TypeExpr *E) { if (!hasType(E)) return Type(); @@ -364,6 +398,26 @@ namespace { return base.getOldType(); } + /// Check whether it is possible to have an ObjC key path string for the keypath expression + /// and set the key path string, if yes + void checkAndSetObjCKeyPathString(KeyPathExpr *keyPath) { + if (cs.getASTContext().LangOpts.EnableObjCInterop) { + SmallString<64> compatStringBuf; + if (buildObjCKeyPathString(keyPath, compatStringBuf)) { + auto stringCopy = cs.getASTContext().AllocateCopy(compatStringBuf.begin(), + compatStringBuf.end()); + auto stringExpr = new (cs.getASTContext()) StringLiteralExpr( + StringRef(stringCopy, compatStringBuf.size()), + SourceRange(), + /*implicit*/ true); + cs.setType( + stringExpr, + cs.getASTContext().getStringDecl()->getDeclaredInterfaceType()); + keyPath->setObjCStringLiteralExpr(stringExpr); + } + } + } + // Returns None if the AST does not contain enough information to recover // substitutions; this is different from an Optional(SubstitutionMap()), // indicating a valid call to a non-generic operator. @@ -806,12 +860,9 @@ namespace { } // Similarly, ".foo(...)" really applies two argument lists. - if (auto *unresolvedMemberExpr = dyn_cast(prev)) { - if (unresolvedMemberExpr->hasArguments() || - unresolvedMemberExpr->hasTrailingClosure()) - return 2; - return 1; - } + if (isa(prev) && + isa(cast(prev)->getFn())) + return 2; return getArgCount(maxArgCount); }(); @@ -2007,6 +2058,11 @@ namespace { keyPath->setParsedPath(componentExpr); keyPath->resolveComponents(ctx, components); cs.cacheExprTypes(keyPath); + + // See whether there's an equivalent ObjC key path string we can produce + // for interop purposes. + checkAndSetObjCKeyPathString(keyPath); + return keyPath; } @@ -2694,31 +2750,25 @@ namespace { } Expr *visitUnresolvedMemberExpr(UnresolvedMemberExpr *expr) { - // Dig out the type of the base, which will be the result type of this - // expression. If constraint solving resolved this to an UnresolvedType, - // then we're in an ambiguity tolerant mode used for diagnostic - // generation. Just leave this as an unresolved member reference. + // If constraint solving resolved this to an UnresolvedType, then we're in + // an ambiguity tolerant mode used for diagnostic generation. Just leave + // this as an unresolved member reference. Type resultTy = simplifyType(cs.getType(expr)); if (resultTy->hasUnresolvedType()) { cs.setType(expr, resultTy); return expr; } - Type baseTy = resultTy->getRValueType(); auto &ctx = cs.getASTContext(); - - // Find the selected member. + // Find the selected member and base type. auto memberLocator = cs.getConstraintLocator( expr, ConstraintLocator::UnresolvedMember); auto selected = solution.getOverloadChoice(memberLocator); - - // If the member came by optional unwrapping, then unwrap the base type. - if (selected.choice.getKind() - == OverloadChoiceKind::DeclViaUnwrappedOptional) { - baseTy = baseTy->getOptionalObjectType(); - assert(baseTy - && "got unwrapped optional decl from non-optional base?!"); - } + + // Unresolved member lookup always happens in a metatype so dig out the + // instance type. + auto baseTy = selected.choice.getBaseType()->getMetatypeInstanceType(); + baseTy = simplifyType(baseTy); // The base expression is simply the metatype of the base type. // FIXME: This location info is bogus. @@ -2733,30 +2783,6 @@ namespace { if (!result) return nullptr; - auto getType = [&](Expr *E) -> Type { return cs.getType(E); }; - - // If there was an argument, apply it. - if (auto arg = expr->getArgument()) { - // Get the callee locator. Note this may be different to the locator for - // the member being referenced for things like callAsFunction. - auto *calleeLoc = cs.getCalleeLocator(exprLoc); - - // Build and finish the apply. - ApplyExpr *apply = CallExpr::create( - ctx, result, arg, expr->getArgumentLabels(), - expr->getArgumentLabelLocs(), expr->hasTrailingClosure(), - /*implicit=*/expr->isImplicit(), Type(), getType); - result = finishApply(apply, Type(), exprLoc, calleeLoc); - - // FIXME: Application could fail, because some of the solutions - // are not expressible in AST (yet?), like certain tuple-to-tuple - // conversions. Better solution here would be not to form solutions - // which couldn't be applied by e.g. detecting situations like that - // and inserting fixes early. - if (!result) - return nullptr; - } - // Check for ambiguous member if the base is an Optional if (baseTy->getOptionalObjectType()) { diagnoseAmbiguousNominalMember(baseTy, result); @@ -3217,6 +3243,19 @@ namespace { return simplifyExprType(expr); } + Expr *visitUnresolvedMemberChainResultExpr( + UnresolvedMemberChainResultExpr *expr) { + // Since this expression only exists to give the result type of an + // unresolved member chain visibility in the AST, remove it from the AST + // now that we have a solution and coerce the subexpr to the resulting + // type. + auto *subExpr = expr->getSubExpr(); + auto type = simplifyType(cs.getType(expr)); + subExpr = coerceToType(subExpr, type, cs.getConstraintLocator(subExpr)); + cs.setType(subExpr, type); + return subExpr; + } + Expr *visitTupleExpr(TupleExpr *expr) { return simplifyExprType(expr); } @@ -4673,9 +4712,21 @@ namespace { KeyPathExpr::Component::forOptionalChain(objectTy, loc)); break; } - case KeyPathExpr::Component::Kind::OptionalForce: - buildKeyPathOptionalForceComponent(resolvedComponents); + case KeyPathExpr::Component::Kind::OptionalForce: { + // Handle force optional when it is the first component e.g. + // \String?.!.count + if (resolvedComponents.empty()) { + auto loc = origComponent.getLoc(); + auto objectTy = componentTy->getOptionalObjectType(); + assert(objectTy); + + resolvedComponents.push_back( + KeyPathExpr::Component::forOptionalForce(objectTy, loc)); + } else { + buildKeyPathOptionalForceComponent(resolvedComponents); + } break; + } case KeyPathExpr::Component::Kind::Invalid: { auto component = origComponent; component.setComponentType(leafTy); @@ -4721,22 +4772,7 @@ namespace { // See whether there's an equivalent ObjC key path string we can produce // for interop purposes. - if (cs.getASTContext().LangOpts.EnableObjCInterop) { - SmallString<64> compatStringBuf; - if (buildObjCKeyPathString(E, compatStringBuf)) { - auto stringCopy = - cs.getASTContext().AllocateCopy(compatStringBuf.begin(), - compatStringBuf.end()); - auto stringExpr = new (cs.getASTContext()) StringLiteralExpr( - StringRef(stringCopy, compatStringBuf.size()), - SourceRange(), - /*implicit*/ true); - cs.setType( - stringExpr, - cs.getASTContext().getStringDecl()->getDeclaredInterfaceType()); - E->setObjCStringLiteralExpr(stringExpr); - } - } + checkAndSetObjCKeyPathString(E); // The final component type ought to line up with the leaf type of the // key path. @@ -7618,6 +7654,8 @@ namespace { // "Mismatched types!"); assert(!exprType->hasTypeVariable() && "Should not write type variable into expression!"); + assert(!exprType->hasHole() && + "Should not write type holes into expression!"); expr->setType(exprType); if (auto kp = dyn_cast(expr)) { @@ -7627,6 +7665,8 @@ namespace { componentType = solution.simplifyType(cs.getType(kp, i)); assert(!componentType->hasTypeVariable() && "Should not write type variable into key-path component"); + assert(!componentType->hasHole() && + "Should not write type hole into key-path component"); kp->getMutableComponents()[i].setComponentType(componentType); } } @@ -8381,6 +8421,10 @@ Type Solution::getType(ASTNode node) const { return cs.getType(node); } +Type Solution::getResolvedType(ASTNode node) const { + return simplifyType(getType(node)); +} + void Solution::setExprTypes(Expr *expr) const { if (!expr) return; diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index bb99b97afd980..a82b389991788 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -22,7 +22,7 @@ using namespace swift; using namespace constraints; void ConstraintSystem::PotentialBindings::inferTransitiveBindings( - ConstraintSystem &cs, llvm::SmallPtrSetImpl &existingTypes, + const ConstraintSystem &cs, llvm::SmallPtrSetImpl &existingTypes, const llvm::SmallDenseMap &inferredBindings) { @@ -119,7 +119,7 @@ isUnviableDefaultType(Type defaultType, } void ConstraintSystem::PotentialBindings::inferDefaultTypes( - ConstraintSystem &cs, llvm::SmallPtrSetImpl &existingTypes) { + const ConstraintSystem &cs, llvm::SmallPtrSetImpl &existingTypes) { auto isDirectRequirement = [&](Constraint *constraint) -> bool { if (auto *typeVar = constraint->getFirstType()->getAs()) { auto *repr = cs.getRepresentative(typeVar); @@ -275,7 +275,7 @@ void ConstraintSystem::PotentialBindings::inferDefaultTypes( } void ConstraintSystem::PotentialBindings::finalize( - ConstraintSystem &cs, + const ConstraintSystem &cs, const llvm::SmallDenseMap &inferredBindings) { @@ -335,7 +335,7 @@ void ConstraintSystem::PotentialBindings::finalize( if (locator->isLastElement()) PotentiallyIncomplete = true; - addPotentialBinding(PotentialBinding::forHole(cs.getASTContext(), locator)); + addPotentialBinding(PotentialBinding::forHole(TypeVar, locator)); } // Let's always consider `Any` to be a last resort binding because @@ -374,7 +374,7 @@ ConstraintSystem::determineBestBindings() { // First, let's collect all of the possible bindings. for (auto *typeVar : getTypeVariables()) { if (!typeVar->getImpl().hasRepresentativeOrFixed()) - cache.insert({typeVar, getPotentialBindings(typeVar)}); + cache.insert({typeVar, inferBindingsFor(typeVar, /*finalize=*/false)}); } // Determine whether given type variable with its set of bindings is @@ -481,6 +481,7 @@ void ConstraintSystem::PotentialBindings::addPotentialBinding( if (binding.Kind == AllowedBindingKind::Supertypes && !binding.BindingType->hasUnresolvedType() && !binding.BindingType->hasTypeVariable() && + !binding.BindingType->hasHole() && !binding.BindingType->hasUnboundGenericType() && !binding.hasDefaultedLiteralProtocol() && !binding.isDefaultableBinding() && allowJoinMeet) { @@ -577,20 +578,41 @@ bool ConstraintSystem::PotentialBindings::favoredOverDisjunction( } ConstraintSystem::PotentialBindings -ConstraintSystem::inferBindingsFor(TypeVariableType *typeVar) { - auto bindings = getPotentialBindings(typeVar); +ConstraintSystem::inferBindingsFor(TypeVariableType *typeVar, + bool finalize) const { + assert(typeVar->getImpl().getRepresentative(nullptr) == typeVar && + "not a representative"); + assert(!typeVar->getImpl().getFixedType(nullptr) && "has a fixed type"); + + PotentialBindings bindings(typeVar); + + // Gather the constraints associated with this type variable. + auto constraints = CG.gatherConstraints( + typeVar, ConstraintGraph::GatheringKind::EquivalenceClass); + + llvm::SmallPtrSet exactTypes; + + for (auto *constraint : constraints) { + bool failed = bindings.infer(*this, exactTypes, constraint); + + // Upon inference failure let's produce an empty set of bindings. + if (failed) + return {typeVar}; + } + + if (finalize) { + llvm::SmallDenseMap + inferred; + + bindings.finalize(*this, inferred); + } - llvm::SmallDenseMap - inferred; - bindings.finalize(*this, inferred); return bindings; } Optional ConstraintSystem::getPotentialBindingForRelationalConstraint( - PotentialBindings &result, Constraint *constraint, - bool &hasDependentMemberRelationalConstraints, - bool &hasNonDependentMemberRelationalConstraints) const { + PotentialBindings &result, Constraint *constraint) const { assert(constraint->getClassification() == ConstraintClassification::Relational && "only relational constraints handled here"); @@ -673,11 +695,11 @@ ConstraintSystem::getPotentialBindingForRelationalConstraint( if (type->is()) { if (!ConstraintSystem::typeVarOccursInType(typeVar, type, &result.InvolvesTypeVariables)) { - hasDependentMemberRelationalConstraints = true; + result.FullyBound = true; } + return None; } - hasNonDependentMemberRelationalConstraints = true; // If our binding choice is a function type and we're attempting // to bind to a type variable that is the result of opening a @@ -746,67 +768,46 @@ ConstraintSystem::getPotentialBindingForRelationalConstraint( /// Retrieve the set of potential type bindings for the given /// representative type variable, along with flags indicating whether /// those types should be opened. -ConstraintSystem::PotentialBindings -ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const { - assert(typeVar->getImpl().getRepresentative(nullptr) == typeVar && - "not a representative"); - assert(!typeVar->getImpl().getFixedType(nullptr) && "has a fixed type"); - - // Determines whether this type variable represents an object - // of the optional type extracted by force unwrap. - bool isOptionalObject = false; - if (auto *locator = typeVar->getImpl().getLocator()) { - auto anchor = locator->getAnchor(); - isOptionalObject = isExpr(anchor); - } - - // Gather the constraints associated with this type variable. - auto constraints = - getConstraintGraph().gatherConstraints( - typeVar, ConstraintGraph::GatheringKind::EquivalenceClass); - - PotentialBindings result(typeVar); +bool ConstraintSystem::PotentialBindings::infer( + const ConstraintSystem &cs, llvm::SmallPtrSetImpl &exactTypes, + Constraint *constraint) { + switch (constraint->getKind()) { + case ConstraintKind::Bind: + case ConstraintKind::Equal: + case ConstraintKind::BindParam: + case ConstraintKind::BindToPointerType: + case ConstraintKind::Subtype: + case ConstraintKind::Conversion: + case ConstraintKind::ArgumentConversion: + case ConstraintKind::OperatorArgumentConversion: + case ConstraintKind::OptionalObject: { + // If there is a `bind param` constraint associated with + // current type variable, result should be aware of that + // fact. Binding set might be incomplete until + // this constraint is resolved, because we currently don't + // look-through constraints expect to `subtype` to try and + // find related bindings. + // This only affects type variable that appears one the + // right-hand side of the `bind param` constraint and + // represents result type of the closure body, because + // left-hand side gets types from overload choices. + if (constraint->getKind() == ConstraintKind::BindParam && + constraint->getSecondType()->isEqual(TypeVar)) + PotentiallyIncomplete = true; - // Consider each of the constraints related to this type variable. - llvm::SmallPtrSet exactTypes; - SmallVector literalBindings; - bool hasNonDependentMemberRelationalConstraints = false; - bool hasDependentMemberRelationalConstraints = false; - for (auto constraint : constraints) { - switch (constraint->getKind()) { - case ConstraintKind::Bind: - case ConstraintKind::Equal: - case ConstraintKind::BindParam: - case ConstraintKind::BindToPointerType: - case ConstraintKind::Subtype: - case ConstraintKind::Conversion: - case ConstraintKind::ArgumentConversion: - case ConstraintKind::OperatorArgumentConversion: - case ConstraintKind::OptionalObject: { - // If there is a `bind param` constraint associated with - // current type variable, result should be aware of that - // fact. Binding set might be incomplete until - // this constraint is resolved, because we currently don't - // look-through constraints expect to `subtype` to try and - // find related bindings. - // This only affects type variable that appears one the - // right-hand side of the `bind param` constraint and - // represents result type of the closure body, because - // left-hand side gets types from overload choices. - if (constraint->getKind() == ConstraintKind::BindParam && - constraint->getSecondType()->isEqual(typeVar)) - result.PotentiallyIncomplete = true; - - auto binding = getPotentialBindingForRelationalConstraint( - result, constraint, hasDependentMemberRelationalConstraints, - hasNonDependentMemberRelationalConstraints); - if (!binding) - break; + auto binding = + cs.getPotentialBindingForRelationalConstraint(*this, constraint); + if (!binding) + break; - auto type = binding->BindingType; - if (exactTypes.insert(type->getCanonicalType()).second) { - result.addPotentialBinding(*binding); + auto type = binding->BindingType; + if (exactTypes.insert(type->getCanonicalType()).second) { + addPotentialBinding(*binding); + // Determines whether this type variable represents an object + // of the optional type extracted by force unwrap. + if (auto *locator = TypeVar->getImpl().getLocator()) { + auto anchor = locator->getAnchor(); // Result of force unwrap is always connected to its base // optional type via `OptionalObject` constraint which // preserves l-valueness, so in case where object type got @@ -814,191 +815,177 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const { // type from context e.g. parameter type of a function call), // we need to test type with and without l-value after // delaying bindings for as long as possible. - if (isOptionalObject && !type->is()) { - result.addPotentialBinding(binding->withType(LValueType::get(type))); - result.FullyBound = true; + if (isExpr(anchor) && !type->is()) { + addPotentialBinding(binding->withType(LValueType::get(type))); + FullyBound = true; } - if (auto *locator = typeVar->getImpl().getLocator()) { - auto path = locator->getPath(); - auto voidType = getASTContext().TheEmptyTupleType; - - // If this is a type variable representing closure result, - // which is on the right-side of some relational constraint - // let's have it try `Void` as well because there is an - // implicit conversion `() -> T` to `() -> Void` and this - // helps to avoid creating a thunk to support it. - if (!path.empty() && - path.back().getKind() == ConstraintLocator::ClosureResult && - binding->Kind == AllowedBindingKind::Supertypes && - exactTypes.insert(voidType).second) { - result.addPotentialBinding({voidType, binding->Kind, constraint}, - /*allowJoinMeet=*/false); - } + // If this is a type variable representing closure result, + // which is on the right-side of some relational constraint + // let's have it try `Void` as well because there is an + // implicit conversion `() -> T` to `() -> Void` and this + // helps to avoid creating a thunk to support it. + auto voidType = cs.getASTContext().TheEmptyTupleType; + if (locator->isLastElement() && + binding->Kind == AllowedBindingKind::Supertypes && + exactTypes.insert(voidType).second) { + addPotentialBinding({voidType, binding->Kind, constraint}, + /*allowJoinMeet=*/false); } } - break; } - case ConstraintKind::KeyPathApplication: { - if (result.FullyBound) - continue; + break; + } + case ConstraintKind::KeyPathApplication: { + if (FullyBound) + return false; + + // If this variable is in the application projected result type, mark the + // result as `FullyBound` to ensure we delay binding until we've bound + // other type variables in the KeyPathApplication constraint. This ensures + // we try to bind the key path type first, which can allow us to discover + // additional bindings for the result type. + SmallPtrSet typeVars; + findInferableTypeVars(cs.simplifyType(constraint->getThirdType()), + typeVars); + if (typeVars.count(TypeVar)) + FullyBound = true; - // If this variable is in the application projected result type, mark the - // result as `FullyBound` to ensure we delay binding until we've bound - // other type variables in the KeyPathApplication constraint. This ensures - // we try to bind the key path type first, which can allow us to discover - // additional bindings for the result type. - SmallPtrSet typeVars; - findInferableTypeVars(simplifyType(constraint->getThirdType()), typeVars); - if (typeVars.count(typeVar)) - result.FullyBound = true; + break; + } - break; + case ConstraintKind::BridgingConversion: + case ConstraintKind::CheckedCast: + case ConstraintKind::EscapableFunctionOf: + case ConstraintKind::OpenedExistentialOf: + case ConstraintKind::KeyPath: + case ConstraintKind::FunctionInput: + case ConstraintKind::FunctionResult: + case ConstraintKind::OpaqueUnderlyingType: + // Constraints from which we can't do anything. + break; + + case ConstraintKind::DynamicTypeOf: { + // Direct binding of the left-hand side could result + // in `DynamicTypeOf` failure if right-hand side is + // bound (because 'Bind' requires equal types to + // succeed), or left is bound to Any which is not an + // [existential] metatype. + auto dynamicType = constraint->getFirstType(); + if (auto *tv = dynamicType->getAs()) { + if (tv->getImpl().getRepresentative(nullptr) == TypeVar) + return true; } - case ConstraintKind::BridgingConversion: - case ConstraintKind::CheckedCast: - case ConstraintKind::EscapableFunctionOf: - case ConstraintKind::OpenedExistentialOf: - case ConstraintKind::KeyPath: - case ConstraintKind::FunctionInput: - case ConstraintKind::FunctionResult: - case ConstraintKind::OpaqueUnderlyingType: - // Constraints from which we can't do anything. - break; - - case ConstraintKind::DynamicTypeOf: { - // Direct binding of the left-hand side could result - // in `DynamicTypeOf` failure if right-hand side is - // bound (because 'Bind' requires equal types to - // succeed), or left is bound to Any which is not an - // [existential] metatype. - auto dynamicType = constraint->getFirstType(); - if (auto *tv = dynamicType->getAs()) { - if (tv->getImpl().getRepresentative(nullptr) == typeVar) - return {typeVar}; - } + // This is right-hand side, let's continue. + break; + } - // This is right-hand side, let's continue. - break; + case ConstraintKind::Defaultable: + case ConstraintKind::DefaultClosureType: + // Do these in a separate pass. + if (cs.getFixedTypeRecursive(constraint->getFirstType(), true) + ->getAs() == TypeVar) { + Defaults.push_back(constraint); } + break; + + case ConstraintKind::Disjunction: + // FIXME: Recurse into these constraints to see whether this + // type variable is fully bound by any of them. + InvolvesTypeVariables = true; + + // If there is additional context available via disjunction + // associated with closure literal (e.g. coercion to some other + // type) let's delay resolving the closure until the disjunction + // is attempted. + if (TypeVar->getImpl().isClosureType()) + return true; - case ConstraintKind::Defaultable: - case ConstraintKind::DefaultClosureType: - // Do these in a separate pass. - if (getFixedTypeRecursive(constraint->getFirstType(), true) - ->getAs() == typeVar) { - result.Defaults.push_back(constraint); - hasNonDependentMemberRelationalConstraints = true; - } - break; - - case ConstraintKind::Disjunction: - // FIXME: Recurse into these constraints to see whether this - // type variable is fully bound by any of them. - result.InvolvesTypeVariables = true; - - // If there is additional context available via disjunction - // associated with closure literal (e.g. coercion to some other - // type) let's delay resolving the closure until the disjunction - // is attempted. - if (typeVar->getImpl().isClosureType()) - return {typeVar}; - - break; - - case ConstraintKind::ConformsTo: - case ConstraintKind::SelfObjectOfProtocol: - // Swift 3 allowed the use of default types for normal conformances - // to expressible-by-literal protocols. - if (getASTContext().LangOpts.EffectiveLanguageVersion[0] >= 4) - continue; + break; - if (!constraint->getSecondType()->is()) - continue; + case ConstraintKind::ConformsTo: + case ConstraintKind::SelfObjectOfProtocol: + // Swift 3 allowed the use of default types for normal conformances + // to expressible-by-literal protocols. + if (cs.getASTContext().LangOpts.EffectiveLanguageVersion[0] >= 4) + return false; - LLVM_FALLTHROUGH; - - case ConstraintKind::LiteralConformsTo: { - // Record constraint where protocol requirement originated - // this is useful to use for the binding later. - result.Protocols.push_back(constraint); - hasNonDependentMemberRelationalConstraints = true; - break; - } + if (!constraint->getSecondType()->is()) + return false; - case ConstraintKind::ApplicableFunction: - case ConstraintKind::DynamicCallableApplicableFunction: - case ConstraintKind::BindOverload: { - if (result.FullyBound && result.InvolvesTypeVariables) - continue; + LLVM_FALLTHROUGH; - // If this variable is in the left-hand side, it is fully bound. - SmallPtrSet typeVars; - findInferableTypeVars(simplifyType(constraint->getFirstType()), typeVars); - if (typeVars.count(typeVar)) - result.FullyBound = true; + case ConstraintKind::LiteralConformsTo: { + // Record constraint where protocol requirement originated + // this is useful to use for the binding later. + Protocols.push_back(constraint); + break; + } - if (result.InvolvesTypeVariables) - continue; + case ConstraintKind::ApplicableFunction: + case ConstraintKind::DynamicCallableApplicableFunction: + case ConstraintKind::BindOverload: { + if (FullyBound && InvolvesTypeVariables) + return false; - // If this and another type variable occur, this result involves - // type variables. - findInferableTypeVars(simplifyType(constraint->getSecondType()), - typeVars); - if (typeVars.size() > 1 && typeVars.count(typeVar)) - result.InvolvesTypeVariables = true; + // If this variable is in the left-hand side, it is fully bound. + SmallPtrSet typeVars; + findInferableTypeVars(cs.simplifyType(constraint->getFirstType()), + typeVars); + if (typeVars.count(TypeVar)) + FullyBound = true; + + if (InvolvesTypeVariables) + return false; + + // If this and another type variable occur, this result involves + // type variables. + findInferableTypeVars(cs.simplifyType(constraint->getSecondType()), + typeVars); + if (typeVars.size() > 1 && typeVars.count(TypeVar)) + InvolvesTypeVariables = true; + + break; + } - break; + case ConstraintKind::ValueMember: + case ConstraintKind::UnresolvedValueMember: + case ConstraintKind::ValueWitness: + // If our type variable shows up in the base type, there's + // nothing to do. + // FIXME: Can we avoid simplification here? + if (ConstraintSystem::typeVarOccursInType( + TypeVar, cs.simplifyType(constraint->getFirstType()), + &InvolvesTypeVariables)) { + return false; } - case ConstraintKind::ValueMember: - case ConstraintKind::UnresolvedValueMember: - case ConstraintKind::ValueWitness: - // If our type variable shows up in the base type, there's - // nothing to do. - // FIXME: Can we avoid simplification here? - if (ConstraintSystem::typeVarOccursInType( - typeVar, simplifyType(constraint->getFirstType()), - &result.InvolvesTypeVariables)) { - continue; - } - - // If the type variable is in the list of member type - // variables, it is fully bound. - // FIXME: Can we avoid simplification here? - if (ConstraintSystem::typeVarOccursInType( - typeVar, simplifyType(constraint->getSecondType()), - &result.InvolvesTypeVariables)) { - result.FullyBound = true; - } - break; - - case ConstraintKind::OneWayEqual: - case ConstraintKind::OneWayBindParam: { - // Don't produce any bindings if this type variable is on the left-hand - // side of a one-way binding. - auto firstType = constraint->getFirstType(); - if (auto *tv = firstType->getAs()) { - if (tv->getImpl().getRepresentative(nullptr) == typeVar) - return {typeVar}; - } - - break; + // If the type variable is in the list of member type + // variables, it is fully bound. + // FIXME: Can we avoid simplification here? + if (ConstraintSystem::typeVarOccursInType( + TypeVar, cs.simplifyType(constraint->getSecondType()), + &InvolvesTypeVariables)) { + FullyBound = true; } + break; + + case ConstraintKind::OneWayEqual: + case ConstraintKind::OneWayBindParam: { + // Don't produce any bindings if this type variable is on the left-hand + // side of a one-way binding. + auto firstType = constraint->getFirstType(); + if (auto *tv = firstType->getAs()) { + if (tv->getImpl().getRepresentative(nullptr) == TypeVar) + return true; } - } - // If there were both dependent-member and non-dependent-member relational - // constraints, consider this "fully bound"; we don't want to touch it. - if (hasDependentMemberRelationalConstraints) { - if (hasNonDependentMemberRelationalConstraints) - result.FullyBound = true; - else - result.Bindings.clear(); + break; + } } - return result; + return false; } /// Check whether the given type can be used as a binding for the given @@ -1220,10 +1207,23 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const { } else if (TypeVar->getImpl().isClosureParameterType()) { fix = SpecifyClosureParameterType::create(cs, dstLocator); } else if (TypeVar->getImpl().isClosureResultType()) { - fix = SpecifyClosureReturnType::create(cs, dstLocator); + auto *locator = TypeVar->getImpl().getLocator(); + auto *closure = castToExpr(locator->getAnchor()); + // If the whole body is being ignored due to a pre-check failure, + // let's not record a fix about result type since there is + // just not enough context to infer it without a body. + if (!cs.hasFixFor(cs.getConstraintLocator(closure->getBody()), + FixKind::IgnoreInvalidFunctionBuilderBody)) + fix = SpecifyClosureReturnType::create(cs, dstLocator); } else if (srcLocator->directlyAt()) { fix = SpecifyObjectLiteralTypeImport::create(cs, dstLocator); } else if (srcLocator->isKeyPathRoot()) { + // If we recorded an invalid key path fix, let's skip this specify root + // type fix because it wouldn't produce a useful diagnostic. + auto *kpLocator = cs.getConstraintLocator(srcLocator->getAnchor()); + if (cs.hasFixFor(kpLocator, FixKind::AllowKeyPathWithoutComponents)) + return true; + fix = SpecifyKeyPathRootType::create(cs, dstLocator); } diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 4791518b68816..6562cc33e8915 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -17,8 +17,10 @@ #include "CSDiagnostics.h" #include "ConstraintSystem.h" #include "MiscDiagnostics.h" +#include "TypeCheckProtocol.h" #include "TypoCorrection.h" #include "swift/AST/ASTContext.h" +#include "swift/AST/ASTPrinter.h" #include "swift/AST/Decl.h" #include "swift/AST/ExistentialLayout.h" #include "swift/AST/Expr.h" @@ -753,6 +755,11 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() { break; } + case ConstraintLocator::UnresolvedMemberChainResult: { + diagnostic = diag::cannot_convert_chain_result_type; + break; + } + default: break; } @@ -1069,9 +1076,6 @@ bool MemberAccessOnOptionalBaseFailure::diagnoseAsError() { return false; auto sourceRange = getSourceRange(); - - emitDiagnostic(diag::optional_base_not_unwrapped, - baseType, Member, unwrappedBaseType); auto componentPathElt = locator->getLastElementAs(); @@ -1080,12 +1084,25 @@ bool MemberAccessOnOptionalBaseFailure::diagnoseAsError() { // let's emit a tailored note suggesting to use its unwrapped type. auto *keyPathExpr = castToExpr(getAnchor()); if (auto rootType = keyPathExpr->getRootType()) { + emitDiagnostic(diag::optional_base_not_unwrapped, baseType, Member, + unwrappedBaseType); + emitDiagnostic(diag::optional_base_remove_optional_for_keypath_root, unwrappedBaseType) .fixItReplace(rootType->getSourceRange(), unwrappedBaseType.getString()); + } else { + emitDiagnostic(diag::invalid_optional_infered_keypath_root, baseType, + Member, unwrappedBaseType); + emitDiagnostic(diag::optional_key_path_root_base_chain, Member) + .fixItInsert(sourceRange.End, "?."); + emitDiagnostic(diag::optional_key_path_root_base_unwrap, Member) + .fixItInsert(sourceRange.End, "!."); } } else { + emitDiagnostic(diag::optional_base_not_unwrapped, baseType, Member, + unwrappedBaseType); + // FIXME: It would be nice to immediately offer "base?.member ?? defaultValue" // for non-optional results where that would be appropriate. For the moment // always offering "?" means that if the user chooses chaining, we'll end up @@ -1124,6 +1141,8 @@ void MissingOptionalUnwrapFailure::offerDefaultValueUnwrapFixIt( bool needsParensInside = exprNeedsParensBeforeAddingNilCoalescing(DC, const_cast(expr)); auto parentExpr = findParentExpr(anchor); + if (parentExpr && isa(parentExpr)) + parentExpr = findParentExpr(parentExpr); bool needsParensOutside = exprNeedsParensAfterAddingNilCoalescing( DC, const_cast(expr), parentExpr); @@ -1177,7 +1196,7 @@ class VarDeclMultipleReferencesChecker : public ASTWalker { VarDecl *varDecl; int count; - std::pair walkToExprPre(Expr *E) { + std::pair walkToExprPre(Expr *E) override { if (auto *DRE = dyn_cast(E)) { if (DRE->getDecl() == varDecl) ++count; @@ -1198,14 +1217,6 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() { auto *anchor = castToExpr(getAnchor()); - // If this is an unresolved member expr e.g. `.foo` its - // base type is going to be the same as result type minus - // r-value adjustment because base could be an l-value type. - // We want to fix both cases by only diagnose one of them, - // otherwise this is just going to result in a duplcate diagnostic. - if (getLocator()->isLastElement()) - return false; - if (auto assignExpr = dyn_cast(anchor)) anchor = assignExpr->getSrc(); @@ -1235,8 +1246,10 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() { assert(!baseType->hasTypeVariable() && "Base type must not be a type variable"); + assert(!baseType->isHole() && "Base type must not be a type hole"); assert(!unwrappedType->hasTypeVariable() && "Unwrapped type must not be a type variable"); + assert(!unwrappedType->isHole() && "Unwrapped type must not be a type hole"); if (!baseType->getOptionalObjectType()) return false; @@ -1313,6 +1326,11 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() { if (getContextualTypePurpose(diagExpr) == CTP_Condition) return false; + // If the failure happened at the end of an unresolved member chain, it should + // be diagnosed instead as though it happened at the last element. + if (auto chainExpr = dyn_cast(diagExpr)) + diagExpr = chainExpr->getSubExpr(); + if (auto assignExpr = dyn_cast(diagExpr)) { // Let's check whether this is an attempt to assign // variable or property to itself. @@ -1436,6 +1454,8 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() { } } else if (isa(diagExpr)) { subElementDiagID = diag::assignment_subscript_has_immutable_base; + } else if (auto *UME = dyn_cast(diagExpr)) { + subElementDiagID = diag::assignment_lhs_is_immutable_property; } else { subElementDiagID = diag::assignment_lhs_is_immutable_variable; } @@ -1860,7 +1880,9 @@ AssignmentFailure::resolveImmutableBase(Expr *expr) const { // In Swift versions lower than 5, this check will fail as read only // key paths can masquerade as writable for compatibilty reasons. // This is fine as in this case we just fall back on old diagnostics. - if (bgt->getDecl() == getASTContext().getKeyPathDecl()) { + auto &ctx = getASTContext(); + if (bgt->getDecl() == ctx.getKeyPathDecl() || + bgt->getDecl() == ctx.getPartialKeyPathDecl()) { return {expr, member}; } } @@ -1900,6 +1922,18 @@ AssignmentFailure::resolveImmutableBase(Expr *expr) const { return resolveImmutableBase(MRE->getBase()); } + if (auto *UME = dyn_cast(expr)) { + auto loc = getConstraintLocator(UME, ConstraintLocator::UnresolvedMember); + auto member = getMemberRef(loc); + + // If we can resolve a member, we can determine whether it is settable in + // this context. + if (member && member->isDecl() && isImmutable(member->getDecl())) + return {expr, member}; + else + return {expr, None}; + } + if (auto *DRE = dyn_cast(expr)) return {expr, OverloadChoice(Type(), DRE->getDecl(), FunctionRefKind::Unapplied)}; @@ -2133,10 +2167,11 @@ bool ContextualFailure::diagnoseAsError() { return false; } - case ConstraintLocator::RValueAdjustment: { + case ConstraintLocator::UnresolvedMemberChainResult: { auto &solution = getSolution(); - auto overload = getOverloadChoiceIfAvailable( - getConstraintLocator(anchor, ConstraintLocator::UnresolvedMember)); + + auto overload = + getCalleeOverloadChoiceIfAvailable(getConstraintLocator(anchor)); if (!(overload && overload->choice.isDecl())) return false; @@ -2171,13 +2206,22 @@ bool ContextualFailure::diagnoseAsError() { }); if (numMissingArgs == 0 || numMissingArgs > 1) { - auto diagnostic = emitDiagnostic( - diag::expected_parens_in_contextual_member, choice->getName()); - - // If there are no parameters we can suggest a fix-it - // to form an explicit call. - if (numMissingArgs == 0) - diagnostic.fixItInsertAfter(getSourceRange().End, "()"); + auto applyFixIt = [&](InFlightDiagnostic &diagnostic) { + // If there are no parameters we can suggest a fix-it + // to form an explicit call. + if (numMissingArgs == 0) + diagnostic.fixItInsertAfter(getSourceRange().End, "()"); + }; + if (fnType->getResult()->isEqual(toType)) { + auto diag = emitDiagnostic( + diag::expected_parens_in_contextual_member_type, + choice->getName(), fnType->getResult()); + applyFixIt(diag); + } else { + auto diag = emitDiagnostic(diag::expected_parens_in_contextual_member, + choice->getName()); + applyFixIt(diag); + } } else { emitDiagnostic(diag::expected_argument_in_contextual_member, choice->getName(), params.front().getPlainType()); @@ -2396,6 +2440,10 @@ bool ContextualFailure::diagnoseMissingFunctionCall() const { if (getLocator()->isLastElement()) return false; + if (getLocator() + ->isLastElement()) + return false; + auto *srcFT = getFromType()->getAs(); if (!srcFT || !(srcFT->getParams().empty() || @@ -2766,9 +2814,11 @@ bool ContextualFailure::tryProtocolConformanceFixIt( // Let's build a list of protocols that the context does not conform to. SmallVector missingProtoTypeStrings; + SmallVector missingProtocols; for (auto protocol : layout.getProtocols()) { if (!TypeChecker::conformsToProtocol(fromType, protocol->getDecl(), getDC())) { missingProtoTypeStrings.push_back(protocol->getString()); + missingProtocols.push_back(protocol->getDecl()); } } @@ -2790,8 +2840,6 @@ bool ContextualFailure::tryProtocolConformanceFixIt( // Emit a diagnostic to inform the user that they need to conform to the // missing protocols. - // - // TODO: Maybe also insert the requirement stubs? auto conformanceDiag = emitDiagnostic(diag::assign_protocol_conformance_fix_it, unwrappedToType, nominal->getDescriptiveKind(), fromType); @@ -2806,6 +2854,35 @@ bool ContextualFailure::tryProtocolConformanceFixIt( conformanceDiag.fixItInsert(nameEndLoc, ": " + protoString); } + // Emit fix-its to insert requirement stubs if we're in editor mode. + if (!getASTContext().LangOpts.DiagnosticsEditorMode) { + return true; + } + + { + llvm::SmallString<128> Text; + llvm::raw_svector_ostream SS(Text); + llvm::SetVector missingWitnesses; + for (auto protocol : missingProtocols) { + auto conformance = NormalProtocolConformance( + nominal->getDeclaredType(), protocol, SourceLoc(), nominal, + ProtocolConformanceState::Incomplete); + ConformanceChecker checker(getASTContext(), &conformance, + missingWitnesses); + checker.resolveValueWitnesses(); + checker.resolveTypeWitnesses(); + } + + for (auto decl : missingWitnesses) { + swift::printRequirementStub(decl, nominal, nominal->getDeclaredType(), + nominal->getStartLoc(), SS); + } + + if (!Text.empty()) { + conformanceDiag.fixItInsertAfter(nominal->getBraces().Start, Text.str()); + } + } + return true; } @@ -3409,6 +3486,13 @@ bool MissingMemberFailure::diagnoseInLiteralCollectionContext() const { if (!(parentExpr && isa(expr))) return false; + if (!isa(parentExpr)) + return false; + + parentExpr = findParentExpr(parentExpr); + if (!parentExpr) + return false; + auto parentType = getType(parentExpr); if (!parentType->isKnownStdlibCollectionType() && !parentType->is()) @@ -4425,9 +4509,6 @@ MissingArgumentsFailure::getCallInfo(ASTNode anchor) const { return std::make_tuple(call->getFn(), call->getArg(), call->getNumArguments(), call->getUnlabeledTrailingClosureIndex()); - } else if (auto *UME = getAsExpr(anchor)) { - return std::make_tuple(UME, UME->getArgument(), UME->getNumArguments(), - UME->getUnlabeledTrailingClosureIndex()); } else if (auto *SE = getAsExpr(anchor)) { return std::make_tuple(SE, SE->getIndex(), SE->getNumArguments(), SE->getUnlabeledTrailingClosureIndex()); @@ -5002,7 +5083,7 @@ bool ExtraneousReturnFailure::diagnoseAsError() { // cases like like 'var foo: () { return 1 }' as here that loc will // be invalid. We also need to check that the name is not empty, // because certain decls will have empty name (like setters). - if (FD->getBodyResultTypeLoc().getLoc().isInvalid() && + if (FD->getResultTypeRepr() == nullptr && FD->getParameters()->getStartLoc().isValid() && !FD->getBaseIdentifier().empty()) { auto fixItLoc = Lexer::getLocForEndOfToken( @@ -5055,7 +5136,7 @@ bool CollectionElementContextualFailure::diagnoseAsError() { // holes present in the contextual type. if (FailureDiagnostic::getContextualTypePurpose(getAnchor()) == ContextualTypePurpose::CTP_ForEachStmt && - contextualType->hasHole()) { + contextualType->hasUnresolvedType()) { diagnostic.emplace(emitDiagnostic( (contextualType->is() && !eltType->is()) ? diag::cannot_match_expr_tuple_pattern_with_nontuple_value @@ -6266,6 +6347,20 @@ bool MissingContextualBaseInMemberRefFailure::diagnoseAsError() { // Member reference could be wrapped into a number of parens // e.g. `((.foo))`. auto *parentExpr = findParentExpr(anchor); + + // Look through immediate call of unresolved member (e.g., `.foo(0)`). + if (parentExpr && isa(parentExpr)) + parentExpr = findParentExpr(parentExpr); + + // FIXME: We should probably look through the entire member chain so that + // something like `let _ = .foo().bar` gets the "no contextual type" error + // rather than the "Cannot infer contextual base" error. + UnresolvedMemberChainResultExpr *resultExpr = nullptr; + if (parentExpr && isa(parentExpr)) { + resultExpr = cast(parentExpr); + parentExpr = findParentExpr(parentExpr); + } + do { // If we have found something which isn't a paren let's stop, // otherwise let's keep unwrapping until there are either no @@ -6274,7 +6369,7 @@ bool MissingContextualBaseInMemberRefFailure::diagnoseAsError() { break; } while ((parentExpr = findParentExpr(parentExpr))); - auto diagnostic = parentExpr || getContextualType(anchor) + auto diagnostic = parentExpr || (resultExpr && getContextualType(resultExpr)) ? diag::cannot_infer_base_of_unresolved_member : diag::unresolved_member_no_inference; @@ -6313,7 +6408,7 @@ bool UnableToInferClosureParameterType::diagnoseAsError() { if (parentExpr) { // Missing or invalid member reference in call. if (auto *AE = dyn_cast(parentExpr)) { - if (getType(AE->getFn())->isHole()) + if (getType(AE->getFn())->is()) return false; } @@ -6760,3 +6855,19 @@ void TrailingClosureRequiresExplicitLabel::fixIt( diagnostic.fixItInsert(newRParenLoc, isExpr(anchor) ? "]" : ")"); } + +bool InvalidEmptyKeyPathFailure::diagnoseAsError() { + auto *KPE = getAsExpr(getAnchor()); + assert(KPE && KPE->hasSingleInvalidComponent() && + "Expected a malformed key path expression"); + + // If we have a string interpolation represented as key path expressions + // e.g. \(x), \(x, a: 1). Let's skip it because this would be already + // diagnosed and it is not the case for an extra empty key path diagnostic. + auto *root = KPE->getParsedRoot(); + if (root && (isa(root) || isa(root))) + return true; + + emitDiagnostic(diag::expr_swift_keypath_empty); + return true; +} diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 30192dbc20fc4..956c91736dd0e 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -94,20 +94,26 @@ class FailureDiagnostic { /// Resolve type variables present in the raw type, if any. Type resolveType(Type rawType, bool reconstituteSugar = false, bool wantRValue = true) const { - if (!rawType->hasTypeVariable()) { - if (reconstituteSugar) - rawType = rawType->reconstituteSugar(/*recursive*/ true); - return wantRValue ? rawType->getRValueType() : rawType; + auto &cs = getConstraintSystem(); + + if (rawType->hasTypeVariable() || rawType->hasHole()) { + rawType = rawType.transform([&](Type type) { + if (auto *typeVar = type->getAs()) { + auto resolvedType = S.simplifyType(typeVar); + Type GP = typeVar->getImpl().getGenericParameter(); + return resolvedType->is() && GP + ? GP + : resolvedType; + } + + return type->isHole() ? Type(cs.getASTContext().TheUnresolvedType) + : type; + }); } - auto &cs = getConstraintSystem(); - return cs.simplifyTypeImpl(rawType, [&](TypeVariableType *typeVar) -> Type { - auto fixed = S.simplifyType(typeVar); - auto *genericParam = typeVar->getImpl().getGenericParameter(); - if (fixed->isHole() && genericParam) - return genericParam; - return resolveType(fixed, reconstituteSugar, wantRValue); - }); + if (reconstituteSugar) + rawType = rawType->reconstituteSugar(/*recursive*/ true); + return wantRValue ? rawType->getRValueType() : rawType; } template @@ -2013,7 +2019,7 @@ class MissingContextualBaseInMemberRefFailure final : public FailureDiagnostic { ConstraintLocator *locator) : FailureDiagnostic(solution, locator), MemberName(member) {} - bool diagnoseAsError(); + bool diagnoseAsError() override; }; class UnableToInferClosureParameterType final : public FailureDiagnostic { @@ -2022,7 +2028,7 @@ class UnableToInferClosureParameterType final : public FailureDiagnostic { ConstraintLocator *locator) : FailureDiagnostic(solution, locator) {} - bool diagnoseAsError(); + bool diagnoseAsError() override; }; class UnableToInferClosureReturnType final : public FailureDiagnostic { @@ -2031,7 +2037,7 @@ class UnableToInferClosureReturnType final : public FailureDiagnostic { ConstraintLocator *locator) : FailureDiagnostic(solution, locator) {} - bool diagnoseAsError(); + bool diagnoseAsError() override; }; class UnableToInferProtocolLiteralType final : public FailureDiagnostic { @@ -2065,7 +2071,7 @@ class MissingQuialifierInMemberRefFailure final : public FailureDiagnostic { ConstraintLocator *locator) : FailureDiagnostic(solution, locator) {} - bool diagnoseAsError(); + bool diagnoseAsError() override; }; /// Emits a warning about an attempt to use the 'as' operator as the 'as!' @@ -2248,6 +2254,20 @@ class TrailingClosureRequiresExplicitLabel final : public FailureDiagnostic { const FunctionArgApplyInfo &info) const; }; +/// Diagnose situations where we have a key path with no components. +/// +/// \code +/// let _ : KeyPath = \A +/// \endcode +class InvalidEmptyKeyPathFailure final : public FailureDiagnostic { +public: + InvalidEmptyKeyPathFailure(const Solution &solution, + ConstraintLocator *locator) + : FailureDiagnostic(solution, locator) {} + + bool diagnoseAsError() override; +}; + } // end namespace constraints } // end namespace swift diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 96f6a43872284..80cc9fc225ad6 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -1539,3 +1539,59 @@ SpecifyLabelToAssociateTrailingClosure::create(ConstraintSystem &cs, return new (cs.getAllocator()) SpecifyLabelToAssociateTrailingClosure(cs, locator); } + +bool AllowKeyPathWithoutComponents::diagnose(const Solution &solution, + bool asNote) const { + InvalidEmptyKeyPathFailure failure(solution, getLocator()); + return failure.diagnose(asNote); +} + +AllowKeyPathWithoutComponents * +AllowKeyPathWithoutComponents::create(ConstraintSystem &cs, + ConstraintLocator *locator) { + return new (cs.getAllocator()) AllowKeyPathWithoutComponents(cs, locator); +} + +bool IgnoreInvalidFunctionBuilderBody::diagnose(const Solution &solution, + bool asNote) const { + auto *S = getAnchor().get(); + + class PreCheckWalker : public ASTWalker { + DeclContext *DC; + DiagnosticTransaction Transaction; + + public: + PreCheckWalker(DeclContext *dc) + : DC(dc), Transaction(dc->getASTContext().Diags) {} + + std::pair walkToExprPre(Expr *E) override { + auto hasError = ConstraintSystem::preCheckExpression( + E, DC, /*replaceInvalidRefsWithErrors=*/true); + return std::make_pair(false, hasError ? nullptr : E); + } + + std::pair walkToStmtPre(Stmt *S) override { + return std::make_pair(true, S); + } + + // Ignore patterns because function builder pre-check does so as well. + std::pair walkToPatternPre(Pattern *P) override { + return std::make_pair(false, P); + } + + bool diagnosed() const { + return Transaction.hasDiagnostics(); + } + }; + + PreCheckWalker walker(solution.getDC()); + S->walk(walker); + + return walker.diagnosed(); +} + +IgnoreInvalidFunctionBuilderBody * +IgnoreInvalidFunctionBuilderBody::create(ConstraintSystem &cs, + ConstraintLocator *locator) { + return new (cs.getAllocator()) IgnoreInvalidFunctionBuilderBody(cs, locator); +} diff --git a/lib/Sema/CSFix.h b/lib/Sema/CSFix.h index ae232f33ff187..7bcaf50f85c65 100644 --- a/lib/Sema/CSFix.h +++ b/lib/Sema/CSFix.h @@ -266,13 +266,19 @@ enum class FixKind : uint8_t { /// Specify key path root type when it cannot be infered from context. SpecifyKeyPathRootType, - + /// Unwrap optional base on key path application. UnwrapOptionalBaseKeyPathApplication, /// Explicitly specify a label to match trailing closure to a certain /// parameter in the call. SpecifyLabelToAssociateTrailingClosure, + + /// Allow key path expressions with no components. + AllowKeyPathWithoutComponents, + + /// Ignore function builder body which fails `pre-check` call. + IgnoreInvalidFunctionBuilderBody, }; class ConstraintFix { @@ -1694,9 +1700,9 @@ class CoerceToCheckedCast final : public ContextualMismatch { locator) {} public: - std::string getName() const { return "as to as!"; } + std::string getName() const override { return "as to as!"; } - bool diagnose(const Solution &solution, bool asNote = false) const; + bool diagnose(const Solution &solution, bool asNote = false) const override; static CoerceToCheckedCast *attempt(ConstraintSystem &cs, Type fromType, Type toType, ConstraintLocator *locator); @@ -1707,11 +1713,11 @@ class RemoveInvalidCall final : public ConstraintFix { : ConstraintFix(cs, FixKind::RemoveCall, locator) {} public: - std::string getName() const { + std::string getName() const override { return "remove extraneous call from value of non-function type"; } - bool diagnose(const Solution &solution, bool asNote = false) const; + bool diagnose(const Solution &solution, bool asNote = false) const override; static RemoveInvalidCall *create(ConstraintSystem &cs, ConstraintLocator *locator); @@ -1749,13 +1755,13 @@ class SpecifyBaseTypeForContextualMember final : public ConstraintFix { MemberName(member) {} public: - std::string getName() const { + std::string getName() const override { const auto baseName = MemberName.getBaseName(); return "specify base type in reference to member '" + baseName.userFacingName().str() + "'"; } - bool diagnose(const Solution &solution, bool asNote = false) const; + bool diagnose(const Solution &solution, bool asNote = false) const override; static SpecifyBaseTypeForContextualMember * create(ConstraintSystem &cs, DeclNameRef member, ConstraintLocator *locator); @@ -1766,9 +1772,9 @@ class SpecifyClosureParameterType final : public ConstraintFix { : ConstraintFix(cs, FixKind::SpecifyClosureParameterType, locator) {} public: - std::string getName() const; + std::string getName() const override; - bool diagnose(const Solution &solution, bool asNote = false) const; + bool diagnose(const Solution &solution, bool asNote = false) const override; static SpecifyClosureParameterType *create(ConstraintSystem &cs, ConstraintLocator *locator); @@ -1779,11 +1785,11 @@ class SpecifyClosureReturnType final : public ConstraintFix { : ConstraintFix(cs, FixKind::SpecifyClosureReturnType, locator) {} public: - std::string getName() const { + std::string getName() const override { return "specify closure return type"; } - bool diagnose(const Solution &solution, bool asNote = false) const; + bool diagnose(const Solution &solution, bool asNote = false) const override; static SpecifyClosureReturnType *create(ConstraintSystem &cs, ConstraintLocator *locator); @@ -1794,11 +1800,11 @@ class SpecifyObjectLiteralTypeImport final : public ConstraintFix { : ConstraintFix(cs, FixKind::SpecifyObjectLiteralTypeImport, locator) {} public: - std::string getName() const { + std::string getName() const override { return "import required module to gain access to a default literal type"; } - bool diagnose(const Solution &solution, bool asNote = false) const; + bool diagnose(const Solution &solution, bool asNote = false) const override; static SpecifyObjectLiteralTypeImport *create(ConstraintSystem &cs, ConstraintLocator *locator); @@ -1810,11 +1816,11 @@ class AddQualifierToAccessTopLevelName final : public ConstraintFix { : ConstraintFix(cs, FixKind::AddQualifierToAccessTopLevelName, locator) {} public: - std::string getName() const { + std::string getName() const override { return "qualify reference to access top-level function"; } - bool diagnose(const Solution &solution, bool asNote = false) const; + bool diagnose(const Solution &solution, bool asNote = false) const override; static AddQualifierToAccessTopLevelName *create(ConstraintSystem &cs, ConstraintLocator *locator); @@ -1825,11 +1831,11 @@ class AllowNonClassTypeToConvertToAnyObject final : public ContextualMismatch { ConstraintLocator *locator); public: - std::string getName() const { + std::string getName() const override { return "allow non-class type to convert to 'AnyObject'"; } - bool diagnose(const Solution &solution, bool asNote = false) const; + bool diagnose(const Solution &solution, bool asNote = false) const override; static AllowNonClassTypeToConvertToAnyObject * create(ConstraintSystem &cs, Type type, ConstraintLocator *locator); @@ -1852,11 +1858,11 @@ class AllowCoercionToForceCast final : public ContextualMismatch { toType, locator, /*warning*/ true) {} public: - std::string getName() const { + std::string getName() const override { return "allow coercion to be treated as a force-cast"; } - bool diagnose(const Solution &solution, bool asNote = false) const; + bool diagnose(const Solution &solution, bool asNote = false) const override; static AllowCoercionToForceCast *create(ConstraintSystem &cs, Type fromType, Type toType, @@ -1894,11 +1900,11 @@ class SpecifyKeyPathRootType final : public ConstraintFix { : ConstraintFix(cs, FixKind::SpecifyKeyPathRootType, locator) {} public: - std::string getName() const { + std::string getName() const override { return "specify key path root type"; } - bool diagnose(const Solution &solution, bool asNote = false) const; + bool diagnose(const Solution &solution, bool asNote = false) const override; static SpecifyKeyPathRootType *create(ConstraintSystem &cs, ConstraintLocator *locator); @@ -1958,6 +1964,45 @@ class SpecifyLabelToAssociateTrailingClosure final : public ConstraintFix { create(ConstraintSystem &cs, ConstraintLocator *locator); }; +/// Diagnose situations where we have a key path with no components. +/// +/// \code +/// let _ : KeyPath = \A +/// \endcode +class AllowKeyPathWithoutComponents final : public ConstraintFix { + AllowKeyPathWithoutComponents(ConstraintSystem &cs, + ConstraintLocator *locator) + : ConstraintFix(cs, FixKind::AllowKeyPathWithoutComponents, locator) {} + +public: + std::string getName() const override { return "key path missing component"; } + + bool diagnose(const Solution &solution, bool asNote = false) const override; + + static AllowKeyPathWithoutComponents *create(ConstraintSystem &cs, + ConstraintLocator *locator); +}; + +class IgnoreInvalidFunctionBuilderBody final : public ConstraintFix { + IgnoreInvalidFunctionBuilderBody(ConstraintSystem &cs, + ConstraintLocator *locator) + : ConstraintFix(cs, FixKind::IgnoreInvalidFunctionBuilderBody, locator) {} + +public: + std::string getName() const override { + return "ignore invalid function builder body"; + } + + bool diagnose(const Solution &solution, bool asNote = false) const override; + + bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override { + return diagnose(*commonFixes.front().first); + } + + static IgnoreInvalidFunctionBuilderBody *create(ConstraintSystem &cs, + ConstraintLocator *locator); +}; + } // end namespace constraints } // end namespace swift diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index b4f0c1facc721..496052c162432 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -79,22 +79,10 @@ namespace { /// Internal struct for tracking information about types within a series /// of "linked" expressions. (Such as a chain of binary operator invocations.) struct LinkedTypeInfo { - unsigned haveIntLiteral : 1; - unsigned haveFloatLiteral : 1; - unsigned haveStringLiteral : 1; + bool hasLiteral = false; llvm::SmallSet collectedTypes; llvm::SmallVector binaryExprs; - - LinkedTypeInfo() { - haveIntLiteral = false; - haveFloatLiteral = false; - haveStringLiteral = false; - } - - bool hasLiteral() { - return haveIntLiteral || haveFloatLiteral || haveStringLiteral; - } }; /// Walks an expression sub-tree, and collects information about expressions @@ -180,19 +168,9 @@ namespace { !CS.getType(expr)->hasTypeVariable()) { return { false, expr }; } - - if (isa(expr)) { - LTI.haveIntLiteral = true; - return { false, expr }; - } - - if (isa(expr)) { - LTI.haveFloatLiteral = true; - return { false, expr }; - } - - if (isa(expr)) { - LTI.haveStringLiteral = true; + + if (isa(expr)) { + LTI.hasLiteral = true; return { false, expr }; } @@ -331,7 +309,7 @@ namespace { auto simplifyBinOpExprTyVars = [&]() { // Don't attempt to do linking if there are // literals intermingled with other inferred types. - if (lti.hasLiteral()) + if (lti.hasLiteral) return; for (auto binExp1 : lti.binaryExprs) { @@ -391,42 +369,6 @@ namespace { simplifyBinOpExprTyVars(); return true; - } - - if (lti.haveFloatLiteral) { - if (auto floatProto = CS.getASTContext().getProtocol( - KnownProtocolKind::ExpressibleByFloatLiteral)) { - if (auto defaultType = TypeChecker::getDefaultType(floatProto, CS.DC)) { - if (!CS.getFavoredType(expr)) { - CS.setFavoredType(expr, defaultType.getPointer()); - } - return true; - } - } - } - - if (lti.haveIntLiteral) { - if (auto intProto = CS.getASTContext().getProtocol( - KnownProtocolKind::ExpressibleByIntegerLiteral)) { - if (auto defaultType = TypeChecker::getDefaultType(intProto, CS.DC)) { - if (!CS.getFavoredType(expr)) { - CS.setFavoredType(expr, defaultType.getPointer()); - } - return true; - } - } - } - - if (lti.haveStringLiteral) { - if (auto stringProto = CS.getASTContext().getProtocol( - KnownProtocolKind::ExpressibleByStringLiteral)) { - if (auto defTy = TypeChecker::getDefaultType(stringProto, CS.DC)) { - if (!CS.getFavoredType(expr)) { - CS.setFavoredType(expr, defTy.getPointer()); - } - return true; - } - } } return false; @@ -850,6 +792,10 @@ namespace { /// Keep track of acceptable DiscardAssignmentExpr's. llvm::SmallPtrSet CorrectDiscardAssignmentExprs; + /// A map from each UnresolvedMemberExpr to the respective (implicit) base + /// found during our walk. + llvm::MapVector UnresolvedBaseTypes; + /// Returns false and emits the specified diagnostic if the member reference /// base is a nil literal. Returns true otherwise. bool isValidBaseOfMemberRef(Expr *base, Diag<> diagnostic) { @@ -1480,15 +1426,21 @@ namespace { Type visitDynamicMemberRefExpr(DynamicMemberRefExpr *expr) { llvm_unreachable("Already typechecked"); } + + void setUnresolvedBaseType(UnresolvedMemberExpr *UME, Type ty) { + UnresolvedBaseTypes.insert({UME, ty}); + } + + Type getUnresolvedBaseType(UnresolvedMemberExpr *UME) { + auto result = UnresolvedBaseTypes.find(UME); + assert(result != UnresolvedBaseTypes.end()); + return result->second; + } virtual Type visitUnresolvedMemberExpr(UnresolvedMemberExpr *expr) { auto baseLocator = CS.getConstraintLocator( expr, ConstraintLocator::MemberRefBase); - FunctionRefKind functionRefKind = - expr->getArgument() ? FunctionRefKind::DoubleApply - : FunctionRefKind::Compound; - auto memberLocator = CS.getConstraintLocator(expr, ConstraintLocator::UnresolvedMember); @@ -1496,6 +1448,8 @@ namespace { // should be marked as a potential hole. auto baseTy = CS.createTypeVariable(baseLocator, TVO_CanBindToNoEscape | TVO_CanBindToHole); + setUnresolvedBaseType(expr, baseTy); + auto memberTy = CS.createTypeVariable( memberLocator, TVO_CanBindToLValue | TVO_CanBindToNoEscape); @@ -1508,54 +1462,38 @@ namespace { // member, i.e., an enum case or a static variable. auto baseMetaTy = MetatypeType::get(baseTy); CS.addUnresolvedValueMemberConstraint(baseMetaTy, expr->getName(), - memberTy, CurDC, functionRefKind, + memberTy, CurDC, + expr->getFunctionRefKind(), memberLocator); + return memberTy; + } + + Type visitUnresolvedMemberChainResultExpr( + UnresolvedMemberChainResultExpr *expr) { + auto *tail = expr->getSubExpr(); + auto memberTy = CS.getType(tail); + auto *base = expr->getChainBase(); + assert(base == TypeChecker::getUnresolvedMemberChainBase(tail)); + + // The result type of the chain is is represented by a new type variable. + auto locator = CS.getConstraintLocator( + expr, ConstraintLocator::UnresolvedMemberChainResult); + auto chainResultTy = CS.createTypeVariable( + locator, + TVO_CanBindToLValue | TVO_CanBindToHole | TVO_CanBindToNoEscape); + auto chainBaseTy = getUnresolvedBaseType(base); + + // The result of the last element of the chain must be convertible to the + // whole chain, and the type of the whole chain must be equal to the base. + CS.addConstraint( + ConstraintKind::Conversion, memberTy, chainBaseTy, + CS.getConstraintLocator(tail, ConstraintLocator::RValueAdjustment)); + CS.addConstraint(ConstraintKind::Conversion, memberTy, chainResultTy, + locator); + CS.addConstraint(ConstraintKind::Equal, chainBaseTy, chainResultTy, + locator); - // If there is an argument, apply it. - if (auto arg = expr->getArgument()) { - // The result type of the function must be convertible to the base type. - // TODO: we definitely want this to include ImplicitlyUnwrappedOptional; - // does it need to include everything else in the world? - auto outputTy = CS.createTypeVariable( - CS.getConstraintLocator(expr, ConstraintLocator::FunctionResult), - TVO_CanBindToNoEscape); - CS.addConstraint(ConstraintKind::Conversion, outputTy, baseTy, - CS.getConstraintLocator(expr, ConstraintLocator::RValueAdjustment)); - - // The function/enum case must be callable with the given argument. - - // FIXME: Redesign the AST so that an UnresolvedMemberExpr directly - // stores a list of arguments together with their inout-ness, instead of - // a single ParenExpr or TupleExpr argument. - SmallVector params; - AnyFunctionType::decomposeInput(CS.getType(arg), params); - - CS.addConstraint(ConstraintKind::ApplicableFunction, - FunctionType::get(params, outputTy), - memberTy, - CS.getConstraintLocator(expr, ConstraintLocator::ApplyFunction)); - - associateArgumentLabels( - CS.getConstraintLocator(expr), - {expr->getArgumentLabels(), - expr->getUnlabeledTrailingClosureIndex()}); - return baseTy; - } - - // Otherwise, the member needs to be convertible to the base type. - CS.addConstraint(ConstraintKind::Conversion, memberTy, baseTy, - CS.getConstraintLocator(expr, ConstraintLocator::RValueAdjustment)); - - // The member type also needs to be convertible to the context type, which - // preserves lvalue-ness. - auto resultTy = CS.createTypeVariable(memberLocator, - TVO_CanBindToLValue | - TVO_CanBindToNoEscape); - CS.addConstraint(ConstraintKind::Conversion, memberTy, resultTy, - memberLocator); - CS.addConstraint(ConstraintKind::Equal, resultTy, baseTy, - memberLocator); - return resultTy; + return chainResultTy; } Type visitUnresolvedDotExpr(UnresolvedDotExpr *expr) { @@ -2114,56 +2052,44 @@ namespace { } } - auto extInfo = FunctionType::ExtInfo(); - if (closureCanThrow(closure)) - extInfo = extInfo.withThrows(); + auto extInfo = closureEffects(closure); // Closure expressions always have function type. In cases where a // parameter or return type is omitted, a fresh type variable is used to // stand in for that parameter or return type, allowing it to be inferred // from context. - auto getExplicitResultType = [&]() -> Type { - if (!closure->hasExplicitResultType()) { - return Type(); - } + Type resultTy = [&] { + if (closure->hasExplicitResultType()) { + if (auto declaredTy = closure->getExplicitResultType()) { + return declaredTy; + } - if (auto declaredTy = closure->getExplicitResultType()) { - return declaredTy; + const auto resolvedTy = resolveTypeReferenceInExpression( + closure->getExplicitResultTypeRepr(), + TypeResolverContext::InExpression, + // Introduce type variables for unbound generics. + OpenUnboundGenericType( + CS, CS.getConstraintLocator( + closure, ConstraintLocator::ClosureResult))); + if (resolvedTy) + return resolvedTy; } - return resolveTypeReferenceInExpression( - closure->getExplicitResultTypeRepr(), - TypeResolverContext::InExpression, nullptr); - }; - - Type resultTy; - auto *resultLoc = - CS.getConstraintLocator(closure, ConstraintLocator::ClosureResult); - if (auto explicityTy = getExplicitResultType()) { - resultTy = explicityTy; - } else { - auto getContextualResultType = [&]() -> Type { - if (auto contextualType = CS.getContextualType(closure)) { - if (auto fnType = contextualType->getAs()) - return fnType->getResult(); - } - return Type(); - }; - - if (auto contextualResultTy = getContextualResultType()) { - resultTy = contextualResultTy; - } else { - // If no return type was specified, create a fresh type - // variable for it and mark it as possible hole. - // - // If this is a multi-statement closure, let's mark result - // as potential hole right away. - resultTy = CS.createTypeVariable( - resultLoc, - shouldTypeCheckInEnclosingExpression(closure) - ? 0 : TVO_CanBindToHole); + if (auto contextualType = CS.getContextualType(closure)) { + if (auto fnType = contextualType->getAs()) + return fnType->getResult(); } - } + + // If no return type was specified, create a fresh type + // variable for it and mark it as possible hole. + // + // If this is a multi-statement closure, let's mark result + // as potential hole right away. + return Type(CS.createTypeVariable( + CS.getConstraintLocator(closure, ConstraintLocator::ClosureResult), + shouldTypeCheckInEnclosingExpression(closure) ? 0 + : TVO_CanBindToHole)); + }(); return FunctionType::get(closureParams, resultTy, extInfo); } @@ -2249,6 +2175,12 @@ namespace { Type varType; + // Determine whether optionality will be required. + auto ROK = ReferenceOwnership::Strong; + if (auto *OA = var->getAttrs().getAttribute()) + ROK = OA->get(); + auto optionality = optionalityOf(ROK); + // If we have a type from an initializer expression, and that // expression does not produce an InOut type, use it. This // will avoid exponential typecheck behavior in the case of @@ -2257,18 +2189,17 @@ namespace { // FIXME: This should be handled in the solver, not here. // // Otherwise, create a new type variable. - bool assumedInitializerType = false; if (!var->hasNonPatternBindingInit() && - !var->hasAttachedPropertyWrapper()) { + !var->hasAttachedPropertyWrapper() && + optionality != ReferenceOwnershipOptionality::Required) { if (auto boundExpr = locator.trySimplifyToExpr()) { if (!boundExpr->isSemanticallyInOutExpr()) { varType = CS.getType(boundExpr)->getRValueType(); - assumedInitializerType = true; } } } - if (!assumedInitializerType) + if (!varType) varType = CS.createTypeVariable(CS.getConstraintLocator(locator), TVO_CanBindToNoEscape); @@ -2286,22 +2217,8 @@ namespace { // If there is an externally-imposed type. - auto ROK = ReferenceOwnership::Strong; - if (auto *OA = var->getAttrs().getAttribute()) - ROK = OA->get(); - switch (optionalityOf(ROK)) { + switch (optionality) { case ReferenceOwnershipOptionality::Required: - if (assumedInitializerType) { - // Already Optional - if (varType->getOptionalObjectType()) - break; - - // Create a fresh type variable to handle overloaded expressions. - if (varType->is()) - varType = CS.createTypeVariable(CS.getConstraintLocator(locator), - TVO_CanBindToNoEscape); - } - varType = TypeChecker::getOptionalType(var->getLoc(), varType); assert(!varType->hasError()); @@ -2596,9 +2513,12 @@ namespace { return CS.getType(expr->getClosureBody()); } - /// Walk a closure AST to determine if it can throw. - bool closureCanThrow(ClosureExpr *expr) { - // A walker that looks for 'try' or 'throw' expressions + /// Walk a closure AST to determine its effects. + /// + /// \returns a function's extended info describing the effects, as + /// determined syntactically. + FunctionType::ExtInfo closureEffects(ClosureExpr *expr) { + // A walker that looks for 'try' and 'throw' expressions // that aren't nested within closures, nested declarations, // or exhaustive catches. class FindInnerThrows : public ASTWalker { @@ -2743,18 +2663,62 @@ namespace { bool foundThrow() { return FoundThrow; } }; - - if (expr->getThrowsLoc().isValid()) - return true; - + + // A walker that looks for 'async' and 'await' expressions + // that aren't nested within closures or nested declarations. + class FindInnerAsync : public ASTWalker { + bool FoundAsync = false; + + std::pair walkToExprPre(Expr *expr) override { + // If we've found an 'await', record it and terminate the traversal. + if (isa(expr)) { + FoundAsync = true; + return { false, nullptr }; + } + + // Do not recurse into other closures. + if (isa(expr)) + return { false, expr }; + + return { true, expr }; + } + + bool walkToDeclPre(Decl *decl) override { + // Do not walk into function or type declarations. + if (!isa(decl)) + return false; + + return true; + } + + public: + bool foundAsync() { return FoundAsync; } + }; + + // If either 'throws' or 'async' was explicitly specified, use that + // set of effects. + bool throws = expr->getThrowsLoc().isValid(); + bool async = expr->getAsyncLoc().isValid(); + if (throws || async) { + return ASTExtInfoBuilder() + .withThrows(throws) + .withAsync(async) + .build(); + } + + // Scan the body to determine the effects. auto body = expr->getBody(); - if (!body) - return false; - - auto tryFinder = FindInnerThrows(CS, expr); - body->walk(tryFinder); - return tryFinder.foundThrow(); + return FunctionType::ExtInfo(); + + auto throwFinder = FindInnerThrows(CS, expr); + body->walk(throwFinder); + auto asyncFinder = FindInnerAsync(); + body->walk(asyncFinder); + return ASTExtInfoBuilder() + .withThrows(throwFinder.foundThrow()) + .withAsync(asyncFinder.foundAsync()) + .build(); } Type visitClosureExpr(ClosureExpr *closure) { @@ -2797,10 +2761,17 @@ namespace { return { true, expr }; } } collectVarRefs(CS); + closure->walk(collectVarRefs); - if (collectVarRefs.hasErrorExprs) + // If walker discovered error expressions, let's fail constraint + // genreation only if closure is going to participate + // in the type-check. This allows us to delay validation of + // multi-statement closures until body is opened. + if (shouldTypeCheckInEnclosingExpression(closure) && + collectVarRefs.hasErrorExprs) { return Type(); + } auto inferredType = inferClosureType(closure); if (!inferredType || inferredType->hasError()) @@ -3699,6 +3670,7 @@ namespace { if (CG.getConstraintSystem().shouldReusePrecheckedType()) { if (expr->getType()) { assert(!expr->getType()->hasTypeVariable()); + assert(!expr->getType()->hasHole()); CG.getConstraintSystem().cacheType(expr); return { false, expr }; } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 6468c1e5a0cc1..1ea9cf08b296a 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -4306,22 +4306,18 @@ bool ConstraintSystem::repairFailures( break; } - // Unresolved member type mismatches are handled when - // r-value adjustment constraint fails. - case ConstraintLocator::UnresolvedMember: + case ConstraintLocator::RValueAdjustment: return true; - case ConstraintLocator::RValueAdjustment: { - if (!isExpr(anchor)) - break; - + case ConstraintLocator::UnresolvedMemberChainResult: { if (repairViaOptionalUnwrap(*this, lhs, rhs, matchKind, conversionsOrFixes, locator)) break; - // r-value adjustment is used to connect base type of - // unresolved member to its output type, if there is - // a type mismatch here it's contextual e.g. + if (repairByTreatingRValueAsLValue(lhs, rhs)) + break; + + // If there is a type mismatch here it's contextual e.g., // `let x: E = .foo(42)`, where `.foo` is a member of `E` // but produces an incorrect type. auto *fix = IgnoreContextualType::create(*this, lhs, rhs, @@ -4434,6 +4430,12 @@ bool ConstraintSystem::repairFailures( } case ConstraintLocator::FunctionBuilderBodyResult: { + // If result type of the body couldn't be determined + // there is going to be other fix available to diagnose + // the underlying issue. + if (lhs->isHole()) + return true; + conversionsOrFixes.push_back(ContextualMismatch::create( *this, lhs, rhs, getConstraintLocator(locator))); break; @@ -4529,7 +4531,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, return formUnsolvedResult(); // Merge the equivalence classes corresponding to these two variables. - mergeEquivalenceClasses(rep1, rep2); + mergeEquivalenceClasses(rep1, rep2, /*updateWorkList=*/true); return getTypeMatchSuccess(); } @@ -4581,7 +4583,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, if (!rep1->getImpl().canBindToInOut() || !rep2->getImpl().canBindToLValue()) { // Merge the equivalence classes corresponding to these two variables. - mergeEquivalenceClasses(rep1, rep2); + mergeEquivalenceClasses(rep1, rep2, /*updateWorkList=*/true); return getTypeMatchSuccess(); } } @@ -4687,6 +4689,17 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, case TypeKind::Unresolved: return getTypeMatchFailure(locator); + case TypeKind::Hole: { + // If it's allowed to attempt fixes, let's delegate + // decision to `repairFailures`, since depending on + // locator we might either ignore such a mismatch, + // or record a specialized fix. + if (shouldAttemptFixes()) + break; + + return getTypeMatchFailure(locator); + } + case TypeKind::GenericTypeParam: llvm_unreachable("unmapped dependent type in type checker"); @@ -5366,6 +5379,7 @@ ConstraintSystem::simplifyConstructionConstraint( case TypeKind::Unresolved: case TypeKind::Error: + case TypeKind::Hole: return SolutionKind::Error; case TypeKind::GenericFunction: @@ -6759,28 +6773,39 @@ static ConstraintFix *validateInitializerRef(ConstraintSystem &cs, } else if (auto *CE = getAsExpr(anchor)) { baseExpr = CE->getFn(); baseType = getType(baseExpr); - // If this is an initializer call without explicit mention - // of `.init` on metatype value. - if (auto *AMT = baseType->getAs()) { - auto instanceType = AMT->getInstanceType()->getWithoutParens(); - if (!cs.isTypeReference(baseExpr)) { - if (baseType->is() && - instanceType->isAnyExistentialType()) { - return AllowInvalidInitRef::onProtocolMetatype( - cs, baseType, init, cs.isStaticallyDerivedMetatype(baseExpr), - baseExpr->getSourceRange(), locator); - } + // FIXME: Historically, UnresolvedMemberExprs have allowed implicit + // construction through a metatype value, but this should probably be + // illegal. + if (!isa(baseExpr)) { + // If this is an initializer call without explicit mention + // of `.init` on metatype value. + if (auto *AMT = baseType->getAs()) { + auto instanceType = AMT->getInstanceType()->getWithoutParens(); + if (!cs.isTypeReference(baseExpr)) { + if (baseType->is() && + instanceType->isAnyExistentialType()) { + return AllowInvalidInitRef::onProtocolMetatype( + cs, baseType, init, cs.isStaticallyDerivedMetatype(baseExpr), + baseExpr->getSourceRange(), locator); + } - if (!instanceType->isExistentialType() || - instanceType->isAnyExistentialType()) { - return AllowInvalidInitRef::onNonConstMetatype(cs, baseType, init, - locator); + if (!instanceType->isExistentialType() || + instanceType->isAnyExistentialType()) { + return AllowInvalidInitRef::onNonConstMetatype(cs, baseType, init, + locator); + } } } } // Initializer reference which requires contextual base type e.g. - // `.init(...)`. + // `.init(...)`. Could also be a nested type or typealias being constructed + // via implicit member syntax, e.g., `let _: Base = .Nested()` where + // `Base.Nested: Base`. } else if (auto *UME = getAsExpr(anchor)) { + // If we're accessing a nested type to perform the construction implicitly, + // then the type we're constructing may not actually be the base of the + // UnresolvedMemberExpr--instead, it will be the type of the nested type + // member. // We need to find type variable which represents contextual base. auto *baseLocator = cs.getConstraintLocator( UME, locatorEndsWith(locator, ConstraintLocator::ConstructorMember) @@ -8127,6 +8152,14 @@ ConstraintSystem::simplifyKeyPathConstraint( if (keyPathTy->isHole()) return SolutionKind::Solved; + // If we have a malformed KeyPathExpr e.g. let _: KeyPath = \A + // let's record a AllowKeyPathMissingComponent fix. + if (keyPath->hasSingleInvalidComponent()) { + auto *fix = AllowKeyPathWithoutComponents::create( + *this, getConstraintLocator(locator)); + return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved; + } + // If the root type has been bound to a hole, we cannot infer it. if (getFixedTypeRecursive(rootTy, /*wantRValue*/ true)->isHole()) return SolutionKind::Solved; @@ -9988,7 +10021,9 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( case FixKind::UnwrapOptionalBaseKeyPathApplication: case FixKind::AllowCoercionToForceCast: case FixKind::SpecifyKeyPathRootType: - case FixKind::SpecifyLabelToAssociateTrailingClosure: { + case FixKind::SpecifyLabelToAssociateTrailingClosure: + case FixKind::AllowKeyPathWithoutComponents: + case FixKind::IgnoreInvalidFunctionBuilderBody: { return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved; } @@ -10647,7 +10682,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) { case ConstraintKind::OptionalObject: return simplifyOptionalObjectConstraint(constraint.getFirstType(), constraint.getSecondType(), - TMF_GenerateConstraints, + /*flags*/ None, constraint.getLocator()); case ConstraintKind::ValueMember: @@ -10659,8 +10694,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) { constraint.getMemberUseDC(), constraint.getFunctionRefKind(), /*outerAlternatives=*/{}, - TMF_GenerateConstraints, - constraint.getLocator()); + /*flags*/ None, constraint.getLocator()); case ConstraintKind::ValueWitness: return simplifyValueWitnessConstraint(constraint.getKind(), @@ -10669,20 +10703,20 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) { constraint.getSecondType(), constraint.getMemberUseDC(), constraint.getFunctionRefKind(), - TMF_GenerateConstraints, + /*flags*/ None, constraint.getLocator()); case ConstraintKind::Defaultable: return simplifyDefaultableConstraint(constraint.getFirstType(), constraint.getSecondType(), - TMF_GenerateConstraints, + /*flags*/ None, constraint.getLocator()); case ConstraintKind::DefaultClosureType: return simplifyDefaultClosureTypeConstraint(constraint.getFirstType(), constraint.getSecondType(), constraint.getTypeVariables(), - TMF_GenerateConstraints, + /*flags*/ None, constraint.getLocator()); case ConstraintKind::FunctionInput: @@ -10690,7 +10724,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) { return simplifyFunctionComponentConstraint(constraint.getKind(), constraint.getFirstType(), constraint.getSecondType(), - TMF_GenerateConstraints, + /*flags*/ None, constraint.getLocator()); case ConstraintKind::Disjunction: @@ -10702,8 +10736,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) { return simplifyOneWayConstraint(constraint.getKind(), constraint.getFirstType(), constraint.getSecondType(), - TMF_GenerateConstraints, - constraint.getLocator()); + /*flags*/ None, constraint.getLocator()); } llvm_unreachable("Unhandled ConstraintKind in switch."); diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index 7af6590a65c0d..8f0afc7b18b81 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -1411,7 +1411,8 @@ void ConstraintSystem::solveForCodeCompletion( llvm::function_ref callback) { // First, pre-check the expression, validating any types that occur in the // expression and folding sequence expressions. - if (ConstraintSystem::preCheckExpression(expr, DC)) + if (ConstraintSystem::preCheckExpression( + expr, DC, /*replaceInvalidRefsWithErrors=*/true)) return; ConstraintSystemOptions options; @@ -1428,7 +1429,7 @@ void ConstraintSystem::solveForCodeCompletion( cs.shrink(expr); - if (cs.generateConstraints(expr, DC)) + if (!cs.generateConstraints(expr, DC)) return; llvm::SmallVector solutions; diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 4ff16a78a5ede..5ed7bdafa5de6 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -911,8 +911,8 @@ static bool canInheritDesignatedInits(Evaluator &eval, ClassDecl *decl) { static void collectNonOveriddenSuperclassInits( ClassDecl *subclass, SmallVectorImpl &results) { - auto superclassTy = subclass->getSuperclass(); - assert(superclassTy); + auto *superclassDecl = subclass->getSuperclassDecl(); + assert(superclassDecl); // Record all of the initializers the subclass has overriden, excluding stub // overrides, which we don't want to consider as viable delegates for @@ -924,11 +924,17 @@ static void collectNonOveriddenSuperclassInits( if (auto overridden = ctor->getOverriddenDecl()) overriddenInits.insert(overridden); - auto superclassCtors = TypeChecker::lookupConstructors( - subclass, superclassTy, NameLookupFlags::IgnoreAccessControl); + superclassDecl->synthesizeSemanticMembersIfNeeded( + DeclBaseName::createConstructor()); - for (auto memberResult : superclassCtors) { - auto superclassCtor = cast(memberResult.getValueDecl()); + NLOptions subOptions = (NL_QualifiedDefault | NL_IgnoreAccessControl); + SmallVector lookupResults; + subclass->lookupQualified( + superclassDecl, DeclNameRef::createConstructor(), + subOptions, lookupResults); + + for (auto decl : lookupResults) { + auto superclassCtor = cast(decl); // Skip invalid superclass initializers. if (superclassCtor->isInvalid()) @@ -958,12 +964,7 @@ static void addImplicitInheritedConstructorsToClass(ClassDecl *decl) { decl->setAddedImplicitInitializers(); // We can only inherit initializers if we have a superclass. - // FIXME: We should be bailing out earlier in the function, but unfortunately - // that currently regresses associated type inference for cases like - // compiler_crashers_2_fixed/0124-sr5825.swift due to the fact that we no - // longer eagerly compute the interface types of the other constructors. - auto superclassTy = decl->getSuperclass(); - if (!superclassTy) + if (!decl->getSuperclassDecl() || !decl->getSuperclass()) return; // Check whether the user has defined a designated initializer for this class, diff --git a/lib/Sema/ConstraintLocator.cpp b/lib/Sema/ConstraintLocator.cpp index d570c8983b13e..708d90d7dc6de 100644 --- a/lib/Sema/ConstraintLocator.cpp +++ b/lib/Sema/ConstraintLocator.cpp @@ -32,54 +32,7 @@ void ConstraintLocator::Profile(llvm::FoldingSetNodeID &id, ASTNode anchor, id.AddInteger(path.size()); for (auto elt : path) { id.AddInteger(elt.getKind()); - switch (elt.getKind()) { - case GenericParameter: - id.AddPointer(elt.castTo().getType()); - break; - - case ProtocolRequirement: { - auto reqElt = elt.castTo(); - id.AddPointer(reqElt.getDecl()); - break; - } - - case Witness: - id.AddPointer(elt.castTo().getDecl()); - break; - - case KeyPathDynamicMember: { - auto kpElt = elt.castTo(); - id.AddPointer(kpElt.getKeyPathDecl()); - break; - } - - case PatternMatch: - id.AddPointer(elt.castTo().getPattern()); - break; - - case ArgumentAttribute: - case GenericArgument: - case NamedTupleElement: - case TupleElement: - case ApplyArgToParam: - case OpenedGeneric: - case KeyPathComponent: - case ConditionalRequirement: - case TypeParameterRequirement: - case ContextualType: - case SynthesizedArgument: - case TernaryBranch: - case ClosureBody: { - auto numValues = numNumericValuesInPathElement(elt.getKind()); - for (unsigned i = 0; i < numValues; ++i) - id.AddInteger(elt.getValue(i)); - break; - } -#define SIMPLE_LOCATOR_PATH_ELT(Name) case Name : -#include "ConstraintLocatorPathElts.def" - // Nothing to do for simple locator elements. - break; - } + id.AddInteger(elt.getRawStorage()); } } @@ -128,6 +81,7 @@ unsigned LocatorPathElt::getNewSummaryFlags() const { case ConstraintLocator::TernaryBranch: case ConstraintLocator::PatternMatch: case ConstraintLocator::ArgumentAttribute: + case ConstraintLocator::UnresolvedMemberChainResult: return 0; case ConstraintLocator::FunctionArgument: @@ -530,6 +484,10 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) const { break; } + + case UnresolvedMemberChainResult: + out << "unresolved chain result"; + break; } } out << ']'; diff --git a/lib/Sema/ConstraintLocator.h b/lib/Sema/ConstraintLocator.h index 0c3c3e1a432ce..fd5b07a155675 100644 --- a/lib/Sema/ConstraintLocator.h +++ b/lib/Sema/ConstraintLocator.h @@ -64,42 +64,6 @@ class ConstraintLocator : public llvm::FoldingSetNode { #include "ConstraintLocatorPathElts.def" }; - /// Determine the number of numeric values used for the given path - /// element kind. - static unsigned numNumericValuesInPathElement(PathElementKind kind) { - switch (kind) { -#define SIMPLE_LOCATOR_PATH_ELT(Name) case Name : -#include "ConstraintLocatorPathElts.def" - case GenericParameter: - case ProtocolRequirement: - case Witness: - case PatternMatch: - return 0; - - case ClosureBody: - case ContextualType: - case OpenedGeneric: - case GenericArgument: - case NamedTupleElement: - case TupleElement: - case KeyPathComponent: - case SynthesizedArgument: - case KeyPathDynamicMember: - case TernaryBranch: - case ArgumentAttribute: - return 1; - - case TypeParameterRequirement: - case ConditionalRequirement: - return 2; - - case ApplyArgToParam: - return 3; - } - - llvm_unreachable("Unhandled PathElementKind in switch."); - } - /// Flags for efficiently recording certain information about a path. /// All of this information should be re-derivable from the path. /// @@ -120,143 +84,24 @@ class ConstraintLocator : public llvm::FoldingSetNode { /// a kind (PathElementKind) and a value used to describe specific /// kinds further (e.g., the position of a tuple element). class PathElement { - /// Describes the kind of data stored here. - enum StoredKind : unsigned char { - StoredGenericParameter, - StoredProtocolRequirement, - StoredWitness, - StoredGenericSignature, - StoredKeyPathDynamicMemberBase, - StoredPattern, - StoredKindAndValue - }; - - /// The actual storage for the path element, which involves both a - /// kind and (potentially) a value. - /// - /// The current storage involves a two-bit "storage kind", which selects - /// among the possible value stores. The value stores can either be an - /// archetype (for archetype path elements) or an unsigned value that - /// stores both the specific kind and the (optional) numeric value of that - /// kind. Use \c encodeStorage and \c decodeStorage to work with this value. - /// - /// \note The "storage kind" is stored in the \c storedKind field. - uint64_t storage : 61; - - /// The kind of value stored in \c storage. Valid values are those - /// from the StoredKind enum. - uint64_t storedKind : 3; - - /// Encode a path element kind and a value into the storage format. - static uint64_t encodeStorage(PathElementKind kind, uint64_t value) { - return (value << 8) | kind; - } - - /// Decode a storage value into path element kind and value. - static std::pair - decodeStorage(uint64_t storage) { - return { (PathElementKind)((unsigned)storage & 0xFF), storage >> 8 }; - } - - /// Retrieve a value associated with the path element. - unsigned getValue(unsigned index) const { - unsigned numValues = numNumericValuesInPathElement(getKind()); - assert(index < numValues && "Index out of range for path element value"); - - // We pack values into 16 bit components of the storage, with value0 - // being stored in the upper bits, valueN in the lower bits. Therefore we - // need to shift out any extra values in the lower bits. - auto extraValues = numValues - index - 1; - auto value = decodeStorage(storage).second >> (extraValues * 16); - return value & 0xFFFF; - } + PathElementKind kind; - PathElement(PathElementKind kind, unsigned value) - : storage(encodeStorage(kind, value)), storedKind(StoredKindAndValue) - { - assert(numNumericValuesInPathElement(kind) == 1 && - "Path element kind does not require 1 value"); - assert(value == getValue(0) && "value truncated"); - } - - PathElement(PathElementKind kind, unsigned value0, unsigned value1) - : storage(encodeStorage(kind, value0 << 16 | value1)), - storedKind(StoredKindAndValue) - { - assert(numNumericValuesInPathElement(kind) == 2 && - "Path element kind does not require 2 values"); - assert(value0 == getValue(0) && "value0 truncated"); - assert(value1 == getValue(1) && "value1 truncated"); - } - - PathElement(PathElementKind kind, uint64_t value0, uint64_t value1, - uint64_t value2) - : storage(encodeStorage(kind, value0 << 32 | value1 << 16 | value2)), - storedKind(StoredKindAndValue) { - assert(numNumericValuesInPathElement(kind) == 3 && - "Path element kind does not require 3 values"); - assert(value0 == getValue(0) && "value0 truncated"); - assert(value1 == getValue(1) && "value1 truncated"); - assert(value2 == getValue(2) && "value2 truncated"); - } - - /// Store a path element with an associated pointer, accessible using - /// \c getStoredPointer. - template - PathElement(StoredKind storedKind, T *ptr) - : storage((reinterpret_cast(ptr) >> 3)), - storedKind(storedKind) { - assert(ptr == getStoredPointer()); - } - - /// Retrieve an associated pointer for the element. The type \c T must match - /// the type used when creating the path element. - template - T *getStoredPointer() const { - assert(storedKind != StoredKindAndValue); - return reinterpret_cast(storage << 3); - } - - friend class ConstraintLocator; + /// The storage for the path element value. The value stores can either + /// be a pointer or an unsigned int. Only custom path elements store values. + uint64_t storage; public: #define LOCATOR_PATH_ELT(Name) class Name; #include "ConstraintLocatorPathElts.def" - PathElement(PathElementKind kind) - : storage(encodeStorage(kind, 0)), storedKind(StoredKindAndValue) - { - assert(numNumericValuesInPathElement(kind) == 0 && - "Path element requires value"); - } + PathElement(PathElementKind kind, uint64_t storage = 0) + : kind(kind), storage(storage) {} /// Retrieve the kind of path element. - PathElementKind getKind() const { - switch (static_cast(storedKind)) { - case StoredGenericParameter: - return PathElementKind::GenericParameter; - - case StoredProtocolRequirement: - return PathElementKind::ProtocolRequirement; - - case StoredWitness: - return PathElementKind::Witness; - - case StoredGenericSignature: - return PathElementKind::OpenedGeneric; - - case StoredKeyPathDynamicMemberBase: - return PathElementKind::KeyPathDynamicMember; + PathElementKind getKind() const { return kind; } - case StoredPattern: - return PathElementKind::PatternMatch; - - case StoredKindAndValue: - return decodeStorage(storage).first; - } - - llvm_unreachable("Unhandled StoredKind in switch."); - } + /// Retrieve the raw storage value. + uint64_t getRawStorage() const { return storage; } /// Attempts to cast the path element to a specific \c LocatorPathElt /// subclass, returning \c None if unsuccessful. @@ -592,20 +437,76 @@ public: \ }; #include "ConstraintLocatorPathElts.def" +/// A base class for custom path elements that store numeric values. +template +class StoredIntegerElement: public LocatorPathElt { +public: + template ::type> + StoredIntegerElement(ConstraintLocator::PathElementKind kind, unsigned value) + : LocatorPathElt(kind, value) { + assert(value == getValue<0>() && "value truncated"); + } + + template ::type> + StoredIntegerElement(ConstraintLocator::PathElementKind kind, unsigned value0, unsigned value1) + : LocatorPathElt(kind, (value0 << 16 | value1)) { + assert(value0 == getValue<0>() && "value0 truncated"); + assert(value1 == getValue<1>() && "value1 truncated"); + } + + template ::type> + StoredIntegerElement(ConstraintLocator::PathElementKind kind, unsigned value0, + unsigned value1, unsigned value2) + : LocatorPathElt(kind, uint64_t(value0) << 32 | uint64_t(value1) << 16 | uint64_t(value2)) { + assert(value0 == getValue<0>() && "value0 truncated"); + assert(value1 == getValue<1>() && "value1 truncated"); + assert(value2 == getValue<2>() && "value2 truncated"); + } + + /// Retrieve a value associated with the path element. + template ::type> + unsigned getValue() const { + // We pack values into 16 bit components of the storage, with value0 + // being stored in the upper bits, valueN in the lower bits. Therefore we + // need to shift out any extra values in the lower bits. + auto extraValues = NumValues - Index - 1; + auto value = getRawStorage() >> (extraValues * 16); + return value & 0xFFFF; + } +}; + +/// A base class for custom path elements that store a pointer. +template +class StoredPointerElement: public LocatorPathElt { +public: + StoredPointerElement(ConstraintLocator::PathElementKind kind, const T *ptr) + : LocatorPathElt(kind, reinterpret_cast(ptr)) { + assert(ptr == getStoredPointer()); + } + + /// Retrieve the associated pointer for the element. + T *getStoredPointer() const { return reinterpret_cast(getRawStorage()); } +}; + // The following LocatorPathElt subclasses are used to expose accessors for // specific path element information. They shouldn't introduce additional -// storage, as LocatorPathElt gets passed about by value. +// storage, as LocatorPathElt gets passed about by value. Custom path elements +// should subclass StoredIntegerElement to store unsigned values, or StoredPointerElement +// to store pointer values. -class LocatorPathElt::ApplyArgToParam final : public LocatorPathElt { +class LocatorPathElt::ApplyArgToParam final : public StoredIntegerElement<3> { public: ApplyArgToParam(unsigned argIdx, unsigned paramIdx, ParameterTypeFlags flags) - : LocatorPathElt(ConstraintLocator::ApplyArgToParam, argIdx, paramIdx, - flags.toRaw()) {} + : StoredIntegerElement(ConstraintLocator::ApplyArgToParam, argIdx, paramIdx, flags.toRaw()) {} - unsigned getArgIdx() const { return getValue(0); } - unsigned getParamIdx() const { return getValue(1); } + unsigned getArgIdx() const { return getValue<0>(); } + unsigned getParamIdx() const { return getValue<1>(); } ParameterTypeFlags getParameterFlags() const { - return ParameterTypeFlags::fromRaw(getValue(2)); + return ParameterTypeFlags::fromRaw(getValue<2>()); } static bool classof(const LocatorPathElt *elt) { @@ -613,12 +514,12 @@ class LocatorPathElt::ApplyArgToParam final : public LocatorPathElt { } }; -class LocatorPathElt::SynthesizedArgument final : public LocatorPathElt { +class LocatorPathElt::SynthesizedArgument final : public StoredIntegerElement<1> { public: SynthesizedArgument(unsigned index) - : LocatorPathElt(ConstraintLocator::SynthesizedArgument, index) {} + : StoredIntegerElement(ConstraintLocator::SynthesizedArgument, index) {} - unsigned getIndex() const { return getValue(0); } + unsigned getIndex() const { return getValue(); } static bool classof(const LocatorPathElt *elt) { return elt->getKind() == ConstraintLocator::SynthesizedArgument; @@ -626,15 +527,15 @@ class LocatorPathElt::SynthesizedArgument final : public LocatorPathElt { }; /// Abstract superclass for any kind of tuple element. -class LocatorPathElt::AnyTupleElement : public LocatorPathElt { +class LocatorPathElt::AnyTupleElement : public StoredIntegerElement<1> { protected: AnyTupleElement(PathElementKind kind, unsigned index) - : LocatorPathElt(kind, index) { + : StoredIntegerElement(kind, index) { assert(classof(this) && "classof needs updating"); } public: - unsigned getIndex() const { return getValue(0); } + unsigned getIndex() const { return getValue(); } static bool classof(const LocatorPathElt *elt) { return elt->is() || @@ -664,24 +565,24 @@ class LocatorPathElt::NamedTupleElement final } }; -class LocatorPathElt::KeyPathComponent final : public LocatorPathElt { +class LocatorPathElt::KeyPathComponent final : public StoredIntegerElement<1> { public: KeyPathComponent(unsigned index) - : LocatorPathElt(ConstraintLocator::KeyPathComponent, index) {} + : StoredIntegerElement(ConstraintLocator::KeyPathComponent, index) {} - unsigned getIndex() const { return getValue(0); } + unsigned getIndex() const { return getValue(); } static bool classof(const LocatorPathElt *elt) { return elt->getKind() == ConstraintLocator::KeyPathComponent; } }; -class LocatorPathElt::GenericArgument final : public LocatorPathElt { +class LocatorPathElt::GenericArgument final : public StoredIntegerElement<1> { public: GenericArgument(unsigned index) - : LocatorPathElt(ConstraintLocator::GenericArgument, index) {} + : StoredIntegerElement(ConstraintLocator::GenericArgument, index) {} - unsigned getIndex() const { return getValue(0); } + unsigned getIndex() const { return getValue(); } static bool classof(const LocatorPathElt *elt) { return elt->getKind() == ConstraintLocator::GenericArgument; @@ -690,17 +591,17 @@ class LocatorPathElt::GenericArgument final : public LocatorPathElt { /// Abstract superclass for any kind of element that describes a requirement /// placed on a type within a requirements clause. -class LocatorPathElt::AnyRequirement : public LocatorPathElt { +class LocatorPathElt::AnyRequirement : public StoredIntegerElement<2> { protected: AnyRequirement(PathElementKind kind, unsigned index, RequirementKind reqKind) - : LocatorPathElt(kind, index, static_cast(reqKind)) { + : StoredIntegerElement(kind, index, static_cast(reqKind)) { assert(classof(this) && "classof needs updating"); } public: - unsigned getIndex() const { return getValue(0); } + unsigned getIndex() const { return getValue<0>(); } RequirementKind getRequirementKind() const { - return static_cast(getValue(1)); + return static_cast(getValue<1>()); } static bool classof(const LocatorPathElt *elt) { @@ -733,84 +634,81 @@ class LocatorPathElt::TypeParameterRequirement final } }; -class LocatorPathElt::ClosureBody final : public LocatorPathElt { +class LocatorPathElt::ClosureBody final : public StoredIntegerElement<1> { public: ClosureBody(bool hasExplicitReturn = false) - : LocatorPathElt(ConstraintLocator::ClosureBody, - hasExplicitReturn) {} + : StoredIntegerElement(ConstraintLocator::ClosureBody, hasExplicitReturn) {} /// Indicates whether body of the closure has any `return` statements. - bool hasExplicitReturn() const { return bool(getValue(0)); } + bool hasExplicitReturn() const { return bool(getValue()); } static bool classof(const LocatorPathElt *elt) { return elt->getKind() == ConstraintLocator::ClosureBody; } }; -class LocatorPathElt::ContextualType final : public LocatorPathElt { +class LocatorPathElt::ContextualType final : public StoredIntegerElement<1> { public: ContextualType(bool isForSingleExprFunction = false) - : LocatorPathElt(ConstraintLocator::ContextualType, - isForSingleExprFunction) {} + : StoredIntegerElement(ConstraintLocator::ContextualType, isForSingleExprFunction) {} /// Whether this element points to the contextual type associated with the /// result of a single expression function. - bool isForSingleExprFunction() const { return bool(getValue(0)); } + bool isForSingleExprFunction() const { return bool(getValue()); } static bool classof(const LocatorPathElt *elt) { return elt->getKind() == ConstraintLocator::ContextualType; } }; -class LocatorPathElt::Witness final : public LocatorPathElt { +class LocatorPathElt::Witness final : public StoredPointerElement { public: Witness(ValueDecl *witness) - : LocatorPathElt(LocatorPathElt::StoredWitness, witness) {} + : StoredPointerElement(PathElementKind::Witness, witness) {} - ValueDecl *getDecl() const { return getStoredPointer(); } + ValueDecl *getDecl() const { return getStoredPointer(); } static bool classof(const LocatorPathElt *elt) { - return elt->getKind() == ConstraintLocator::Witness; + return elt->getKind() == PathElementKind::Witness; } }; -class LocatorPathElt::ProtocolRequirement final : public LocatorPathElt { +class LocatorPathElt::ProtocolRequirement final : public StoredPointerElement { public: ProtocolRequirement(ValueDecl *decl) - : LocatorPathElt(LocatorPathElt::StoredProtocolRequirement, decl) {} + : StoredPointerElement(PathElementKind::ProtocolRequirement, decl) {} - ValueDecl *getDecl() const { return getStoredPointer(); } + ValueDecl *getDecl() const { return getStoredPointer(); } static bool classof(const LocatorPathElt *elt) { - return elt->getKind() == ConstraintLocator::ProtocolRequirement; + return elt->getKind() == PathElementKind::ProtocolRequirement; } }; -class LocatorPathElt::GenericParameter final : public LocatorPathElt { +class LocatorPathElt::GenericParameter final : public StoredPointerElement { public: GenericParameter(GenericTypeParamType *type) - : LocatorPathElt(LocatorPathElt::StoredGenericParameter, type) { + : StoredPointerElement(PathElementKind::GenericParameter, type) { static_assert(alignof(GenericTypeParamType) >= 4, "archetypes insufficiently aligned"); } GenericTypeParamType *getType() const { - return getStoredPointer(); + return getStoredPointer(); } static bool classof(const LocatorPathElt *elt) { - return elt->getKind() == ConstraintLocator::GenericParameter; + return elt->getKind() == PathElementKind::GenericParameter; } }; -class LocatorPathElt::OpenedGeneric final : public LocatorPathElt { +class LocatorPathElt::OpenedGeneric final : public StoredPointerElement { public: OpenedGeneric(GenericSignature sig) - : LocatorPathElt(LocatorPathElt::StoredGenericSignature, - sig.getPointer()) {} + : StoredPointerElement(PathElementKind::OpenedGeneric, sig.getPointer()) {} GenericSignature getSignature() const { - return getStoredPointer(); + return getStoredPointer(); } static bool classof(const LocatorPathElt *elt) { @@ -818,14 +716,13 @@ class LocatorPathElt::OpenedGeneric final : public LocatorPathElt { } }; -class LocatorPathElt::KeyPathDynamicMember final : public LocatorPathElt { +class LocatorPathElt::KeyPathDynamicMember final : public StoredPointerElement { public: KeyPathDynamicMember(NominalTypeDecl *keyPathDecl) - : LocatorPathElt(LocatorPathElt::StoredKeyPathDynamicMemberBase, - keyPathDecl) {} + : StoredPointerElement(PathElementKind::KeyPathDynamicMember, keyPathDecl) {} NominalTypeDecl *getKeyPathDecl() const { - return getStoredPointer(); + return getStoredPointer(); } static bool classof(const LocatorPathElt *elt) { @@ -833,43 +730,42 @@ class LocatorPathElt::KeyPathDynamicMember final : public LocatorPathElt { } }; -class LocatorPathElt::TernaryBranch final : public LocatorPathElt { +class LocatorPathElt::TernaryBranch final : public StoredIntegerElement<1> { public: TernaryBranch(bool side) - : LocatorPathElt(ConstraintLocator::TernaryBranch, side) {} + : StoredIntegerElement(ConstraintLocator::TernaryBranch, side) {} - bool forThen() const { return bool(getValue(0)); } + bool forThen() const { return bool(getValue()); } - bool forElse() const { return !bool(getValue(0)); } + bool forElse() const { return !bool(getValue()); } static bool classof(const LocatorPathElt *elt) { return elt->getKind() == ConstraintLocator::TernaryBranch; } }; -class LocatorPathElt::PatternMatch final : public LocatorPathElt { +class LocatorPathElt::PatternMatch final : public StoredPointerElement { public: PatternMatch(Pattern *pattern) - : LocatorPathElt(LocatorPathElt::StoredPattern, pattern) {} + : StoredPointerElement(PathElementKind::PatternMatch, pattern) {} - Pattern *getPattern() const { return getStoredPointer(); } + Pattern *getPattern() const { return getStoredPointer(); } static bool classof(const LocatorPathElt *elt) { return elt->getKind() == ConstraintLocator::PatternMatch; } }; -class LocatorPathElt::ArgumentAttribute final : public LocatorPathElt { +class LocatorPathElt::ArgumentAttribute final : public StoredIntegerElement<1> { public: enum Attribute : uint8_t { InOut, Escaping }; private: ArgumentAttribute(Attribute attr) - : LocatorPathElt(ConstraintLocator::ArgumentAttribute, - static_cast(attr)) {} + : StoredIntegerElement(ConstraintLocator::ArgumentAttribute, static_cast(attr)) {} public: - Attribute getAttr() const { return static_cast(getValue(0)); } + Attribute getAttr() const { return static_cast(getValue()); } static ArgumentAttribute forInOut() { return ArgumentAttribute(Attribute::InOut); @@ -884,6 +780,36 @@ class LocatorPathElt::ArgumentAttribute final : public LocatorPathElt { } }; +namespace details { + template + class PathElement { + static constexpr bool hasStoredValueImpl(...) { return false; } + + template + static constexpr bool hasStoredValueImpl(StoredIntegerElement *) { return true; } + + template + static constexpr bool hasStoredValueImpl(StoredPointerElement *) { return true; } + + public: + static constexpr bool hasStoredValue() { + return hasStoredValueImpl(static_cast(nullptr)); + } + }; +} + +template +constexpr bool isValidCustomPathElement() { + return details::PathElement::hasStoredValue(); +} + +// All custom path element classes must inherit from StoredIntegerElement or StoredPointerElement +#define CUSTOM_LOCATOR_PATH_ELT(Name) \ +static_assert(isValidCustomPathElement(), \ + "Custom path elements must inherit from StoredIntegerElement or StoredPointerElement"); +#include "ConstraintLocatorPathElts.def" + + /// A simple stack-only builder object that constructs a /// constraint locator without allocating memory. /// diff --git a/lib/Sema/ConstraintLocatorPathElts.def b/lib/Sema/ConstraintLocatorPathElts.def index 67228bcbc5591..435d20b74ec9f 100644 --- a/lib/Sema/ConstraintLocatorPathElts.def +++ b/lib/Sema/ConstraintLocatorPathElts.def @@ -192,6 +192,9 @@ CUSTOM_LOCATOR_PATH_ELT(PatternMatch) /// of a problem. CUSTOM_LOCATOR_PATH_ELT(ArgumentAttribute) +/// The result of a chain of member accesses off an UnresolvedMemberExpr +SIMPLE_LOCATOR_PATH_ELT(UnresolvedMemberChainResult) + #undef LOCATOR_PATH_ELT #undef CUSTOM_LOCATOR_PATH_ELT #undef SIMPLE_LOCATOR_PATH_ELT diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 1214740c8d1d5..f27cc505b4283 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -562,21 +562,7 @@ ConstraintLocator *ConstraintSystem::getCalleeLocator( } if (auto *UME = getAsExpr(anchor)) { - auto *calleeLoc = - getConstraintLocator(UME, ConstraintLocator::UnresolvedMember); - - // Handle special cases for applies of non-function types. - // FIXME: Consider re-designing the AST such that an unresolved member expr - // with arguments uses a CallExpr, which would make this logic unnecessary - // and clean up a bunch of other special cases. Doing so may require a bit - // of hacking in CSGen though. - if (UME->hasArguments()) { - if (auto overload = getOverloadFor(calleeLoc)) { - if (auto *loc = getSpecialFnCalleeLoc(overload->boundType)) - return loc; - } - } - return calleeLoc; + return getConstraintLocator(UME, ConstraintLocator::UnresolvedMember); } if (isExpr(anchor)) @@ -2617,11 +2603,13 @@ Type ConstraintSystem::simplifyTypeImpl(Type type, // there will be a missing conformance fix applied in diagnostic mode, // so the concrete dependent member type is considered a "hole" in // order to continue solving. + auto memberTy = DependentMemberType::get(lookupBaseType, assocType); if (shouldAttemptFixes() && - getPhase() == ConstraintSystemPhase::Solving) - return getASTContext().TheUnresolvedType; + getPhase() == ConstraintSystemPhase::Solving) { + return HoleType::get(getASTContext(), memberTy); + } - return DependentMemberType::get(lookupBaseType, assocType); + return memberTy; } auto subs = SubstitutionMap::getProtocolSubstitutions( @@ -2653,16 +2641,23 @@ Type ConstraintSystem::simplifyType(Type type) const { } Type Solution::simplifyType(Type type) const { - if (!type->hasTypeVariable()) + if (!(type->hasTypeVariable() || type->hasHole())) return type; // Map type variables to fixed types from bindings. - return getConstraintSystem().simplifyTypeImpl(type, - [&](TypeVariableType *tvt) -> Type { - auto known = typeBindings.find(tvt); - assert(known != typeBindings.end()); - return known->second; - }); + auto &cs = getConstraintSystem(); + auto resolvedType = cs.simplifyTypeImpl( + type, [&](TypeVariableType *tvt) -> Type { return getFixedType(tvt); }); + + // Holes shouldn't be reachable through a solution, they are only + // useful to determine what went wrong exactly. + if (resolvedType->hasHole()) { + return resolvedType.transform([&](Type type) { + return type->isHole() ? Type(cs.getASTContext().TheUnresolvedType) : type; + }); + } + + return resolvedType; } size_t Solution::getTotalMemory() const { @@ -3153,9 +3148,7 @@ static bool diagnoseAmbiguityWithContextualType( auto type = solution.simplifyType(overload.boundType); - if (isExpr(anchor) || isExpr(anchor) || - (isExpr(anchor) && - castToExpr(anchor)->hasArguments())) { + if (isExpr(anchor) || isExpr(anchor)) { auto fnType = type->castTo(); DE.diagnose( loc, diag::cannot_convert_candidate_result_to_contextual_type, @@ -3665,11 +3658,6 @@ void constraints::simplifyLocator(ASTNode &anchor, continue; } - if (auto *UME = getAsExpr(anchor)) { - anchor = UME->getArgument(); - path = path.slice(1); - continue; - } break; } @@ -3679,6 +3667,7 @@ void constraints::simplifyLocator(ASTNode &anchor, } case ConstraintLocator::ApplyFunction: + case ConstraintLocator::FunctionResult: // Extract application function. if (auto applyExpr = getAsExpr(anchor)) { anchor = applyExpr->getFn(); @@ -3693,15 +3682,6 @@ void constraints::simplifyLocator(ASTNode &anchor, continue; } - // The unresolved member itself is the function. - if (auto unresolvedMember = getAsExpr(anchor)) { - if (unresolvedMember->getArgument()) { - anchor = unresolvedMember; - path = path.slice(1); - continue; - } - } - break; case ConstraintLocator::AutoclosureResult: @@ -3858,6 +3838,13 @@ void constraints::simplifyLocator(ASTNode &anchor, break; } + case ConstraintLocator::UnresolvedMemberChainResult: { + auto *resultExpr = castToExpr(anchor); + anchor = resultExpr->getSubExpr(); + path = path.slice(1); + continue; + } + default: // FIXME: Lots of other cases to handle. break; @@ -3890,8 +3877,6 @@ Expr *constraints::getArgumentExpr(ASTNode node, unsigned index) { Expr *argExpr = nullptr; if (auto *AE = dyn_cast(expr)) argExpr = AE->getArg(); - else if (auto *UME = dyn_cast(expr)) - argExpr = UME->getArgument(); else if (auto *SE = dyn_cast(expr)) argExpr = SE->getIndex(); else @@ -4646,7 +4631,7 @@ SolutionApplicationTarget SolutionApplicationTarget::forInitialization( // Determine the contextual type for the initialization. TypeLoc contextualType; if (!(isa(pattern) && !pattern->isImplicit()) && - patternType && !patternType->isHole()) { + patternType && !patternType->is()) { contextualType = TypeLoc::withoutLoc(patternType); // Only provide a TypeLoc if it makes sense to allow diagnostics. diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 4e4924a0bc78b..18579bfc857a8 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -1190,6 +1190,11 @@ class Solution { /// Retrieve the type of the given node, as recorded in this solution. Type getType(ASTNode node) const; + /// Retrieve the type of the given node as recorded in this solution + /// and resolve all of the type variables in contains to form a fully + /// "resolved" concrete type. + Type getResolvedType(ASTNode node) const; + /// Resolve type variables present in the raw type, using generic parameter /// types where possible. Type resolveInterfaceType(Type type) const; @@ -1210,6 +1215,16 @@ class Solution { : nullptr; } + /// This method implements functionality of `Expr::isTypeReference` + /// with data provided by a given solution. + bool isTypeReference(Expr *E) const; + + /// Call Expr::isIsStaticallyDerivedMetatype on the given + /// expression, using a custom accessor for the type on the + /// expression that reads the type from the Solution + /// expression type map. + bool isStaticallyDerivedMetatype(Expr *E) const; + SWIFT_DEBUG_DUMP; /// Dump this solution. @@ -3147,7 +3162,7 @@ class ConstraintSystem { if (originalRep) { if (originalRep != currentRep) - mergeEquivalenceClasses(currentRep, originalRep); + mergeEquivalenceClasses(currentRep, originalRep, /*updateWorkList=*/false); continue; } @@ -3443,7 +3458,7 @@ class ConstraintSystem { /// distinct. void mergeEquivalenceClasses(TypeVariableType *typeVar1, TypeVariableType *typeVar2, - bool updateWorkList = true); + bool updateWorkList); /// Flags that direct type matching. enum TypeMatchFlags { @@ -4549,9 +4564,10 @@ class ConstraintSystem { return {type, kind, BindingSource}; } - static PotentialBinding forHole(ASTContext &ctx, + static PotentialBinding forHole(TypeVariableType *typeVar, ConstraintLocator *locator) { - return {ctx.TheUnresolvedType, AllowedBindingKind::Exact, + return {HoleType::get(typeVar->getASTContext(), typeVar), + AllowedBindingKind::Exact, /*source=*/locator}; } }; @@ -4705,6 +4721,7 @@ class ConstraintSystem { /// if it has only concrete types or would resolve a closure. bool favoredOverDisjunction(Constraint *disjunction) const; +private: /// Detect `subtype` relationship between two type variables and /// attempt to infer supertype bindings transitively e.g. /// @@ -4717,19 +4734,25 @@ class ConstraintSystem { /// \param inferredBindings The set of all bindings inferred for type /// variables in the workset. void inferTransitiveBindings( - ConstraintSystem &cs, llvm::SmallPtrSetImpl &existingTypes, + const ConstraintSystem &cs, + llvm::SmallPtrSetImpl &existingTypes, const llvm::SmallDenseMap &inferredBindings); /// Infer bindings based on any protocol conformances that have default /// types. - void inferDefaultTypes(ConstraintSystem &cs, + void inferDefaultTypes(const ConstraintSystem &cs, llvm::SmallPtrSetImpl &existingTypes); +public: + bool infer(const ConstraintSystem &cs, + llvm::SmallPtrSetImpl &exactTypes, + Constraint *constraint); + /// Finalize binding computation for this type variable by /// inferring bindings from context e.g. transitive bindings. - void finalize(ConstraintSystem &cs, + void finalize(const ConstraintSystem &cs, const llvm::SmallDenseMap &inferredBindings); @@ -4797,14 +4820,13 @@ class ConstraintSystem { /// Infer bindings for the given type variable based on current /// state of the constraint system. - PotentialBindings inferBindingsFor(TypeVariableType *typeVar); + PotentialBindings inferBindingsFor(TypeVariableType *typeVar, + bool finalize = true) const; private: Optional - getPotentialBindingForRelationalConstraint( - PotentialBindings &result, Constraint *constraint, - bool &hasDependentMemberRelationalConstraints, - bool &hasNonDependentMemberRelationalConstraints) const; + getPotentialBindingForRelationalConstraint(PotentialBindings &result, + Constraint *constraint) const; PotentialBindings getPotentialBindings(TypeVariableType *typeVar) const; /// Add a constraint to the constraint system. @@ -4934,8 +4956,12 @@ class ConstraintSystem { public: /// Pre-check the expression, validating any types that occur in the /// expression and folding sequence expressions. - static bool preCheckExpression(Expr *&expr, DeclContext *dc); - + /// + /// \param replaceInvalidRefsWithErrors Indicates whether it's allowed + /// to replace any discovered invalid member references with `ErrorExpr`. + static bool preCheckExpression(Expr *&expr, DeclContext *dc, + bool replaceInvalidRefsWithErrors); + /// Solve the system of constraints generated from provided target. /// /// \param target The target that we'll generate constraints from, which diff --git a/lib/Sema/DebuggerTestingTransform.cpp b/lib/Sema/DebuggerTestingTransform.cpp index 082c9b6190b52..61484a57a0d77 100644 --- a/lib/Sema/DebuggerTestingTransform.cpp +++ b/lib/Sema/DebuggerTestingTransform.cpp @@ -227,8 +227,8 @@ class DebuggerTestingTransform : public ASTWalker { auto *Params = ParameterList::createEmpty(Ctx); auto *Closure = new (Ctx) ClosureExpr(SourceRange(), nullptr, Params, SourceLoc(), SourceLoc(), - SourceLoc(), nullptr, DF.getNextDiscriminator(), - getCurrentDeclContext()); + SourceLoc(), SourceLoc(), nullptr, + DF.getNextDiscriminator(), getCurrentDeclContext()); Closure->setImplicit(true); // TODO: Save and return the value of $OriginalExpr. diff --git a/lib/Sema/DerivedConformanceAdditiveArithmetic.cpp b/lib/Sema/DerivedConformanceAdditiveArithmetic.cpp index baddb7fcfd470..353980ddde7af 100644 --- a/lib/Sema/DerivedConformanceAdditiveArithmetic.cpp +++ b/lib/Sema/DerivedConformanceAdditiveArithmetic.cpp @@ -190,14 +190,12 @@ static ValueDecl *deriveMathOperator(DerivedConformance &derived, auto operatorId = C.getIdentifier(getMathOperatorName(op)); DeclName operatorDeclName(C, operatorId, params); - auto operatorDecl = - FuncDecl::create(C, SourceLoc(), StaticSpellingKind::KeywordStatic, - SourceLoc(), operatorDeclName, SourceLoc(), - /*Async*/ false, SourceLoc(), - /*Throws*/ false, SourceLoc(), - /*GenericParams=*/nullptr, params, - TypeLoc::withoutLoc(selfInterfaceType), parentDC); - operatorDecl->setImplicit(); + auto *const operatorDecl = FuncDecl::createImplicit( + C, StaticSpellingKind::KeywordStatic, operatorDeclName, + /*NameLoc=*/SourceLoc(), + /*Async=*/false, + /*Throws=*/false, + /*GenericParams=*/nullptr, params, selfInterfaceType, parentDC); auto bodySynthesizer = [](AbstractFunctionDecl *funcDecl, void *ctx) -> std::pair { auto op = (MathOperator) reinterpret_cast(ctx); diff --git a/lib/Sema/DerivedConformanceCaseIterable.cpp b/lib/Sema/DerivedConformanceCaseIterable.cpp index 14d3309936918..bc809b4e53930 100644 --- a/lib/Sema/DerivedConformanceCaseIterable.cpp +++ b/lib/Sema/DerivedConformanceCaseIterable.cpp @@ -69,6 +69,15 @@ static ArraySliceType *computeAllCasesType(NominalTypeDecl *enumDecl) { return ArraySliceType::get(enumType); } +static Type deriveCaseIterable_AllCases(DerivedConformance &derived) { + // enum SomeEnum : CaseIterable { + // @derived + // typealias AllCases = [SomeEnum] + // } + auto *rawInterfaceType = computeAllCasesType(cast(derived.Nominal)); + return derived.getConformanceContext()->mapTypeIntoContext(rawInterfaceType); +} + ValueDecl *DerivedConformance::deriveCaseIterable(ValueDecl *requirement) { // Conformance can't be synthesized in an extension. if (checkAndDiagnoseDisallowedContext(requirement)) @@ -102,3 +111,18 @@ ValueDecl *DerivedConformance::deriveCaseIterable(ValueDecl *requirement) { return propDecl; } + +Type DerivedConformance::deriveCaseIterable(AssociatedTypeDecl *assocType) { + // Check that we can actually derive CaseIterable for this type. + if (!canDeriveConformance(Nominal)) + return nullptr; + + if (assocType->getName() == Context.Id_AllCases) { + return deriveCaseIterable_AllCases(*this); + } + + Context.Diags.diagnose(assocType->getLoc(), + diag::broken_case_iterable_requirement); + return nullptr; +} + diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp index 701189126dc34..f903cd126b215 100644 --- a/lib/Sema/DerivedConformanceCodable.cpp +++ b/lib/Sema/DerivedConformanceCodable.cpp @@ -626,12 +626,11 @@ static FuncDecl *deriveEncodable_encode(DerivedConformance &derived) { // Func name: encode(to: Encoder) DeclName name(C, C.Id_encode, params); - auto *encodeDecl = FuncDecl::create( - C, SourceLoc(), StaticSpellingKind::None, SourceLoc(), name, SourceLoc(), - /*Async*/ false, SourceLoc(), - /*Throws=*/true, SourceLoc(), nullptr, params, - TypeLoc::withoutLoc(returnType), conformanceDC); - encodeDecl->setImplicit(); + auto *const encodeDecl = FuncDecl::createImplicit( + C, StaticSpellingKind::None, name, /*NameLoc=*/SourceLoc(), + /*Async=*/false, + /*Throws=*/true, /*GenericParams=*/nullptr, params, returnType, + conformanceDC); encodeDecl->setSynthesized(); encodeDecl->setBodySynthesizer(deriveBodyEncodable_encode); diff --git a/lib/Sema/DerivedConformanceComparable.cpp b/lib/Sema/DerivedConformanceComparable.cpp index 25be215c54351..61035b23364c1 100644 --- a/lib/Sema/DerivedConformanceComparable.cpp +++ b/lib/Sema/DerivedConformanceComparable.cpp @@ -255,17 +255,11 @@ deriveComparable_lt( } DeclName name(C, generatedIdentifier, params); - auto comparableDecl = - FuncDecl::create(C, /*StaticLoc=*/SourceLoc(), - StaticSpellingKind::KeywordStatic, - /*FuncLoc=*/SourceLoc(), name, /*NameLoc=*/SourceLoc(), - /*Async*/ false, SourceLoc(), - /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), - /*GenericParams=*/nullptr, - params, - TypeLoc::withoutLoc(boolTy), - parentDC); - comparableDecl->setImplicit(); + auto *const comparableDecl = FuncDecl::createImplicit( + C, StaticSpellingKind::KeywordStatic, name, /*NameLoc=*/SourceLoc(), + /*Async=*/false, + /*Throws=*/false, + /*GenericParams=*/nullptr, params, boolTy, parentDC); comparableDecl->setUserAccessible(false); // Add the @_implements(Comparable, < (_:_:)) attribute diff --git a/lib/Sema/DerivedConformanceDifferentiable.cpp b/lib/Sema/DerivedConformanceDifferentiable.cpp index b479372be9da0..451dc2c65efad 100644 --- a/lib/Sema/DerivedConformanceDifferentiable.cpp +++ b/lib/Sema/DerivedConformanceDifferentiable.cpp @@ -393,9 +393,9 @@ deriveBodyDifferentiable_zeroTangentVectorInitializer( auto *closureParams = ParameterList::createEmpty(C); auto *closure = new (C) ClosureExpr( - SourceRange(), /*capturedSelfDecl*/ nullptr, closureParams, SourceLoc(), - SourceLoc(), SourceLoc(), TypeExpr::createImplicit(resultTy, C), - discriminator, funcDecl); + SourceRange(), /*capturedSelfDecl*/ nullptr, closureParams, + SourceLoc(), SourceLoc(), SourceLoc(), SourceLoc(), + TypeExpr::createImplicit(resultTy, C), discriminator, funcDecl); closure->setImplicit(); auto *closureReturn = new (C) ReturnStmt(SourceLoc(), zeroExpr, true); auto *closureBody = @@ -504,8 +504,8 @@ deriveBodyDifferentiable_zeroTangentVectorInitializer( auto *closureParams = ParameterList::createEmpty(C); auto *closure = new (C) ClosureExpr( SourceRange(), /*capturedSelfDecl*/ nullptr, closureParams, SourceLoc(), - SourceLoc(), SourceLoc(), TypeExpr::createImplicit(resultTy, C), - discriminator, funcDecl); + SourceLoc(), SourceLoc(), SourceLoc(), + TypeExpr::createImplicit(resultTy, C), discriminator, funcDecl); closure->setImplicit(); auto *closureReturn = new (C) ReturnStmt(SourceLoc(), callExpr, true); auto *closureBody = @@ -544,15 +544,13 @@ static ValueDecl *deriveDifferentiable_method( ParameterList *params = ParameterList::create(C, {param}); DeclName declName(C, methodName, params); - auto *funcDecl = FuncDecl::create(C, SourceLoc(), StaticSpellingKind::None, - SourceLoc(), declName, SourceLoc(), - /*Async*/ false, SourceLoc(), - /*Throws*/ false, SourceLoc(), - /*GenericParams=*/nullptr, params, - TypeLoc::withoutLoc(returnType), parentDC); + auto *const funcDecl = FuncDecl::createImplicit( + C, StaticSpellingKind::None, declName, /*NameLoc=*/SourceLoc(), + /*Async=*/false, + /*Throws=*/false, + /*GenericParams=*/nullptr, params, returnType, parentDC); if (!nominal->getSelfClassDecl()) funcDecl->setSelfAccessKind(SelfAccessKind::Mutating); - funcDecl->setImplicit(); funcDecl->setBodySynthesizer(bodySynthesizer.Fn, bodySynthesizer.Context); funcDecl->setGenericSignature(parentDC->getGenericSignatureOfContext()); diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp index b77762648c7c4..54d5268c52cb5 100644 --- a/lib/Sema/DerivedConformanceEquatableHashable.cpp +++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp @@ -406,17 +406,11 @@ deriveEquatable_eq( } DeclName name(C, generatedIdentifier, params); - auto eqDecl = - FuncDecl::create(C, /*StaticLoc=*/SourceLoc(), - StaticSpellingKind::KeywordStatic, - /*FuncLoc=*/SourceLoc(), name, /*NameLoc=*/SourceLoc(), - /*Async*/ false, SourceLoc(), - /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), - /*GenericParams=*/nullptr, - params, - TypeLoc::withoutLoc(boolTy), - parentDC); - eqDecl->setImplicit(); + auto *const eqDecl = FuncDecl::createImplicit( + C, StaticSpellingKind::KeywordStatic, name, /*NameLoc=*/SourceLoc(), + /*Async=*/false, + /*Throws=*/false, + /*GenericParams=*/nullptr, params, boolTy, parentDC); eqDecl->setUserAccessible(false); // Add the @_implements(Equatable, ==(_:_:)) attribute @@ -549,15 +543,11 @@ deriveHashable_hashInto( // Func name: hash(into: inout Hasher) -> () DeclName name(C, C.Id_hash, params); - auto *hashDecl = FuncDecl::create(C, - SourceLoc(), StaticSpellingKind::None, - SourceLoc(), name, SourceLoc(), - /*Async*/ false, SourceLoc(), - /*Throws=*/false, SourceLoc(), - nullptr, params, - TypeLoc::withoutLoc(returnType), - parentDC); - hashDecl->setImplicit(); + auto *const hashDecl = FuncDecl::createImplicit( + C, StaticSpellingKind::None, name, /*NameLoc=*/SourceLoc(), + /*Async=*/false, + /*Throws=*/false, + /*GenericParams=*/nullptr, params, returnType, parentDC); hashDecl->setBodySynthesizer(bodySynthesizer); hashDecl->copyFormalAccessFrom(derived.Nominal); @@ -899,7 +889,7 @@ static ValueDecl *deriveHashable_hashValue(DerivedConformance &derived) { /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None, /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), /*GenericParams=*/nullptr, params, - TypeLoc::withoutLoc(intType), parentDC); + intType, parentDC); getterDecl->setImplicit(); getterDecl->setBodySynthesizer(&deriveBodyHashable_hashValue); getterDecl->setIsTransparent(false); diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp index 6b96232009592..b3eb907ebb44b 100644 --- a/lib/Sema/DerivedConformances.cpp +++ b/lib/Sema/DerivedConformances.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "TypeChecker.h" +#include "swift/AST/ASTPrinter.h" #include "swift/AST/Decl.h" #include "swift/AST/Stmt.h" #include "swift/AST/Expr.h" @@ -429,8 +430,6 @@ DerivedConformance::declareDerivedPropertyGetter(VarDecl *property, auto &C = property->getASTContext(); auto parentDC = property->getDeclContext(); ParameterList *params = ParameterList::createEmpty(C); - - Type propertyInterfaceType = property->getInterfaceType(); auto getterDecl = AccessorDecl::create(C, /*FuncLoc=*/SourceLoc(), /*AccessorKeywordLoc=*/SourceLoc(), @@ -438,7 +437,7 @@ DerivedConformance::declareDerivedPropertyGetter(VarDecl *property, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None, /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), /*GenericParams=*/nullptr, params, - TypeLoc::withoutLoc(propertyInterfaceType), parentDC); + property->getInterfaceType(), parentDC); getterDecl->setImplicit(); getterDecl->setIsTransparent(false); @@ -490,8 +489,27 @@ bool DerivedConformance::checkAndDiagnoseDisallowedContext( Nominal->getModuleScopeContext() != getConformanceContext()->getModuleScopeContext()) { ConformanceDecl->diagnose(diag::cannot_synthesize_in_crossfile_extension, + Nominal->getDescriptiveKind(), Nominal->getName(), + synthesizing->getName(), getProtocolType()); Nominal->diagnose(diag::kind_declared_here, DescriptiveDeclKind::Type); + + // In editor mode, try to insert a stub. + if (Context.LangOpts.DiagnosticsEditorMode) { + auto Extension = cast(getConformanceContext()); + auto FixitLocation = Extension->getBraces().Start; + llvm::SmallString<128> Text; + { + llvm::raw_svector_ostream SS(Text); + swift::printRequirementStub(synthesizing, Nominal, + Nominal->getDeclaredType(), + Extension->getStartLoc(), SS); + if (!Text.empty()) { + ConformanceDecl->diagnose(diag::missing_witnesses_general) + .fixItInsertAfter(FixitLocation, Text.str()); + } + } + } return true; } diff --git a/lib/Sema/DerivedConformances.h b/lib/Sema/DerivedConformances.h index 3465402b7a9d6..c5dba4bb20172 100644 --- a/lib/Sema/DerivedConformances.h +++ b/lib/Sema/DerivedConformances.h @@ -163,6 +163,12 @@ class DerivedConformance { /// \returns the derived member, which will also be added to the type. ValueDecl *deriveCaseIterable(ValueDecl *requirement); + /// Derive a CaseIterable type witness for an enum if it has no associated + /// values for any of its cases. + /// + /// \returns the derived member, which will also be added to the type. + Type deriveCaseIterable(AssociatedTypeDecl *assocType); + /// Determine if a RawRepresentable requirement can be derived for a type. /// /// This is implemented for non-empty enums without associated values, diff --git a/lib/Sema/LookupVisibleDecls.cpp b/lib/Sema/LookupVisibleDecls.cpp index cc1ef792f5c92..53bb7c8c57512 100644 --- a/lib/Sema/LookupVisibleDecls.cpp +++ b/lib/Sema/LookupVisibleDecls.cpp @@ -946,17 +946,22 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer { /*wouldConflictInSwift5*/nullptr, /*skipProtocolExtensionCheck*/true)) { FoundConflicting = true; - // Prefer derived requirements over their witnesses. - if (Reason == - DeclVisibilityKind::MemberOfProtocolDerivedByCurrentNominal || - VD->getFormalAccess() > OtherVD->getFormalAccess() || - //Prefer available one. - (!AvailableAttr::isUnavailable(VD) && - AvailableAttr::isUnavailable(OtherVD))) { - FilteredResults.remove( - FoundDeclTy(OtherVD, DeclVisibilityKind::LocalVariable, {})); - FilteredResults.insert(DeclAndReason); - *I = VD; + + if (!AvailableAttr::isUnavailable(VD)) { + bool preferVD = ( + // Prefer derived requirements over their witnesses. + Reason == DeclVisibilityKind:: + MemberOfProtocolDerivedByCurrentNominal || + // Prefer available one. + AvailableAttr::isUnavailable(OtherVD) || + // Prefer more accessible one. + VD->getFormalAccess() > OtherVD->getFormalAccess()); + if (preferVD) { + FilteredResults.remove( + FoundDeclTy(OtherVD, DeclVisibilityKind::LocalVariable, {})); + FilteredResults.insert(DeclAndReason); + *I = VD; + } } } } diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 563f281663182..f8bf7cd5219fe 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -594,8 +594,8 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, isExistential = instanceTy->isExistentialType(); if (!isExistential && instanceTy->mayHaveMembers() && - !TypeChecker::lookupConstructors(const_cast(DC), - instanceTy).empty()) { + !TypeChecker::lookupMember(const_cast(DC), instanceTy, + DeclNameRef::createConstructor()).empty()) { Ctx.Diags.diagnose(E->getEndLoc(), diag::add_parens_to_type) .fixItInsertAfter(E->getEndLoc(), "()"); } @@ -2223,7 +2223,7 @@ static bool fixItOverrideDeclarationTypesImpl( fixedAny |= checkType(resultType, ParamDecl::Specifier::Default, baseResultType, ParamDecl::Specifier::Default, - method->getBodyResultTypeLoc().getSourceRange()); + method->getResultTypeSourceRange()); } return fixedAny; } @@ -2246,7 +2246,7 @@ static bool fixItOverrideDeclarationTypesImpl( baseSubscript->getElementInterfaceType()); fixedAny |= checkType(resultType, ParamDecl::Specifier::Default, baseResultType, ParamDecl::Specifier::Default, - subscript->getElementTypeLoc().getSourceRange()); + subscript->getElementTypeSourceRange()); return fixedAny; } diff --git a/lib/Sema/PCMacro.cpp b/lib/Sema/PCMacro.cpp index 5d6075ef5b031..573ad52e9f8f8 100644 --- a/lib/Sema/PCMacro.cpp +++ b/lib/Sema/PCMacro.cpp @@ -226,8 +226,8 @@ class Instrumenter : InstrumenterBase { SourceLoc StartLoc = FES->getStartLoc(); SourceLoc EndLoc = FES->getSequence()->getEndLoc(); // FIXME: get the 'end' of the for stmt - // if (FD->getBodyResultTypeLoc().hasLocation()) { - // EndLoc = FD->getBodyResultTypeLoc().getSourceRange().End; + // if (FD->getResultTypeRepr()) { + // EndLoc = FD->getResultTypeSourceRange().End; // } else { // EndLoc = FD->getParameters()->getSourceRange().End; // } @@ -343,8 +343,8 @@ class Instrumenter : InstrumenterBase { // decl at the start of the transformed body SourceLoc StartLoc = FD->getStartLoc(); SourceLoc EndLoc = SourceLoc(); - if (FD->getBodyResultTypeLoc().hasLocation()) { - EndLoc = FD->getBodyResultTypeLoc().getSourceRange().End; + if (FD->getResultTypeRepr()) { + EndLoc = FD->getResultTypeSourceRange().End; } else { EndLoc = FD->getParameters()->getSourceRange().End; } @@ -354,7 +354,7 @@ class Instrumenter : InstrumenterBase { if (NB != B) { FD->setBody(NB); - TypeChecker::checkFunctionErrorHandling(FD); + TypeChecker::checkFunctionEffects(FD); } } } else if (auto *NTD = dyn_cast(D)) { @@ -695,7 +695,7 @@ void swift::performPCMacro(SourceFile &SF) { BraceStmt *NewBody = I.transformBraceStmt(Body, true); if (NewBody != Body) { TLCD->setBody(NewBody); - TypeChecker::checkTopLevelErrorHandling(TLCD); + TypeChecker::checkTopLevelEffects(TLCD); TypeChecker::contextualizeTopLevelCode(TLCD); } return false; diff --git a/lib/Sema/PlaygroundTransform.cpp b/lib/Sema/PlaygroundTransform.cpp index 7c7e9dcd1e39b..f36294ff47240 100644 --- a/lib/Sema/PlaygroundTransform.cpp +++ b/lib/Sema/PlaygroundTransform.cpp @@ -294,7 +294,7 @@ class Instrumenter : InstrumenterBase { BraceStmt *NB = transformBraceStmt(B); if (NB != B) { FD->setBody(NB); - TypeChecker::checkFunctionErrorHandling(FD); + TypeChecker::checkFunctionEffects(FD); } } } else if (auto *NTD = dyn_cast(D)) { @@ -893,7 +893,7 @@ void swift::performPlaygroundTransform(SourceFile &SF, bool HighPerformance) { BraceStmt *NewBody = I.transformBraceStmt(Body); if (NewBody != Body) { FD->setBody(NewBody); - TypeChecker::checkFunctionErrorHandling(FD); + TypeChecker::checkFunctionEffects(FD); } return false; } @@ -905,7 +905,7 @@ void swift::performPlaygroundTransform(SourceFile &SF, bool HighPerformance) { BraceStmt *NewBody = I.transformBraceStmt(Body, true); if (NewBody != Body) { TLCD->setBody(NewBody); - TypeChecker::checkTopLevelErrorHandling(TLCD); + TypeChecker::checkTopLevelEffects(TLCD); } return false; } diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index e9b75ad9b5ac1..8f2556c311a85 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -873,7 +873,8 @@ class AccessControlChecker : public AccessControlCheckerBase, }); } - checkTypeAccess(SD->getElementTypeLoc(), SD, /*mayBeInferred*/false, + checkTypeAccess(SD->getElementInterfaceType(), SD->getElementTypeRepr(), + SD, /*mayBeInferred*/false, [&](AccessScope typeAccessScope, const TypeRepr *thisComplainRepr, DowngradeToWarning downgradeDiag) { @@ -937,7 +938,8 @@ class AccessControlChecker : public AccessControlCheckerBase, bool problemIsResult = false; if (auto FD = dyn_cast(fn)) { - checkTypeAccess(FD->getBodyResultTypeLoc(), FD, /*mayBeInferred*/false, + checkTypeAccess(FD->getResultInterfaceType(), FD->getResultTypeRepr(), + FD, /*mayBeInferred*/false, [&](AccessScope typeAccessScope, const TypeRepr *thisComplainRepr, DowngradeToWarning downgradeDiag) { @@ -1375,7 +1377,8 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, }); } - checkTypeAccess(SD->getElementTypeLoc(), SD, /*mayBeInferred*/false, + checkTypeAccess(SD->getElementInterfaceType(), SD->getElementTypeRepr(), + SD, /*mayBeInferred*/false, [&](AccessScope typeAccessScope, const TypeRepr *complainRepr, DowngradeToWarning downgradeDiag) { @@ -1418,7 +1421,8 @@ class UsableFromInlineChecker : public AccessControlCheckerBase, } if (auto FD = dyn_cast(fn)) { - checkTypeAccess(FD->getBodyResultTypeLoc(), FD, /*mayBeInferred*/false, + checkTypeAccess(FD->getResultInterfaceType(), FD->getResultTypeRepr(), + FD, /*mayBeInferred*/false, [&](AccessScope typeAccessScope, const TypeRepr *complainRepr, DowngradeToWarning downgradeDiag) { @@ -1916,7 +1920,8 @@ class ExportabilityChecker : public DeclVisitor { checkType(P->getInterfaceType(), P->getTypeRepr(), SD, getDiagnoser(SD)); } - checkType(SD->getElementTypeLoc(), SD, getDiagnoser(SD)); + checkType(SD->getElementInterfaceType(), SD->getElementTypeRepr(), SD, + getDiagnoser(SD)); } void visitAbstractFunctionDecl(AbstractFunctionDecl *fn) { @@ -1929,7 +1934,8 @@ class ExportabilityChecker : public DeclVisitor { void visitFuncDecl(FuncDecl *FD) { visitAbstractFunctionDecl(FD); - checkType(FD->getBodyResultTypeLoc(), FD, getDiagnoser(FD)); + checkType(FD->getResultInterfaceType(), FD->getResultTypeRepr(), FD, + getDiagnoser(FD)); } void visitEnumElementDecl(EnumElementDecl *EED) { diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 1133d4eb3199b..df4080e85a1ba 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -257,6 +257,22 @@ class AttributeChecker : public AttributeVisitor { void visitDifferentiableAttr(DifferentiableAttr *attr); void visitDerivativeAttr(DerivativeAttr *attr); void visitTransposeAttr(TransposeAttr *attr); + + void visitAsyncHandlerAttr(AsyncHandlerAttr *attr) { + if (!Ctx.LangOpts.EnableExperimentalConcurrency) { + diagnoseAndRemoveAttr(attr, diag::asynchandler_attr_requires_concurrency); + return; + } + + auto func = dyn_cast(D); + if (!func) { + diagnoseAndRemoveAttr(attr, diag::asynchandler_non_func); + return; + } + + // Trigger the request to check for @asyncHandler. + (void)func->isAsyncHandler(); + } }; } // end anonymous namespace @@ -301,14 +317,17 @@ void AttributeChecker::visitMutationAttr(DeclAttribute *attr) { llvm_unreachable("unhandled attribute kind"); } + auto DC = FD->getDeclContext(); // mutation attributes may only appear in type context. - if (auto contextTy = FD->getDeclContext()->getDeclaredInterfaceType()) { + if (auto contextTy = DC->getDeclaredInterfaceType()) { // 'mutating' and 'nonmutating' are not valid on types // with reference semantics. if (contextTy->hasReferenceSemantics()) { - if (attrModifier != SelfAccessKind::Consuming) + if (attrModifier != SelfAccessKind::Consuming) { diagnoseAndRemoveAttr(attr, diag::mutating_invalid_classes, - attrModifier); + attrModifier, FD->getDescriptiveKind(), + DC->getSelfProtocolDecl() != nullptr); + } } } else { diagnoseAndRemoveAttr(attr, diag::mutating_invalid_global_scope, @@ -1893,19 +1912,15 @@ SynthesizeMainFunctionRequest::evaluate(Evaluator &evaluator, mainFunction = viableCandidates[0]; } - auto *func = FuncDecl::create( - context, /*StaticLoc*/ SourceLoc(), StaticSpellingKind::KeywordStatic, - /*FuncLoc*/ SourceLoc(), + auto *const func = FuncDecl::createImplicit( + context, StaticSpellingKind::KeywordStatic, DeclName(context, DeclBaseName(context.Id_MainEntryPoint), ParameterList::createEmpty(context)), - /*NameLoc*/ SourceLoc(), - /*Async*/ false, SourceLoc(), + /*NameLoc=*/SourceLoc(), + /*Async=*/false, /*Throws=*/mainFunction->hasThrows(), - /*ThrowsLoc=*/SourceLoc(), /*GenericParams=*/nullptr, ParameterList::createEmpty(context), - /*FnRetType=*/TypeLoc::withoutLoc(TupleType::getEmpty(context)), - declContext); - func->setImplicit(true); + /*FnRetType=*/TupleType::getEmpty(context), declContext); func->setSynthesized(true); auto *params = context.Allocate(); @@ -2886,18 +2901,7 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) { auto nominal = evaluateOrDefault( Ctx.evaluator, CustomAttrNominalRequest{attr, dc}, nullptr); - // If there is no nominal type with this name, complain about this being - // an unknown attribute. if (!nominal) { - std::string typeName; - if (auto typeRepr = attr->getTypeRepr()) { - llvm::raw_string_ostream out(typeName); - typeRepr->print(out); - } else { - typeName = attr->getType().getString(); - } - - diagnose(attr->getLocation(), diag::unknown_attribute, typeName); attr->setInvalid(); return; } @@ -4770,7 +4774,7 @@ static bool typeCheckDerivativeAttr(ASTContext &Ctx, Decl *D, // Emit note with expected differential/pullback type on actual type // location. auto *tupleReturnTypeRepr = - cast(derivative->getBodyResultTypeLoc().getTypeRepr()); + cast(derivative->getResultTypeRepr()); auto *funcEltTypeRepr = tupleReturnTypeRepr->getElementType(1); diags .diagnose(funcEltTypeRepr->getStartLoc(), diff --git a/lib/Sema/TypeCheckCodeCompletion.cpp b/lib/Sema/TypeCheckCodeCompletion.cpp index b40af172a2cd5..6ba92aeb42dd4 100644 --- a/lib/Sema/TypeCheckCodeCompletion.cpp +++ b/lib/Sema/TypeCheckCodeCompletion.cpp @@ -416,6 +416,8 @@ getTypeOfExpressionWithoutApplying(Expr *&expr, DeclContext *dc, assert(exprType && !exprType->hasTypeVariable() && "free type variable with FreeTypeVariableBinding::GenericParameters?"); + assert(exprType && !exprType->hasHole() && + "type hole with FreeTypeVariableBinding::GenericParameters?"); if (exprType->hasError()) { recoverOriginalType(); @@ -553,10 +555,10 @@ TypeChecker::getTypeOfCompletionOperator(DeclContext *DC, Expr *LHS, // 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. UnresolvedDeclRefExpr UDRE(DeclNameRef(opName), refKind, DeclNameLoc(Loc)); - auto *opExpr = TypeChecker::resolveDeclRefExpr(&UDRE, DC); + auto *opExpr = TypeChecker::resolveDeclRefExpr( + &UDRE, DC, /*replaceInvalidRefsWithErrors=*/true); switch (refKind) { - case DeclRefKind::PostfixOperator: { // (postfix_unary_expr // (declref_expr name=) @@ -611,7 +613,8 @@ static Optional getTypeOfCompletionContextExpr( CompletionTypeCheckKind kind, Expr *&parsedExpr, ConcreteDeclRef &referencedDecl) { - if (constraints::ConstraintSystem::preCheckExpression(parsedExpr, DC)) + if (constraints::ConstraintSystem::preCheckExpression( + parsedExpr, DC, /*replaceInvalidRefsWithErrors=*/true)) return None; switch (kind) { diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp new file mode 100644 index 0000000000000..2019e8a179bf3 --- /dev/null +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -0,0 +1,163 @@ +//===--- TypeCheckConcurrency.cpp - Concurrency ---------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This file implements type checking support for Swift's concurrency model. +// +//===----------------------------------------------------------------------===// +#include "TypeChecker.h" +#include "swift/AST/ParameterList.h" +#include "swift/AST/ProtocolConformance.h" +#include "swift/AST/TypeCheckRequests.h" + +using namespace swift; + +/// Check whether the @asyncHandler attribute can be applied to the given +/// function declaration. +/// +/// \param diagnose Whether to emit a diagnostic when a problem is encountered. +/// +/// \returns \c true if there was a problem with adding the attribute, \c false +/// otherwise. +static bool checkAsyncHandler(FuncDecl *func, bool diagnose) { + if (!func->getResultInterfaceType()->isVoid()) { + if (diagnose) { + func->diagnose(diag::asynchandler_returns_value) + .highlight(func->getResultTypeSourceRange()); + } + + return true; + } + + if (func->hasThrows()) { + if (diagnose) { + func->diagnose(diag::asynchandler_throws) + .fixItRemove(func->getThrowsLoc()); + } + + return true; + } + + if (func->hasAsync()) { + if (diagnose) { + func->diagnose(diag::asynchandler_async) + .fixItRemove(func->getAsyncLoc()); + } + + return true; + } + + for (auto param : *func->getParameters()) { + if (param->isInOut()) { + if (diagnose) { + param->diagnose(diag::asynchandler_inout_parameter) + .fixItRemove(param->getSpecifierLoc()); + } + + return true; + } + } + + if (func->isMutating()) { + if (diagnose) { + auto diag = func->diagnose(diag::asynchandler_mutating); + if (auto mutatingAttr = func->getAttrs().getAttribute()) { + diag.fixItRemove(mutatingAttr->getRange()); + } + } + + return true; + } + + return false; +} + +void swift::addAsyncNotes(FuncDecl *func) { + func->diagnose(diag::note_add_async_to_function, func->getName()); + + if (!checkAsyncHandler(func, /*diagnose=*/false)) { + func->diagnose( + diag::note_add_asynchandler_to_function, func->getName()) + .fixItInsert(func->getAttributeInsertionLoc(false), "@asyncHandler "); + } +} + +bool IsAsyncHandlerRequest::evaluate( + Evaluator &evaluator, FuncDecl *func) const { + // Check whether the attribute was explicitly specified. + if (auto attr = func->getAttrs().getAttribute()) { + // Check for well-formedness. + if (checkAsyncHandler(func, /*diagnose=*/true)) { + attr->setInvalid(); + return false; + } + + return true; + } + + if (!func->getASTContext().LangOpts.EnableExperimentalConcurrency) + return false; + + // Are we in a context where inference is possible? + auto dc = func->getDeclContext(); + if (!dc->isTypeContext() || !dc->getParentSourceFile() || + isa(dc) || !func->hasBody()) + return false; + + // Is it possible to infer @asyncHandler for this function at all? + if (checkAsyncHandler(func, /*diagnose=*/false)) + return false; + + // Add an implicit @asyncHandler attribute and return true. We're done. + auto addImplicitAsyncHandlerAttr = [&] { + func->getAttrs().add(new (func->getASTContext()) AsyncHandlerAttr(true)); + return true; + }; + + // Check whether any of the conformances in the context of the function + // implies @asyncHandler. + { + auto idc = cast(dc->getAsDecl()); + auto conformances = evaluateOrDefault( + dc->getASTContext().evaluator, + LookupAllConformancesInContextRequest{idc}, { }); + + for (auto conformance : conformances) { + auto protocol = conformance->getProtocol(); + for (auto found : protocol->lookupDirect(func->getName())) { + if (!isa(found->getDeclContext())) + continue; + + auto requirement = dyn_cast(found); + if (!requirement) + continue; + + if (!requirement->isAsyncHandler()) + continue; + + auto witness = conformance->getWitnessDecl(requirement); + if (witness != func) + continue; + + return addImplicitAsyncHandlerAttr(); + } + } + } + + // Look through dynamic replacements. + if (auto replaced = func->getDynamicallyReplacedDecl()) { + if (auto replacedFunc = dyn_cast(replaced)) + if (replacedFunc->isAsyncHandler()) + return addImplicitAsyncHandlerAttr(); + } + + return false; +} diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index bd6a0fc589bb1..f0226a6d094e8 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -477,15 +477,62 @@ static bool findNonMembers(ArrayRef lookupResults, return AllDeclRefs; } +/// Find the next element in a chain of members. If this expression is (or +/// could be) the base of such a chain, this will return \c nullptr. +static Expr *getMemberChainSubExpr(Expr *expr) { + assert(expr && "getMemberChainSubExpr called with null expr!"); + if (auto *UDE = dyn_cast(expr)) { + return UDE->getBase(); + } else if (auto *CE = dyn_cast(expr)) { + return CE->getFn(); + } else if (auto *BOE = dyn_cast(expr)) { + return BOE->getSubExpr(); + } else if (auto *FVE = dyn_cast(expr)) { + return FVE->getSubExpr(); + } else if (auto *SE = dyn_cast(expr)) { + return SE->getBase(); + } else if (auto *CCE = dyn_cast(expr)) { + return CCE->getBase(); + } else { + return nullptr; + } +} + +UnresolvedMemberExpr *TypeChecker::getUnresolvedMemberChainBase(Expr *expr) { + if (auto *subExpr = getMemberChainSubExpr(expr)) + return getUnresolvedMemberChainBase(subExpr); + else + return dyn_cast(expr); +} + +/// Whether this expression is a member of a member chain. +static bool isMemberChainMember(Expr *expr) { + return getMemberChainSubExpr(expr) != nullptr; +} +/// Whether this expression sits at the end of a chain of member accesses. +static bool isMemberChainTail(Expr *expr, Expr *parent) { + assert(expr && "isMemberChainTail called with null expr!"); + // If this expression's parent is not itself part of a chain (or, this expr + // has no parent expr), this must be the tail of the chain. + return parent == nullptr || !isMemberChainMember(parent); +} + /// Bind an UnresolvedDeclRefExpr by performing name lookup and /// returning the resultant expression. Context is the DeclContext used /// for the lookup. Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, - DeclContext *DC) { + DeclContext *DC, + bool replaceInvalidRefsWithErrors) { // Process UnresolvedDeclRefExpr by doing an unqualified lookup. DeclNameRef Name = UDRE->getName(); SourceLoc Loc = UDRE->getLoc(); + auto errorResult = [&]() -> Expr * { + if (replaceInvalidRefsWithErrors) + return new (DC->getASTContext()) ErrorExpr(UDRE->getSourceRange()); + return UDRE; + }; + // Perform standard value name lookup. NameLookupOptions lookupOptions = defaultUnqualifiedLookupOptions; if (isa(DC)) @@ -506,7 +553,7 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, if (diagnoseRangeOperatorMisspell(Context.Diags, UDRE) || diagnoseIncDecOperator(Context.Diags, UDRE) || diagnoseOperatorJuxtaposition(UDRE, DC)) { - return new (Context) ErrorExpr(UDRE->getSourceRange()); + return errorResult(); } // Try ignoring access control. @@ -531,7 +578,7 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, // Don't try to recover here; we'll get more access-related diagnostics // downstream if the type of the inaccessible decl is also inaccessible. - return new (Context) ErrorExpr(UDRE->getSourceRange()); + return errorResult(); } // TODO: Name will be a compound name if it was written explicitly as @@ -625,7 +672,7 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, // TODO: consider recovering from here. We may want some way to suppress // downstream diagnostics, though. - return new (Context) ErrorExpr(UDRE->getSourceRange()); + return errorResult(); } // FIXME: Need to refactor the way we build an AST node from a lookup result! @@ -916,6 +963,10 @@ namespace { Expr *ParentExpr; + /// Indicates whether pre-check is allowed to insert + /// implicit `ErrorExpr` in place of invalid references. + bool UseErrorExprs; + /// A stack of expressions being walked, used to determine where to /// insert RebindSelfInConstructorExpr nodes. llvm::SmallVector ExprStack; @@ -962,12 +1013,12 @@ namespace { public: StrangeInterpolationRewriter(ASTContext &Ctx) : Context(Ctx) {} - virtual bool walkToDeclPre(Decl *D) { + virtual bool walkToDeclPre(Decl *D) override { // We don't want to look inside decls. return false; } - virtual std::pair walkToExprPre(Expr *E) { + virtual std::pair walkToExprPre(Expr *E) override { // One InterpolatedStringLiteralExpr should never be nested inside // another except as a child of a CallExpr, and we don't recurse into // the children of CallExprs. @@ -1055,8 +1106,10 @@ namespace { } public: - PreCheckExpression(DeclContext *dc, Expr *parent) - : Ctx(dc->getASTContext()), DC(dc), ParentExpr(parent) {} + PreCheckExpression(DeclContext *dc, Expr *parent, + bool replaceInvalidRefsWithErrors) + : Ctx(dc->getASTContext()), DC(dc), ParentExpr(parent), + UseErrorExprs(replaceInvalidRefsWithErrors) {} ASTContext &getASTContext() const { return Ctx; } @@ -1072,13 +1125,6 @@ namespace { } } - // If this is an unresolved member with a call argument (e.g., - // .some(x)), record the argument expression. - if (auto unresolvedMember = dyn_cast(expr)) { - if (auto arg = unresolvedMember->getArgument()) - CallArgs.insert(arg); - } - // FIXME(diagnostics): `InOutType` could appear here as a result // of successful re-typecheck of the one of the sub-expressions e.g. // `let _: Int = { (s: inout S) in s.bar() }`. On the first @@ -1122,7 +1168,8 @@ namespace { if (auto unresolved = dyn_cast(expr)) { TypeChecker::checkForForbiddenPrefix( getASTContext(), unresolved->getName().getBaseName()); - return finish(true, TypeChecker::resolveDeclRefExpr(unresolved, DC)); + return finish(true, TypeChecker::resolveDeclRefExpr(unresolved, DC, + UseErrorExprs)); } // Let's try to figure out if `InOutExpr` is out of place early @@ -1312,6 +1359,14 @@ namespace { if (auto *simplified = simplifyTypeConstructionWithLiteralArg(expr)) return simplified; + // If we find an unresolved member chain, wrap it in an + // UnresolvedMemberChainResultExpr (unless this has already been done). + auto *parent = Parent.getAsExpr(); + if (isMemberChainTail(expr, parent)) + if (auto *UME = TypeChecker::getUnresolvedMemberChainBase(expr)) + if (!parent || !isa(parent)) + return new (ctx) UnresolvedMemberChainResultExpr(expr, UME); + return expr; } @@ -1900,7 +1955,6 @@ void PreCheckExpression::resolveKeyPathExpr(KeyPathExpr *KPE) { // Key paths must be spelled with at least one component. if (components.empty()) { - DE.diagnose(KPE->getLoc(), diag::expr_swift_keypath_empty); // Passes further down the pipeline expect keypaths to always have at least // one component, so stuff an invalid component in the AST for recovery. components.push_back(KeyPathExpr::Component()); @@ -1980,8 +2034,9 @@ Expr *PreCheckExpression::simplifyTypeConstructionWithLiteralArg(Expr *E) { /// Pre-check the expression, validating any types that occur in the /// expression and folding sequence expressions. -bool ConstraintSystem::preCheckExpression(Expr *&expr, DeclContext *dc) { - PreCheckExpression preCheck(dc, expr); +bool ConstraintSystem::preCheckExpression(Expr *&expr, DeclContext *dc, + bool replaceInvalidRefsWithErrors) { + PreCheckExpression preCheck(dc, expr, replaceInvalidRefsWithErrors); // Perform the pre-check. if (auto result = expr->walk(preCheck)) { expr = result; @@ -2108,7 +2163,8 @@ TypeChecker::typeCheckExpression( // First, pre-check the expression, validating any types that occur in the // expression and folding sequence expressions. - if (ConstraintSystem::preCheckExpression(expr, dc)) { + if (ConstraintSystem::preCheckExpression( + expr, dc, /*replaceInvalidRefsWithErrors=*/true)) { target.setExpr(expr); return None; } @@ -2337,13 +2393,15 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) { // Precheck the sequence. Expr *sequence = stmt->getSequence(); - if (ConstraintSystem::preCheckExpression(sequence, dc)) + if (ConstraintSystem::preCheckExpression( + sequence, dc, /*replaceInvalidRefsWithErrors=*/true)) return failed(); stmt->setSequence(sequence); // Precheck the filtering condition. if (Expr *whereExpr = stmt->getWhere()) { - if (ConstraintSystem::preCheckExpression(whereExpr, dc)) + if (ConstraintSystem::preCheckExpression( + whereExpr, dc, /*replaceInvalidRefsWithErrors=*/true)) return failed(); stmt->setWhere(whereExpr); @@ -2905,7 +2963,7 @@ void ConstraintSystem::print(raw_ostream &out) const { out << " as "; Type(fixed).print(out, PO); } else { - getPotentialBindings(tv).dump(out, 1); + inferBindingsFor(tv).dump(out, 1); } } else { out << " equivalent to "; diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index d8fb606a5c388..93c9effd91e74 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1066,7 +1066,7 @@ EnumRawValuesRequest::evaluate(Evaluator &eval, EnumDecl *ED, if (TypeChecker::typeCheckExpression(exprToCheck, ED, rawTy, CTP_EnumCaseRawValue)) { - TypeChecker::checkEnumElementErrorHandling(elt, exprToCheck); + TypeChecker::checkEnumElementEffects(elt, exprToCheck); } } @@ -1682,7 +1682,7 @@ IsImplicitlyUnwrappedOptionalRequest::evaluate(Evaluator &evaluator, switch (decl->getKind()) { case DeclKind::Func: { - TyR = cast(decl)->getBodyResultTypeLoc().getTypeRepr(); + TyR = cast(decl)->getResultTypeRepr(); break; } @@ -1693,14 +1693,14 @@ IsImplicitlyUnwrappedOptionalRequest::evaluate(Evaluator &evaluator, auto *storage = accessor->getStorage(); if (auto *subscript = dyn_cast(storage)) - TyR = subscript->getElementTypeLoc().getTypeRepr(); + TyR = subscript->getElementTypeRepr(); else TyR = cast(storage)->getTypeReprOrParentPatternTypeRepr(); break; } case DeclKind::Subscript: - TyR = cast(decl)->getElementTypeLoc().getTypeRepr(); + TyR = cast(decl)->getElementTypeRepr(); break; case DeclKind::Param: { @@ -2003,7 +2003,12 @@ ResultTypeRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const { } } - auto *resultTyRepr = getResultTypeLoc().getTypeRepr(); + TypeRepr *resultTyRepr = nullptr; + if (const auto *const funcDecl = dyn_cast(decl)) { + resultTyRepr = funcDecl->getResultTypeRepr(); + } else { + resultTyRepr = cast(decl)->getElementTypeRepr(); + } // Nothing to do if there's no result type. if (resultTyRepr == nullptr) @@ -2148,9 +2153,21 @@ static Type validateParameterType(ParamDecl *decl) { decl->setInvalid(); return ErrorType::get(ctx); } + } - return Ty; + // async autoclosures can only occur as parameters to async functions. + if (decl->isAutoClosure()) { + if (auto fnType = Ty->getAs()) { + if (fnType->isAsync() && + !(isa(dc) && + cast(dc)->isAsyncContext())) { + decl->diagnose(diag::async_autoclosure_nonasync_function); + if (auto func = dyn_cast(dc)) + addAsyncNotes(func); + } + } } + return Ty; } diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp index c6b98e0991863..7e8c1d45521f8 100644 --- a/lib/Sema/TypeCheckDeclObjC.cpp +++ b/lib/Sema/TypeCheckDeclObjC.cpp @@ -604,9 +604,8 @@ bool swift::isRepresentableInObjC( if (Diagnose) { AFD->diagnose(diag::objc_invalid_on_func_result_type, getObjCDiagnosticAttrKind(Reason)); - SourceRange Range = - FD->getBodyResultTypeLoc().getTypeRepr()->getSourceRange(); - diagnoseTypeNotRepresentableInObjC(FD, ResultType, Range); + diagnoseTypeNotRepresentableInObjC(FD, ResultType, + FD->getResultTypeSourceRange()); describeObjCReason(FD, Reason); } return false; @@ -928,7 +927,7 @@ bool swift::isRepresentableInObjC(const SubscriptDecl *SD, ObjCReason Reason) { if (!IndexResult) TypeRange = SD->getIndices()->getSourceRange(); else - TypeRange = SD->getElementTypeLoc().getSourceRange(); + TypeRange = SD->getElementTypeSourceRange(); SD->diagnose(diag::objc_invalid_on_subscript, getObjCDiagnosticAttrKind(Reason)) .highlight(TypeRange); diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index 9be81b3cdb722..153c37ed7df83 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -1169,7 +1169,8 @@ bool OverrideMatcher::checkOverride(ValueDecl *baseDecl, // Private migration help for overrides of Objective-C methods. TypeLoc resultTL; if (auto *methodAsFunc = dyn_cast(method)) - resultTL = methodAsFunc->getBodyResultTypeLoc(); + resultTL = TypeLoc(methodAsFunc->getResultTypeRepr(), + methodAsFunc->getResultInterfaceType()); emittedMatchError |= diagnoseMismatchedOptionals( method, method->getParameters(), resultTL, baseDecl, @@ -1197,9 +1198,11 @@ bool OverrideMatcher::checkOverride(ValueDecl *baseDecl, emittedMatchError = true; } else if (mayHaveMismatchedOptionals) { + TypeLoc elementTL(subscript->getElementTypeRepr(), + subscript->getElementInterfaceType()); emittedMatchError |= diagnoseMismatchedOptionals( subscript, subscript->getIndices(), - subscript->getElementTypeLoc(), baseDecl, + elementTL, baseDecl, cast(baseDecl)->getIndices(), owningTy, mayHaveMismatchedOptionals); } @@ -1416,6 +1419,7 @@ namespace { UNINTERESTING_ATTR(AccessControl) UNINTERESTING_ATTR(Alignment) UNINTERESTING_ATTR(AlwaysEmitIntoClient) + UNINTERESTING_ATTR(AsyncHandler) UNINTERESTING_ATTR(Borrowed) UNINTERESTING_ATTR(CDecl) UNINTERESTING_ATTR(Consuming) diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index c307cca174ce5..95f137573b909 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -754,35 +754,38 @@ CheckRedeclarationRequest::evaluate(Evaluator &eval, ValueDecl *current) const { declToDiagnose->diagnose(diag::invalid_redecl_implicit, current->getDescriptiveKind(), isProtocolRequirement, other->getName()); - } - // Emit a specialized note if the one of the declarations is - // the backing storage property ('_foo') or projected value - // property ('$foo') for a wrapped property. The backing or - // projected var has the same source location as the wrapped - // property we diagnosed above, so we don't need to extract - // the original property. - const VarDecl *varToDiagnose = nullptr; - auto kind = PropertyWrapperSynthesizedPropertyKind::Backing; - if (auto currentVD = dyn_cast(current)) { - if (auto currentKind = - currentVD->getPropertyWrapperSynthesizedPropertyKind()) { - varToDiagnose = currentVD; - kind = *currentKind; + // Emit a specialized note if the one of the declarations is + // the backing storage property ('_foo') or projected value + // property ('$foo') for a wrapped property. The backing or + // projected var has the same source location as the wrapped + // property we diagnosed above, so we don't need to extract + // the original property. + const VarDecl *varToDiagnose = nullptr; + auto kind = PropertyWrapperSynthesizedPropertyKind::Backing; + if (auto currentVD = dyn_cast(current)) { + if (auto currentKind = + currentVD->getPropertyWrapperSynthesizedPropertyKind()) { + varToDiagnose = currentVD; + kind = *currentKind; + } } - } - if (auto otherVD = dyn_cast(other)) { - if (auto otherKind = - otherVD->getPropertyWrapperSynthesizedPropertyKind()) { - varToDiagnose = otherVD; - kind = *otherKind; + if (auto otherVD = dyn_cast(other)) { + if (auto otherKind = + otherVD->getPropertyWrapperSynthesizedPropertyKind()) { + varToDiagnose = otherVD; + kind = *otherKind; + } + } + + if (varToDiagnose) { + assert(declToDiagnose); + varToDiagnose->diagnose( + diag::invalid_redecl_implicit_wrapper, varToDiagnose->getName(), + kind == PropertyWrapperSynthesizedPropertyKind::Backing); } - } - if (varToDiagnose) { - varToDiagnose->diagnose( - diag::invalid_redecl_implicit_wrapper, varToDiagnose->getName(), - kind == PropertyWrapperSynthesizedPropertyKind::Backing); + current->setInvalid(); } } else { ctx.Diags.diagnoseWithNotes( @@ -790,8 +793,9 @@ CheckRedeclarationRequest::evaluate(Evaluator &eval, ValueDecl *current) const { current->getName()), [&]() { other->diagnose(diag::invalid_redecl_prev, other->getName()); }); + + current->setInvalid(); } - current->setInvalid(); } // Make sure we don't do this checking again for the same decl. We also @@ -881,7 +885,7 @@ Expr *DefaultArgumentExprRequest::evaluate(Evaluator &evaluator, return new (ctx) ErrorExpr(initExpr->getSourceRange(), ErrorType::get(ctx)); } - TypeChecker::checkInitializerErrorHandling(dc, initExpr); + TypeChecker::checkInitializerEffects(dc, initExpr); // Walk the checked initializer and contextualize any closures // we saw there. @@ -1136,8 +1140,7 @@ static void diagnoseClassWithoutInitializers(ClassDecl *classDecl) { { C, DeclBaseName::createConstructor(), { C.Id_from } }); auto result = TypeChecker::lookupMember(superclassDecl, superclassType, initFrom, - NameLookupFlags::ProtocolMembers | - NameLookupFlags::IgnoreAccessControl); + NameLookupFlags::IgnoreAccessControl); if (!result.empty() && !result.front().getValueDecl()->isImplicit()) diagDest = result.front().getValueDecl(); @@ -1657,7 +1660,7 @@ class DeclChecker : public DeclVisitor { PBD->getInitContext(i)); if (initContext) { // Check safety of error-handling in the declaration, too. - TypeChecker::checkInitializerErrorHandling(initContext, init); + TypeChecker::checkInitializerEffects(initContext, init); TypeChecker::contextualizeInitializer(initContext, init); } } @@ -1852,7 +1855,7 @@ class DeclChecker : public DeclVisitor { if (!computeAutomaticEnumValueKind(ED)) { DE.diagnose(ED->getInherited().front().getSourceRange().Start, diag::raw_type_not_literal_convertible, rawTy); - ED->getInherited().front().setInvalidType(getASTContext()); + ED->getInherited().front().setType(ErrorType::get(getASTContext())); } // We need at least one case to have a raw value. diff --git a/lib/Sema/TypeCheckError.cpp b/lib/Sema/TypeCheckEffects.cpp similarity index 81% rename from lib/Sema/TypeCheckError.cpp rename to lib/Sema/TypeCheckEffects.cpp index 92819337f75dc..4c595ca7f9eba 100644 --- a/lib/Sema/TypeCheckError.cpp +++ b/lib/Sema/TypeCheckEffects.cpp @@ -1,4 +1,4 @@ -//===--- TypeCheckError.cpp - Type Checking for Error Coverage ------------===// +//===--- TypeCheckEffects.cpp - Type Checking for Effects Coverage --------===// // // This source file is part of the Swift.org open source project // @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// // -// This file implements semantic analysis to ensure that errors are -// caught. +// This file implements semantic analysis to ensure that various effects (such +// as throwing and async) are properly handled. // //===----------------------------------------------------------------------===// @@ -184,9 +184,9 @@ enum ShouldRecurse_t : bool { }; /// A CRTP ASTWalker implementation that looks for interesting -/// nodes for error handling. +/// nodes for effects handling. template -class ErrorHandlingWalker : public ASTWalker { +class EffectsHandlingWalker : public ASTWalker { Impl &asImpl() { return *static_cast(this); } public: bool walkToDeclPre(Decl *D) override { @@ -221,7 +221,7 @@ class ErrorHandlingWalker : public ASTWalker { } else if (auto interpolated = dyn_cast(E)) { recurse = asImpl().checkInterpolatedStringLiteral(interpolated); } - // Error handling validation (via checkTopLevelErrorHandling) happens after + // Error handling validation (via checkTopLevelEffects) happens after // type checking. If an unchecked expression is still around, the code was // invalid. #define UNCHECKED_EXPR(KIND, BASE) \ @@ -253,7 +253,7 @@ class ErrorHandlingWalker : public ASTWalker { }; /// A potential reason why something might throw. -class PotentialReason { +class PotentialThrowReason { public: enum class Kind : uint8_t { /// The function throws unconditionally. @@ -275,21 +275,21 @@ class PotentialReason { Expr *TheExpression; Kind TheKind; - explicit PotentialReason(Kind kind) : TheKind(kind) {} + explicit PotentialThrowReason(Kind kind) : TheKind(kind) {} public: - static PotentialReason forRethrowsArgument(Expr *E) { - PotentialReason result(Kind::CallRethrowsWithExplicitThrowingArgument); + static PotentialThrowReason forRethrowsArgument(Expr *E) { + PotentialThrowReason result(Kind::CallRethrowsWithExplicitThrowingArgument); result.TheExpression = E; return result; } - static PotentialReason forDefaultArgument() { - return PotentialReason(Kind::CallRethrowsWithDefaultThrowingArgument); + static PotentialThrowReason forDefaultArgument() { + return PotentialThrowReason(Kind::CallRethrowsWithDefaultThrowingArgument); } - static PotentialReason forThrowingApply() { - return PotentialReason(Kind::CallThrows); + static PotentialThrowReason forThrowingApply() { + return PotentialThrowReason(Kind::CallThrows); } - static PotentialReason forThrow() { - return PotentialReason(Kind::Throw); + static PotentialThrowReason forThrow() { + return PotentialThrowReason(Kind::Throw); } Kind getKind() const { return TheKind; } @@ -321,16 +321,16 @@ enum class ThrowingKind { }; /// A type expressing the result of classifying whether a call or function -/// throws. +/// throws or is async. class Classification { bool IsInvalid = false; // The AST is malformed. Don't diagnose. bool IsAsync = false; ThrowingKind Result = ThrowingKind::None; - Optional Reason; + Optional Reason; public: Classification() : Result(ThrowingKind::None) {} - explicit Classification(ThrowingKind result, PotentialReason reason, + explicit Classification(ThrowingKind result, PotentialThrowReason reason, bool isAsync) : IsAsync(isAsync), Result(result) { if (result == ThrowingKind::Throws || @@ -341,7 +341,7 @@ class Classification { /// Return a classification saying that there's an unconditional /// throw site. - static Classification forThrow(PotentialReason reason, bool isAsync) { + static Classification forThrow(PotentialThrowReason reason, bool isAsync) { Classification result; result.Result = ThrowingKind::Throws; result.Reason = reason; @@ -363,7 +363,7 @@ class Classification { return result; } - static Classification forRethrowingOnly(PotentialReason reason) { + static Classification forRethrowingOnly(PotentialThrowReason reason) { Classification result; result.Result = ThrowingKind::RethrowingOnly; result.Reason = reason; @@ -378,7 +378,7 @@ class Classification { bool isInvalid() const { return IsInvalid; } ThrowingKind getResult() const { return Result; } - PotentialReason getThrowsReason() const { + PotentialThrowReason getThrowsReason() const { assert(getResult() == ThrowingKind::Throws || getResult() == ThrowingKind::RethrowingOnly); return *Reason; @@ -446,7 +446,7 @@ class ApplyClassifier { assert(args.size() > fnRef.getNumArgumentsForFullApply() && "partial application was throwing?"); - return Classification::forThrow(PotentialReason::forThrowingApply(), + return Classification::forThrow(PotentialThrowReason::forThrowingApply(), isAsync); } @@ -476,7 +476,7 @@ class ApplyClassifier { // Try to classify the implementation of functions that we have // local knowledge of. Classification result = - classifyThrowingFunctionBody(fnRef, PotentialReason::forThrowingApply()); + classifyThrowingFunctionBody(fnRef, PotentialThrowReason::forThrowingApply()); assert(result.getResult() != ThrowingKind::None && "body classification decided function was no-throw"); @@ -496,7 +496,7 @@ class ApplyClassifier { /// if the function is an autoclosure that simply doesn't throw at all. Classification classifyThrowingFunctionBody(const AbstractFunction &fn, - PotentialReason reason) { + PotentialThrowReason reason) { // If we're not checking a 'rethrows' context, we don't need to // distinguish between 'throws' and 'rethrows'. But don't even // trust 'throws' for autoclosures. @@ -517,7 +517,7 @@ class ApplyClassifier { } Classification classifyThrowingParameterBody(ParamDecl *param, - PotentialReason reason) { + PotentialThrowReason reason) { assert(param->getType() ->lookThroughAllOptionalTypes() ->castTo() @@ -542,7 +542,7 @@ class ApplyClassifier { } Classification classifyThrowingFunctionBody(AbstractFunctionDecl *fn, - PotentialReason reason) { + PotentialThrowReason reason) { // Functions can't be rethrowing-only unless they're defined // within the rethrows context. if (!isLocallyDefinedInRethrowsContext(fn) || !fn->hasBody()) @@ -556,7 +556,7 @@ class ApplyClassifier { } Classification classifyThrowingFunctionBody(AbstractClosureExpr *closure, - PotentialReason reason) { + PotentialThrowReason reason) { bool isAutoClosure = isa(closure); // Closures can't be rethrowing-only unless they're defined @@ -580,7 +580,7 @@ class ApplyClassifier { } class FunctionBodyClassifier - : public ErrorHandlingWalker { + : public EffectsHandlingWalker { ApplyClassifier &Self; public: bool IsInvalid = false; @@ -705,7 +705,7 @@ class ApplyClassifier { if (isa(arg)) { return classifyArgumentByType(arg->getType(), - PotentialReason::forDefaultArgument()); + PotentialThrowReason::forDefaultArgument()); } // If this argument is `nil` literal, it doesn't cause the call to throw. @@ -736,7 +736,7 @@ class ApplyClassifier { // parameter type included a throwing function type. return classifyArgumentByType( paramType, - PotentialReason::forRethrowsArgument(arg)); + PotentialThrowReason::forRethrowsArgument(arg)); } // FIXME: There's a case where we can end up with an ApplyExpr that @@ -751,7 +751,7 @@ class ApplyClassifier { if (!paramFnType || !paramFnType->isThrowing()) return Classification(); - PotentialReason reason = PotentialReason::forRethrowsArgument(arg); + PotentialThrowReason reason = PotentialThrowReason::forRethrowsArgument(arg); // TODO: partial applications? @@ -793,7 +793,7 @@ class ApplyClassifier { /// a throwing function in a way that is permitted to cause a /// 'rethrows' function to throw. static Classification classifyArgumentByType(Type paramType, - PotentialReason reason) { + PotentialThrowReason reason) { if (!paramType || paramType->hasError()) return Classification::forInvalidCode(); if (auto fnType = paramType->getAs()) { @@ -816,24 +816,12 @@ class ApplyClassifier { } }; -/// An error-handling context. +/// An context in which effects might be handled. class Context { public: enum class Kind : uint8_t { - /// A context that handles errors. - Handled, - - /// A non-throwing function. - NonThrowingFunction, - - /// A rethrowing function. - RethrowingFunction, - - /// A non-throwing autoclosure. - NonThrowingAutoClosure, - - /// A non-exhaustive catch within a non-throwing function. - NonExhaustiveCatch, + /// A context that potentially handles errors or async calls. + PotentiallyHandled, /// A default argument expression. DefaultArgument, @@ -858,26 +846,6 @@ class Context { }; private: - static Kind getKindForFunctionBody(Type type, unsigned numArgs) { - /// Determine whether calling a function of the specified type with the - /// specified number of arguments would throw. - if (!type) return Kind::Handled; - - assert(numArgs > 0); - while (true) { - auto fnType = type->getAs(); - if (!fnType) return Kind::Handled; - - if (fnType->getExtInfo().isThrowing()) - return Kind::Handled; - - if (--numArgs == 0) - return Kind::NonThrowingFunction; - - type = fnType->getResult(); - } - } - static Context getContextForPatternBinding(PatternBindingDecl *pbd) { if (!pbd->isStatic() && pbd->getDeclContext()->isTypeContext()) { return Context(Kind::IVarInitializer); @@ -887,29 +855,67 @@ class Context { } Kind TheKind; + Optional Function; + bool HandlesErrors = false; + bool HandlesAsync = false; + + /// Whether error-handling queries should ignore the function context, e.g., + /// for autoclosure and rethrows checks. + bool ErrorHandlingIgnoresFunction = false; + bool IsNonExhaustiveCatch = false; bool DiagnoseErrorOnTry = false; - DeclContext *RethrowsDC = nullptr; InterpolatedStringLiteralExpr *InterpolatedString = nullptr; - explicit Context(Kind kind) : TheKind(kind) {} + explicit Context(Kind kind) + : TheKind(kind), Function(None), HandlesErrors(false) { + assert(TheKind != Kind::PotentiallyHandled); + } + + explicit Context(bool handlesErrors, bool handlesAsync, + Optional function) + : TheKind(Kind::PotentiallyHandled), Function(function), + HandlesErrors(handlesErrors), HandlesAsync(handlesAsync) { } public: - static Context getHandled() { - return Context(Kind::Handled); + /// Whether this is a function that rethrows. + bool isRethrows() const { + if (!HandlesErrors) + return false; + + if (ErrorHandlingIgnoresFunction) + return false; + + if (!Function) + return false; + + auto fn = Function->getAbstractFunctionDecl(); + if (!fn) + return false; + + return fn->getAttrs().hasAttribute(); + } + + /// Whether this is an autoclosure. + bool isAutoClosure() const { + if (!Function) + return false; + + if (ErrorHandlingIgnoresFunction) + return false; + + auto closure = Function->getAbstractClosureExpr(); + if (!closure) + return false; + + return isa(closure); } static Context forTopLevelCode(TopLevelCodeDecl *D) { - // Top-level code implicitly handles errors. - return Context(Kind::Handled); + // Top-level code implicitly handles errors and 'async' calls. + return Context(/*handlesErrors=*/true, /*handlesAsync=*/true, None); } static Context forFunction(AbstractFunctionDecl *D) { - if (D->getAttrs().hasAttribute()) { - Context result(Kind::RethrowingFunction); - result.RethrowsDC = D; - return result; - } - // HACK: If the decl is the synthesized getter for a 'lazy' property, then // treat the context as a property initializer in order to produce a better // diagnostic; the only code we should be diagnosing on is within the @@ -926,8 +932,7 @@ class Context { } } - return Context(getKindForFunctionBody( - D->getInterfaceType(), D->getNumCurryLevels())); + return Context(D->hasThrows(), D->isAsyncContext(), AnyFunctionRef(D)); } static Context forDeferBody() { @@ -950,14 +955,17 @@ class Context { } static Context forClosure(AbstractClosureExpr *E) { - auto kind = getKindForFunctionBody(E->getType(), 1); - if (kind != Kind::Handled && isa(E)) - kind = Kind::NonThrowingAutoClosure; - return Context(kind); - } + // Determine whether the closure has throwing function type. + bool closureTypeThrows = true; + bool closureTypeIsAsync = true; + if (auto closureType = E->getType()) { + if (auto fnType = closureType->getAs()) { + closureTypeThrows = fnType->isThrowing(); + closureTypeIsAsync = fnType->isAsync(); + } + } - static Context forNonExhaustiveCatch(DoCatchStmt *S) { - return Context(Kind::NonExhaustiveCatch); + return Context(closureTypeThrows, closureTypeIsAsync, AnyFunctionRef(E)); } static Context forCatchPattern(CaseStmt *S) { @@ -978,11 +986,19 @@ class Context { return copy; } + /// Form a subcontext that handles all errors, e.g., for the body of a + /// do-catch with exhaustive catch clauses. + Context withHandlesErrors() const { + Context copy = *this; + copy.HandlesErrors = true; + copy.ErrorHandlingIgnoresFunction = true; + return copy; + } + Kind getKind() const { return TheKind; } bool handlesNothing() const { - return getKind() != Kind::Handled && - getKind() != Kind::RethrowingFunction; + return !HandlesErrors; } bool handles(ThrowingKind errorKind) const { switch (errorKind) { @@ -991,49 +1007,63 @@ class Context { // A call that's rethrowing-only can be handled by 'rethrows'. case ThrowingKind::RethrowingOnly: - return !handlesNothing(); + return HandlesErrors; // An operation that always throws can only be handled by an // all-handling context. case ThrowingKind::Throws: - return getKind() == Kind::Handled; + return HandlesErrors && !isRethrows(); } llvm_unreachable("bad error kind"); } - DeclContext *getRethrowsDC() const { return RethrowsDC; } + bool handlesAsync() const { + return HandlesAsync; + } + + DeclContext *getRethrowsDC() const { + if (!isRethrows()) + return nullptr; + + return Function->getAbstractFunctionDecl(); + } + InterpolatedStringLiteralExpr * getInterpolatedString() const { return InterpolatedString; } + void setNonExhaustiveCatch(bool value) { + IsNonExhaustiveCatch = value; + } + static void diagnoseThrowInIllegalContext(DiagnosticEngine &Diags, ASTNode node, - StringRef description) { + Kind kind) { if (auto *e = node.dyn_cast()) { if (isa(e)) { Diags.diagnose(e->getLoc(), diag::throwing_call_in_illegal_context, - description); + static_cast(kind)); return; } } Diags.diagnose(node.getStartLoc(), diag::throw_in_illegal_context, - description); + static_cast(kind)); } static void maybeAddRethrowsNote(DiagnosticEngine &Diags, SourceLoc loc, - const PotentialReason &reason) { + const PotentialThrowReason &reason) { switch (reason.getKind()) { - case PotentialReason::Kind::Throw: + case PotentialThrowReason::Kind::Throw: llvm_unreachable("should already have been covered"); - case PotentialReason::Kind::CallThrows: + case PotentialThrowReason::Kind::CallThrows: // Already fully diagnosed. return; - case PotentialReason::Kind::CallRethrowsWithExplicitThrowingArgument: + case PotentialThrowReason::Kind::CallRethrowsWithExplicitThrowingArgument: Diags.diagnose(reason.getThrowingArgument()->getLoc(), diag::because_rethrows_argument_throws); return; - case PotentialReason::Kind::CallRethrowsWithDefaultThrowingArgument: + case PotentialThrowReason::Kind::CallRethrowsWithDefaultThrowingArgument: Diags.diagnose(loc, diag::because_rethrows_default_argument_throws); return; } @@ -1041,7 +1071,7 @@ class Context { } void diagnoseUncoveredThrowSite(ASTContext &ctx, ASTNode E, - const PotentialReason &reason) { + const PotentialThrowReason &reason) { auto &Diags = ctx.Diags; auto message = diag::throwing_call_without_try; auto loc = E.getStartLoc(); @@ -1077,7 +1107,7 @@ class Context { // // Let's suggest couple of alternative fix-its // because complete context is unavailable. - if (reason.getKind() != PotentialReason::Kind::CallThrows) + if (reason.getKind() != PotentialThrowReason::Kind::CallThrows) return; Diags.diagnose(loc, diag::note_forgot_try) @@ -1090,7 +1120,7 @@ class Context { void diagnoseThrowInLegalContext(DiagnosticEngine &Diags, ASTNode node, bool isTryCovered, - const PotentialReason &reason, + const PotentialThrowReason &reason, Diag<> diagForThrow, Diag<> diagForThrowingCall, Diag<> diagForTrylessThrowingCall) { @@ -1103,8 +1133,7 @@ class Context { // Allow the diagnostic to fire on the 'try' if we don't have // anything else to say. if (isTryCovered && !reason.isRethrowsCall() && - (getKind() == Kind::NonThrowingFunction || - getKind() == Kind::NonExhaustiveCatch)) { + !isRethrows() && !isAutoClosure()) { DiagnoseErrorOnTry = true; return; } @@ -1119,91 +1148,123 @@ class Context { void diagnoseUnhandledThrowSite(DiagnosticEngine &Diags, ASTNode E, bool isTryCovered, - const PotentialReason &reason) { + const PotentialThrowReason &reason) { switch (getKind()) { - case Kind::Handled: - llvm_unreachable("throw site is handled!"); + case Kind::PotentiallyHandled: + if (IsNonExhaustiveCatch) { + diagnoseThrowInLegalContext(Diags, E, isTryCovered, reason, + diag::throw_in_nonexhaustive_catch, + diag::throwing_call_in_nonexhaustive_catch, + diag::tryless_throwing_call_in_nonexhaustive_catch); + return; + } - // TODO: Doug suggested that we could generate one error per - // non-throwing function with throw sites within it, possibly with - // notes for the throw sites. + if (isAutoClosure()) { + diagnoseThrowInLegalContext(Diags, E, isTryCovered, reason, + diag::throw_in_nonthrowing_autoclosure, + diag::throwing_call_in_nonthrowing_autoclosure, + diag::tryless_throwing_call_in_nonthrowing_autoclosure); + return; + } - case Kind::RethrowingFunction: - diagnoseThrowInLegalContext(Diags, E, isTryCovered, reason, - diag::throw_in_rethrows_function, - diag::throwing_call_in_rethrows_function, - diag::tryless_throwing_call_in_rethrows_function); - return; + if (isRethrows()) { + diagnoseThrowInLegalContext(Diags, E, isTryCovered, reason, + diag::throw_in_rethrows_function, + diag::throwing_call_in_rethrows_function, + diag::tryless_throwing_call_in_rethrows_function); + return; + } - case Kind::NonThrowingFunction: diagnoseThrowInLegalContext(Diags, E, isTryCovered, reason, diag::throw_in_nonthrowing_function, diag::throwing_call_unhandled, diag::tryless_throwing_call_unhandled); return; - case Kind::NonThrowingAutoClosure: - diagnoseThrowInLegalContext(Diags, E, isTryCovered, reason, - diag::throw_in_nonthrowing_autoclosure, - diag::throwing_call_in_nonthrowing_autoclosure, - diag::tryless_throwing_call_in_nonthrowing_autoclosure); + case Kind::EnumElementInitializer: + case Kind::GlobalVarInitializer: + case Kind::IVarInitializer: + case Kind::DefaultArgument: + case Kind::CatchPattern: + case Kind::CatchGuard: + case Kind::DeferBody: + diagnoseThrowInIllegalContext(Diags, E, getKind()); return; + } + llvm_unreachable("bad context kind"); + } - case Kind::NonExhaustiveCatch: - diagnoseThrowInLegalContext(Diags, E, isTryCovered, reason, - diag::throw_in_nonexhaustive_catch, - diag::throwing_call_in_nonexhaustive_catch, - diag::tryless_throwing_call_in_nonexhaustive_catch); + void diagnoseUnhandledTry(DiagnosticEngine &Diags, TryExpr *E) { + switch (getKind()) { + case Kind::PotentiallyHandled: + if (DiagnoseErrorOnTry) { + Diags.diagnose( + E->getTryLoc(), + IsNonExhaustiveCatch ? diag::try_unhandled_in_nonexhaustive_catch + : diag::try_unhandled); + } return; case Kind::EnumElementInitializer: - diagnoseThrowInIllegalContext(Diags, E, "an enum case raw value"); - return; - case Kind::GlobalVarInitializer: - diagnoseThrowInIllegalContext(Diags, E, "a global variable initializer"); - return; - case Kind::IVarInitializer: - diagnoseThrowInIllegalContext(Diags, E, "a property initializer"); - return; - case Kind::DefaultArgument: - diagnoseThrowInIllegalContext(Diags, E, "a default argument"); - return; - case Kind::CatchPattern: - diagnoseThrowInIllegalContext(Diags, E, "a catch pattern"); - return; - case Kind::CatchGuard: - diagnoseThrowInIllegalContext(Diags, E, "a catch guard expression"); - return; case Kind::DeferBody: - diagnoseThrowInIllegalContext(Diags, E, "a defer body"); + assert(!DiagnoseErrorOnTry); + // Diagnosed at the call sites. return; } llvm_unreachable("bad context kind"); } - void diagnoseUnhandledTry(DiagnosticEngine &Diags, TryExpr *E) { - switch (getKind()) { - case Kind::Handled: - case Kind::RethrowingFunction: - llvm_unreachable("try is handled!"); + void diagnoseUncoveredAsyncSite(ASTContext &ctx, ASTNode node) { + SourceRange highlight; + + // Generate more specific messages in some cases. + if (auto apply = dyn_cast_or_null(node.dyn_cast())) + highlight = apply->getSourceRange(); + + auto diag = diag::async_call_without_await; + if (isAutoClosure()) + diag = diag::async_call_without_await_in_autoclosure; + ctx.Diags.diagnose(node.getStartLoc(), diag) + .highlight(highlight); + } + + void diagnoseAsyncInIllegalContext(DiagnosticEngine &Diags, ASTNode node) { + if (auto *e = node.dyn_cast()) { + if (isa(e)) { + Diags.diagnose(e->getLoc(), diag::async_call_in_illegal_context, + static_cast(getKind())); + return; + } + } - case Kind::NonThrowingFunction: - if (DiagnoseErrorOnTry) - Diags.diagnose(E->getTryLoc(), diag::try_unhandled); + Diags.diagnose(node.getStartLoc(), diag::await_in_illegal_context, + static_cast(getKind())); + } + + void maybeAddAsyncNote(DiagnosticEngine &Diags) { + if (!Function) + return; + + auto func = dyn_cast_or_null(Function->getAbstractFunctionDecl()); + if (!func) return; - case Kind::NonExhaustiveCatch: - if (DiagnoseErrorOnTry) - Diags.diagnose(E->getTryLoc(), - diag::try_unhandled_in_nonexhaustive_catch); + addAsyncNotes(func); + } + + void diagnoseUnhandledAsyncSite(DiagnosticEngine &Diags, ASTNode node) { + switch (getKind()) { + case Kind::PotentiallyHandled: + Diags.diagnose(node.getStartLoc(), diag::async_in_nonasync_function, + node.isExpr(ExprKind::Await), isAutoClosure()); + maybeAddAsyncNote(Diags); return; - case Kind::NonThrowingAutoClosure: case Kind::EnumElementInitializer: case Kind::GlobalVarInitializer: case Kind::IVarInitializer: @@ -1211,23 +1272,20 @@ class Context { case Kind::CatchPattern: case Kind::CatchGuard: case Kind::DeferBody: - assert(!DiagnoseErrorOnTry); - // Diagnosed at the call sites. + diagnoseAsyncInIllegalContext(Diags, node); return; } - llvm_unreachable("bad context kind"); } }; /// A class to walk over a local context and validate the correctness /// of its error coverage. -class CheckErrorCoverage : public ErrorHandlingWalker { - friend class ErrorHandlingWalker; +class CheckEffectsCoverage : public EffectsHandlingWalker { + friend class EffectsHandlingWalker; ASTContext &Ctx; - ApplyClassifier Classifier; - + DeclContext *RethrowsDC = nullptr; Context CurContext; class ContextFlags { @@ -1288,15 +1346,15 @@ class CheckErrorCoverage : public ErrorHandlingWalker { /// An RAII object for restoring all the interesting state in an /// error-coverage. class ContextScope { - CheckErrorCoverage &Self; + CheckEffectsCoverage &Self; Context OldContext; DeclContext *OldRethrowsDC; ContextFlags OldFlags; ThrowingKind OldMaxThrowingKind; public: - ContextScope(CheckErrorCoverage &self, Optional newContext) + ContextScope(CheckEffectsCoverage &self, Optional newContext) : Self(self), OldContext(self.CurContext), - OldRethrowsDC(self.Classifier.RethrowsDC), + OldRethrowsDC(self.RethrowsDC), OldFlags(self.Flags), OldMaxThrowingKind(self.MaxThrowingKind) { if (newContext) self.CurContext = *newContext; @@ -1306,7 +1364,7 @@ class CheckErrorCoverage : public ErrorHandlingWalker { ContextScope &operator=(const ContextScope &) = delete; void enterSubFunction() { - Self.Classifier.RethrowsDC = nullptr; + Self.RethrowsDC = nullptr; } void enterTry() { @@ -1329,6 +1387,12 @@ class CheckErrorCoverage : public ErrorHandlingWalker { Self.MaxThrowingKind = ThrowingKind::None; } + void resetCoverageForAutoclosureBody() { + Self.Flags.clear(ContextFlags::IsAsyncCovered); + Self.Flags.clear(ContextFlags::HasAnyAsyncSite); + Self.Flags.clear(ContextFlags::HasAnyAwait); + } + void resetCoverageForDoCatch() { Self.Flags.reset(); Self.MaxThrowingKind = ThrowingKind::None; @@ -1372,19 +1436,19 @@ class CheckErrorCoverage : public ErrorHandlingWalker { ~ContextScope() { Self.CurContext = OldContext; - Self.Classifier.RethrowsDC = OldRethrowsDC; + Self.RethrowsDC = OldRethrowsDC; Self.Flags = OldFlags; Self.MaxThrowingKind = OldMaxThrowingKind; } }; public: - CheckErrorCoverage(ASTContext &ctx, Context initialContext) + CheckEffectsCoverage(ASTContext &ctx, Context initialContext) : Ctx(ctx), CurContext(initialContext), MaxThrowingKind(ThrowingKind::None) { if (auto rethrowsDC = initialContext.getRethrowsDC()) { - Classifier.RethrowsDC = rethrowsDC; + RethrowsDC = rethrowsDC; } } @@ -1416,14 +1480,15 @@ class CheckErrorCoverage : public ErrorHandlingWalker { ShouldRecurse_t checkAutoClosure(AutoClosureExpr *E) { ContextScope scope(*this, Context::forClosure(E)); scope.enterSubFunction(); + scope.resetCoverageForAutoclosureBody(); E->getBody()->walk(*this); scope.preserveCoverageFromAutoclosureBody(); return ShouldNotRecurse; } ThrowingKind checkExhaustiveDoBody(DoCatchStmt *S) { - // This is a handled context. - ContextScope scope(*this, Context::getHandled()); + // This is a context where errors are handled. + ContextScope scope(*this, CurContext.withHandlesErrors()); assert(!Flags.has(ContextFlags::IsInTry) && "do/catch within try?"); scope.resetCoverageForDoCatch(); @@ -1442,7 +1507,7 @@ class CheckErrorCoverage : public ErrorHandlingWalker { // If the enclosing context doesn't handle anything, use a // specialized diagnostic about non-exhaustive catches. if (CurContext.handlesNothing()) { - scope.refineLocalContext(Context::forNonExhaustiveCatch(S)); + CurContext.setNonExhaustiveCatch(true); } S->getBody()->walk(*this); @@ -1478,11 +1543,11 @@ class CheckErrorCoverage : public ErrorHandlingWalker { auto savedContext = CurContext; if (doThrowingKind != ThrowingKind::Throws && - CurContext.getKind() == Context::Kind::RethrowingFunction) { + CurContext.isRethrows()) { // If this catch clause is reachable at all, it's because a function - // parameter throws. So let's temporarily set our context to Handled so - // the catch body is allowed to throw. - CurContext = Context::getHandled(); + // parameter throws. So let's temporarily state that the body is allowed + // to throw. + CurContext = CurContext.withHandlesErrors(); } // The catch body just happens in the enclosing context. @@ -1494,7 +1559,9 @@ class CheckErrorCoverage : public ErrorHandlingWalker { ShouldRecurse_t checkApply(ApplyExpr *E) { // An apply expression is a potential throw site if the function throws. // But if the expression didn't type-check, suppress diagnostics. - auto classification = Classifier.classifyApply(E); + ApplyClassifier classifier; + classifier.RethrowsDC = RethrowsDC; + auto classification = classifier.classifyApply(E); checkThrowAsyncSite(E, /*requiresTry*/ true, classification); @@ -1528,8 +1595,8 @@ class CheckErrorCoverage : public ErrorHandlingWalker { // Check the inactive regions of a #if block to disable warnings that may // be due to platform specific code. struct ConservativeThrowChecker : public ASTWalker { - CheckErrorCoverage &CEC; - ConservativeThrowChecker(CheckErrorCoverage &CEC) : CEC(CEC) {} + CheckEffectsCoverage &CEC; + ConservativeThrowChecker(CheckEffectsCoverage &CEC) : CEC(CEC) {} Expr *walkToExprPost(Expr *E) override { if (isa(E)) @@ -1557,7 +1624,7 @@ class CheckErrorCoverage : public ErrorHandlingWalker { ShouldRecurse_t checkThrow(ThrowStmt *S) { checkThrowAsyncSite(S, /*requiresTry*/ false, - Classification::forThrow(PotentialReason::forThrow(), + Classification::forThrow(PotentialThrowReason::forThrow(), /*async*/false)); return ShouldRecurse; } @@ -1577,17 +1644,14 @@ class CheckErrorCoverage : public ErrorHandlingWalker { if (classification.isAsync()) { // Remember that we've seen an async call. Flags.set(ContextFlags::HasAnyAsyncSite); - + + // Diagnose async calls in a context that doesn't handle async. + if (!CurContext.handlesAsync()) { + CurContext.diagnoseUnhandledAsyncSite(Ctx.Diags, E); + } // Diagnose async calls that are outside of an await context. - if (!Flags.has(ContextFlags::IsAsyncCovered)) { - SourceRange highlight; - - // Generate more specific messages in some cases. - if (auto e = dyn_cast_or_null(E.dyn_cast())) - highlight = e->getSourceRange(); - - Ctx.Diags.diagnose(E.getStartLoc(), diag::async_call_without_await) - .highlight(highlight); + else if (!Flags.has(ContextFlags::IsAsyncCovered)) { + CurContext.diagnoseUncoveredAsyncSite(Ctx, E); } } @@ -1631,10 +1695,16 @@ class CheckErrorCoverage : public ErrorHandlingWalker { scope.enterAwait(); E->getSubExpr()->walk(*this); - - // Warn about 'await' expressions that weren't actually needed. - if (!Flags.has(ContextFlags::HasAnyAsyncSite)) - Ctx.Diags.diagnose(E->getAwaitLoc(), diag::no_async_in_await); + + // Warn about 'await' expressions that weren't actually needed, unless of + // course we're in a context that could never handle an 'async'. Then, we + // produce an error. + if (!Flags.has(ContextFlags::HasAnyAsyncSite)) { + if (CurContext.handlesAsync()) + Ctx.Diags.diagnose(E->getAwaitLoc(), diag::no_async_in_await); + else + CurContext.diagnoseUnhandledAsyncSite(Ctx.Diags, E); + } // Inform the parent of the walk that an 'await' exists here. scope.preserveCoverageFromAwaitOperand(); @@ -1665,7 +1735,7 @@ class CheckErrorCoverage : public ErrorHandlingWalker { ShouldRecurse_t checkForceTry(ForceTryExpr *E) { // Walk the operand. 'try!' handles errors. - ContextScope scope(*this, Context::getHandled()); + ContextScope scope(*this, CurContext.withHandlesErrors()); scope.enterTry(); E->getSubExpr()->walk(*this); @@ -1679,7 +1749,7 @@ class CheckErrorCoverage : public ErrorHandlingWalker { ShouldRecurse_t checkOptionalTry(OptionalTryExpr *E) { // Walk the operand. 'try?' handles errors. - ContextScope scope(*this, Context::getHandled()); + ContextScope scope(*this, CurContext.withHandlesErrors()); scope.enterTry(); E->getSubExpr()->walk(*this); @@ -1694,9 +1764,9 @@ class CheckErrorCoverage : public ErrorHandlingWalker { } // end anonymous namespace -void TypeChecker::checkTopLevelErrorHandling(TopLevelCodeDecl *code) { +void TypeChecker::checkTopLevelEffects(TopLevelCodeDecl *code) { auto &ctx = code->getDeclContext()->getASTContext(); - CheckErrorCoverage checker(ctx, Context::forTopLevelCode(code)); + CheckEffectsCoverage checker(ctx, Context::forTopLevelCode(code)); // In some language modes, we allow top-level code to omit 'try' marking. if (ctx.LangOpts.EnableThrowWithoutTry) @@ -1705,16 +1775,16 @@ void TypeChecker::checkTopLevelErrorHandling(TopLevelCodeDecl *code) { code->getBody()->walk(checker); } -void TypeChecker::checkFunctionErrorHandling(AbstractFunctionDecl *fn) { +void TypeChecker::checkFunctionEffects(AbstractFunctionDecl *fn) { #ifndef NDEBUG - PrettyStackTraceDecl debugStack("checking error handling for", fn); + PrettyStackTraceDecl debugStack("checking effects handling for", fn); #endif auto isDeferBody = isa(fn) && cast(fn)->isDeferBody(); auto context = isDeferBody ? Context::forDeferBody() : Context::forFunction(fn); auto &ctx = fn->getASTContext(); - CheckErrorCoverage checker(ctx, context); + CheckEffectsCoverage checker(ctx, context); // If this is a debugger function, suppress 'try' marking at the top level. if (fn->getAttrs().hasAttribute()) @@ -1728,14 +1798,14 @@ void TypeChecker::checkFunctionErrorHandling(AbstractFunctionDecl *fn) { superInit->walk(checker); } -void TypeChecker::checkInitializerErrorHandling(Initializer *initCtx, +void TypeChecker::checkInitializerEffects(Initializer *initCtx, Expr *init) { auto &ctx = initCtx->getASTContext(); - CheckErrorCoverage checker(ctx, Context::forInitializer(initCtx)); + CheckEffectsCoverage checker(ctx, Context::forInitializer(initCtx)); init->walk(checker); } -/// Check the correctness of error handling within the given enum +/// Check the correctness of effects within the given enum /// element's raw value expression. /// /// The syntactic restrictions on such expressions should make it @@ -1743,15 +1813,15 @@ void TypeChecker::checkInitializerErrorHandling(Initializer *initCtx, /// ensures correctness if those restrictions are ever loosened, /// perhaps accidentally, and (2) allows the verifier to assert that /// all calls have been checked. -void TypeChecker::checkEnumElementErrorHandling(EnumElementDecl *elt, Expr *E) { +void TypeChecker::checkEnumElementEffects(EnumElementDecl *elt, Expr *E) { auto &ctx = elt->getASTContext(); - CheckErrorCoverage checker(ctx, Context::forEnumElementInitializer(elt)); + CheckEffectsCoverage checker(ctx, Context::forEnumElementInitializer(elt)); E->walk(checker); } -void TypeChecker::checkPropertyWrapperErrorHandling( +void TypeChecker::checkPropertyWrapperEffects( PatternBindingDecl *binding, Expr *expr) { auto &ctx = binding->getASTContext(); - CheckErrorCoverage checker(ctx, Context::forPatternBinding(binding)); + CheckEffectsCoverage checker(ctx, Context::forPatternBinding(binding)); expr->walk(checker); } diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index 861ee21d75350..016345c4620bc 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -691,9 +691,9 @@ GenericSignatureRequest::evaluate(Evaluator &evaluator, // Gather requirements from the result type. auto *resultTypeRepr = [&subscr, &func]() -> TypeRepr * { if (subscr) { - return subscr->getElementTypeLoc().getTypeRepr(); + return subscr->getElementTypeRepr(); } else if (auto *FD = dyn_cast(func)) { - return FD->getBodyResultTypeLoc().getTypeRepr(); + return FD->getResultTypeRepr(); } else { return nullptr; } diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp index 6068b1a2c527f..1cddaedd4f562 100644 --- a/lib/Sema/TypeCheckNameLookup.cpp +++ b/lib/Sema/TypeCheckNameLookup.cpp @@ -113,8 +113,7 @@ namespace { // If this isn't a protocol member to be given special // treatment, just add the result. - if (!Options.contains(NameLookupFlags::ProtocolMembers) || - !isa(foundDC) || + if (!isa(foundDC) || isa(found) || isa(found) || (isa(found) && cast(found)->isOperator())) { @@ -124,9 +123,6 @@ namespace { assert(isa(foundDC)); - if (!Options.contains(NameLookupFlags::PerformConformanceCheck)) - return; - // If we found something within the protocol itself, and our // search began somewhere that is not in a protocol or extension // thereof, remap this declaration to the witness. @@ -210,11 +206,9 @@ namespace { static UnqualifiedLookupOptions convertToUnqualifiedLookupOptions(NameLookupOptions options) { - UnqualifiedLookupOptions newOptions; + UnqualifiedLookupOptions newOptions = UnqualifiedLookupFlags::AllowProtocolMembers; if (options.contains(NameLookupFlags::KnownPrivate)) newOptions |= UnqualifiedLookupFlags::KnownPrivate; - if (options.contains(NameLookupFlags::ProtocolMembers)) - newOptions |= UnqualifiedLookupFlags::AllowProtocolMembers; if (options.contains(NameLookupFlags::IgnoreAccessControl)) newOptions |= UnqualifiedLookupFlags::IgnoreAccessControl; if (options.contains(NameLookupFlags::IncludeOuterResults)) @@ -226,8 +220,26 @@ convertToUnqualifiedLookupOptions(NameLookupOptions options) { LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclNameRef name, SourceLoc loc, NameLookupOptions options) { - auto ulOptions = convertToUnqualifiedLookupOptions(options); auto &ctx = dc->getASTContext(); + // HACK: Qualified lookup cannot be allowed to synthesize CodingKeys because + // it would lead to a number of egregious cycles through + // QualifiedLookupRequest when we resolve the protocol conformance. Codable's + // magic has pushed its way so deeply into the compiler, we have to + // pessimistically force every nominal context above this one to synthesize + // it in the event the user needs it from e.g. a non-primary input. + // We can undo this if Codable's semantic content is divorced from its + // syntactic content - so we synthesize just enough to allow lookups to + // succeed, but don't force protocol conformances while we're doing it. + if (name.getBaseIdentifier() == ctx.Id_CodingKeys) { + for (auto typeCtx = dc->getInnermostTypeContext(); typeCtx != nullptr; + typeCtx = typeCtx->getParent()->getInnermostTypeContext()) { + if (auto *nominal = typeCtx->getSelfNominalTypeDecl()) { + nominal->synthesizeSemanticMembersIfNeeded(name.getFullName()); + } + } + } + + auto ulOptions = convertToUnqualifiedLookupOptions(options); auto descriptor = UnqualifiedLookupDescriptor(name, dc, loc, ulOptions); auto lookup = evaluateOrDefault(ctx.evaluator, UnqualifiedLookupRequest{descriptor}, {}); @@ -278,8 +290,7 @@ TypeChecker::lookupUnqualifiedType(DeclContext *dc, DeclNameRef name, auto lookup = evaluateOrDefault(ctx.evaluator, UnqualifiedLookupRequest{desc}, {}); - if (!lookup.allResults().empty() || - !options.contains(NameLookupFlags::ProtocolMembers)) + if (!lookup.allResults().empty()) return lookup; } @@ -302,18 +313,12 @@ LookupResult TypeChecker::lookupMember(DeclContext *dc, assert(type->mayHaveMembers()); LookupResult result; - NLOptions subOptions = NL_QualifiedDefault; + NLOptions subOptions = (NL_QualifiedDefault | NL_ProtocolMembers); if (options.contains(NameLookupFlags::KnownPrivate)) subOptions |= NL_KnownNonCascadingDependency; if (options.contains(NameLookupFlags::IgnoreAccessControl)) subOptions |= NL_IgnoreAccessControl; - if (options.contains(NameLookupFlags::ProtocolMembers)) - subOptions |= NL_ProtocolMembers; - - if (options.contains(NameLookupFlags::IncludeAttributeImplements)) - subOptions |= NL_IncludeAttributeImplements; - // We handle our own overriding/shadowing filtering. subOptions &= ~NL_RemoveOverridden; subOptions &= ~NL_RemoveNonVisible; @@ -387,12 +392,10 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc, // Look for members with the given name. SmallVector decls; - NLOptions subOptions = NL_QualifiedDefault | NL_OnlyTypes; + NLOptions subOptions = (NL_QualifiedDefault | NL_OnlyTypes | NL_ProtocolMembers); if (options.contains(NameLookupFlags::KnownPrivate)) subOptions |= NL_KnownNonCascadingDependency; - if (options.contains(NameLookupFlags::ProtocolMembers)) - subOptions |= NL_ProtocolMembers; if (options.contains(NameLookupFlags::IgnoreAccessControl)) subOptions |= NL_IgnoreAccessControl; @@ -434,21 +437,7 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc, if (auto assocType = dyn_cast(typeDecl)) { if (!type->is() && !type->isTypeParameter()) { - if (options.contains(NameLookupFlags::PerformConformanceCheck)) - inferredAssociatedTypes.push_back(assocType); - continue; - } - } - - // FIXME: This is a hack, we should be able to remove this entire 'if' - // statement once we learn how to deal with the circularity here. - if (auto *aliasDecl = dyn_cast(typeDecl)) { - if (isa(aliasDecl->getDeclContext()) && - !type->is() && - !type->isTypeParameter() && - aliasDecl->getUnderlyingType()->getCanonicalType() - ->hasTypeParameter() && - !options.contains(NameLookupFlags::PerformConformanceCheck)) { + inferredAssociatedTypes.push_back(assocType); continue; } } @@ -511,11 +500,6 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc, return result; } -LookupResult TypeChecker::lookupConstructors(DeclContext *dc, Type type, - NameLookupOptions options) { - return lookupMember(dc, type, DeclNameRef::createConstructor(), options); -} - unsigned TypeChecker::getCallEditDistance(DeclNameRef writtenName, DeclName correctedName, unsigned maxEditDistance) { diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index 6a5ec66b76cb1..1e5c3a571df6f 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -446,18 +446,12 @@ class ResolvePattern : public ASTVisitorgetArgument()) { - subPattern = getSubExprPattern(arg); - } - if (ume->getName().getBaseName().isSpecial()) return nullptr; return new (Context) EnumElementPattern(ume->getDotLoc(), ume->getNameLoc(), ume->getName(), - subPattern, ume); + nullptr, ume); } // Member syntax 'T.Element' forms a pattern if 'T' is an enum and the @@ -530,9 +524,10 @@ class ResolvePattern : public ASTVisitor(ce->getFn())) return nullptr; + if (isa(ce->getFn())) { + auto *P = visit(ce->getFn()); + if (!P) + return nullptr; + + auto *EEP = cast(P); + EEP->setSubPattern(getSubExprPattern(ce->getArg())); + EEP->setUnresolvedOriginalExpr(ce); + + return P; + } + SmallVector components; if (!ExprToIdentTypeRepr(components, Context).visit(ce->getFn())) return nullptr; diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index e68a7b2d095fa..b3b57e5dc8fa9 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -850,7 +850,14 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache, Type openedFullWitnessType; Type reqType, openedFullReqType; - auto reqSig = req->getInnermostDeclContext()->getGenericSignatureOfContext(); + GenericSignature reqSig = proto->getGenericSignature(); + if (auto *funcDecl = dyn_cast(req)) { + if (funcDecl->isGeneric()) + reqSig = funcDecl->getGenericSignature(); + } else if (auto *subscriptDecl = dyn_cast(req)) { + if (subscriptDecl->isGeneric()) + reqSig = subscriptDecl->getGenericSignature(); + } ClassDecl *covariantSelf = nullptr; if (witness->getDeclContext()->getExtendedProtocolDecl()) { @@ -1105,16 +1112,25 @@ WitnessChecker::WitnessChecker(ASTContext &ctx, ProtocolDecl *proto, void WitnessChecker::lookupValueWitnessesViaImplementsAttr( ValueDecl *req, SmallVector &witnesses) { - auto lookupOptions = defaultMemberTypeLookupOptions; - lookupOptions -= NameLookupFlags::PerformConformanceCheck; - lookupOptions |= NameLookupFlags::IncludeAttributeImplements; - auto candidates = TypeChecker::lookupMember(DC, Adoptee, req->createNameRef(), - lookupOptions); - for (auto candidate : candidates) { - if (witnessHasImplementsAttrForExactRequirement(candidate.getValueDecl(), req)) { - witnesses.push_back(candidate.getValueDecl()); - } + + auto name = req->createNameRef(); + auto *nominal = Adoptee->getAnyNominal(); + + NLOptions subOptions = (NL_ProtocolMembers | NL_IncludeAttributeImplements); + + nominal->synthesizeSemanticMembersIfNeeded(name.getFullName()); + + SmallVector lookupResults; + DC->lookupQualified(nominal, name, subOptions, lookupResults); + + for (auto decl : lookupResults) { + if (!isa(decl->getDeclContext())) + if (witnessHasImplementsAttrForExactRequirement(decl, req)) + witnesses.push_back(decl); } + + removeOverriddenDecls(witnesses); + removeShadowedDecls(witnesses, DC); } SmallVector @@ -1147,23 +1163,34 @@ WitnessChecker::lookupValueWitnesses(ValueDecl *req, bool *ignoringNames) { } } else { // Variable/function/subscript requirements. - auto lookupOptions = defaultMemberTypeLookupOptions; - lookupOptions -= NameLookupFlags::PerformConformanceCheck; - - auto candidates = TypeChecker::lookupMember(DC, Adoptee, reqName, - lookupOptions); + auto *nominal = Adoptee->getAnyNominal(); + nominal->synthesizeSemanticMembersIfNeeded(reqName.getFullName()); + + SmallVector lookupResults; + bool addedAny = false; + DC->lookupQualified(nominal, reqName, NL_ProtocolMembers, lookupResults); + for (auto *decl : lookupResults) { + if (!isa(decl->getDeclContext())) { + witnesses.push_back(decl); + addedAny = true; + } + }; // If we didn't find anything with the appropriate name, look // again using only the base name. - if (candidates.empty() && ignoringNames) { - candidates = TypeChecker::lookupMember(DC, Adoptee, reqBaseName, - lookupOptions); + if (!addedAny && ignoringNames) { + lookupResults.clear(); + DC->lookupQualified(nominal, reqBaseName, NL_ProtocolMembers, lookupResults); + for (auto *decl : lookupResults) { + if (!isa(decl->getDeclContext())) + witnesses.push_back(decl); + } + *ignoringNames = true; } - for (auto candidate : candidates) { - witnesses.push_back(candidate.getValueDecl()); - } + removeOverriddenDecls(witnesses); + removeShadowedDecls(witnesses, DC); } return witnesses; @@ -2066,13 +2093,12 @@ SourceLoc OptionalAdjustment::getOptionalityLoc(ValueDecl *witness) const { // For a function, use the result type. if (auto func = dyn_cast(witness)) { return getOptionalityLoc( - func->getBodyResultTypeLoc().getTypeRepr()); + func->getResultTypeRepr()); } // For a subscript, use the element type. if (auto subscript = dyn_cast(witness)) { - return getOptionalityLoc( - subscript->getElementTypeLoc().getTypeRepr()); + return getOptionalityLoc(subscript->getElementTypeRepr()); } // Otherwise, we have a variable. @@ -3768,9 +3794,10 @@ ResolveWitnessResult ConformanceChecker::resolveWitnessViaDefault( # pragma mark Type witness resolution -CheckTypeWitnessResult swift::checkTypeWitness(Type type, - AssociatedTypeDecl *assocType, - NormalProtocolConformance *Conf) { +CheckTypeWitnessResult +swift::checkTypeWitness(Type type, AssociatedTypeDecl *assocType, + const NormalProtocolConformance *Conf, + SubstOptions options) { if (type->hasError()) return ErrorType::get(assocType->getASTContext()); @@ -3784,13 +3811,19 @@ CheckTypeWitnessResult swift::checkTypeWitness(Type type, : type; if (auto superclass = genericSig->getSuperclassBound(depTy)) { - // If the superclass has a type parameter, substitute in known type - // witnesses. if (superclass->hasTypeParameter()) { - const auto subMap = SubstitutionMap::getProtocolSubstitutions( - proto, Conf->getType(), ProtocolConformanceRef(Conf)); + // Replace type parameters with other known or tentative type witnesses. + superclass = superclass.subst( + [&](SubstitutableType *type) { + if (type->isEqual(proto->getSelfInterfaceType())) + return Conf->getType(); - superclass = superclass.subst(subMap); + return Type(); + }, + LookUpConformanceInModule(dc->getParentModule()), options); + + if (superclass->hasTypeParameter()) + superclass = dc->mapTypeIntoContext(superclass); } if (!superclass->isExactSuperclassOf(contextType)) return superclass; @@ -3862,36 +3895,86 @@ ResolveWitnessResult ConformanceChecker::resolveTypeWitnessViaLookup( abort(); } + NLOptions subOptions = (NL_QualifiedDefault | NL_OnlyTypes | NL_ProtocolMembers); + // Look for a member type with the same name as the associated type. - auto candidates = TypeChecker::lookupMemberType( - DC, Adoptee, assocType->createNameRef(), - NameLookupFlags::ProtocolMembers); + SmallVector candidates; + + DC->lookupQualified(Adoptee->getAnyNominal(), + assocType->createNameRef(), + subOptions, candidates); // If there aren't any candidates, we're done. - if (!candidates) { + if (candidates.empty()) { return ResolveWitnessResult::Missing; } // Determine which of the candidates is viable. SmallVector viable; SmallVector, 2> nonViable; + SmallPtrSet viableTypes; + for (auto candidate : candidates) { - // Skip nested generic types. - if (auto *genericDecl = dyn_cast(candidate.Member)) - if (genericDecl->isGeneric()) - continue; + auto *typeDecl = cast(candidate); + + // Skip other associated types. + if (isa(typeDecl)) + continue; + + auto *genericDecl = cast(typeDecl); + + // If the declaration has generic parameters, it cannot witness an + // associated type. + if (genericDecl->isGeneric()) + continue; + + // As a narrow fix for a source compatibility issue with SwiftUI's + // swiftinterface, allow the conformance if the underlying type of + // the typealias is Never. + // + // FIXME: This should be conditionalized on a new language version. + bool skipRequirementCheck = false; + if (auto *typeAliasDecl = dyn_cast(typeDecl)) { + if (typeAliasDecl->getUnderlyingType()->isUninhabited()) + skipRequirementCheck = true; + } // Skip typealiases with an unbound generic type as their underlying type. - if (auto *typeAliasDecl = dyn_cast(candidate.Member)) + if (auto *typeAliasDecl = dyn_cast(typeDecl)) if (typeAliasDecl->getDeclaredInterfaceType()->is()) continue; + // Skip dependent protocol typealiases. + // + // FIXME: This should not be necessary. + if (auto *typeAliasDecl = dyn_cast(typeDecl)) { + if (isa(typeAliasDecl->getDeclContext()) && + typeAliasDecl->getUnderlyingType()->getCanonicalType() + ->hasTypeParameter()) { + continue; + } + } + + // If the type comes from a constrained extension or has a 'where' + // clause, check those requirements now. + if (!skipRequirementCheck && + !TypeChecker::checkContextualRequirements(genericDecl, Adoptee, + SourceLoc(), DC)) { + continue; + } + + auto memberType = TypeChecker::substMemberTypeWithBase(DC->getParentModule(), + typeDecl, Adoptee); + + if (!viableTypes.insert(memberType->getCanonicalType()).second) + continue; + // Check this type against the protocol requirements. if (auto checkResult = - checkTypeWitness(candidate.MemberType, assocType, Conformance)) { - nonViable.push_back({candidate.Member, checkResult}); + checkTypeWitness(memberType, assocType, Conformance)) { + nonViable.push_back({typeDecl, checkResult}); } else { - viable.push_back(candidate); + viable.push_back({typeDecl, memberType, nullptr}); } } @@ -3908,8 +3991,6 @@ ResolveWitnessResult ConformanceChecker::resolveTypeWitnessViaLookup( // If there is a single viable candidate, form a substitution for it. if (viable.size() == 1) { auto interfaceType = viable.front().MemberType; - if (interfaceType->hasArchetype()) - interfaceType = interfaceType->mapTypeOutOfContext(); recordTypeWitness(assocType, interfaceType, viable.front().Member); return ResolveWitnessResult::Success; } @@ -5073,16 +5154,20 @@ diagnoseMissingAppendInterpolationMethod(NominalTypeDecl *typeDecl) { static bool hasValidMethod(NominalTypeDecl *typeDecl, SmallVectorImpl &invalid) { - auto type = typeDecl->getDeclaredType(); + NLOptions subOptions = NL_QualifiedDefault; + subOptions |= NL_ProtocolMembers; + DeclNameRef baseName(typeDecl->getASTContext().Id_appendInterpolation); - auto lookupOptions = defaultMemberTypeLookupOptions; - lookupOptions -= NameLookupFlags::PerformConformanceCheck; - for (auto resultEntry : - TypeChecker::lookupMember(typeDecl, type, baseName, lookupOptions)) { - auto method = dyn_cast(resultEntry.getValueDecl()); + SmallVector lookupResults; + typeDecl->lookupQualified(typeDecl, baseName, subOptions, lookupResults); + for (auto decl : lookupResults) { + auto method = dyn_cast(decl); if (!method) continue; - + + if (isa(method->getDeclContext())) + continue; + if (method->isStatic()) { invalid.emplace_back(method, Reason::Static); continue; @@ -5124,11 +5209,13 @@ diagnoseMissingAppendInterpolationMethod(NominalTypeDecl *typeDecl) { break; case InvalidMethod::Reason::ReturnType: - C.Diags - .diagnose(invalidMethod.method->getBodyResultTypeLoc().getLoc(), - diag::append_interpolation_void_or_discardable) - .fixItInsert(invalidMethod.method->getStartLoc(), - "@discardableResult "); + if (auto *const repr = invalidMethod.method->getResultTypeRepr()) { + C.Diags + .diagnose(repr->getLoc(), + diag::append_interpolation_void_or_discardable) + .fixItInsert(invalidMethod.method->getStartLoc(), + "@discardableResult "); + } break; case InvalidMethod::Reason::AccessControl: @@ -5691,6 +5778,8 @@ TypeChecker::deriveTypeWitness(DeclContext *DC, switch (*knownKind) { case KnownProtocolKind::RawRepresentable: return std::make_pair(derived.deriveRawRepresentable(AssocType), nullptr); + case KnownProtocolKind::CaseIterable: + return std::make_pair(derived.deriveCaseIterable(AssocType), nullptr); case KnownProtocolKind::Differentiable: return derived.deriveDifferentiable(AssocType); default: diff --git a/lib/Sema/TypeCheckProtocol.h b/lib/Sema/TypeCheckProtocol.h index badf16810d0b7..d51341300ac48 100644 --- a/lib/Sema/TypeCheckProtocol.h +++ b/lib/Sema/TypeCheckProtocol.h @@ -96,7 +96,8 @@ class CheckTypeWitnessResult { /// \returns an empty result on success, or a description of the error. CheckTypeWitnessResult checkTypeWitness(Type type, AssociatedTypeDecl *assocType, - NormalProtocolConformance *Conf); + const NormalProtocolConformance *Conf, + SubstOptions options = None); /// Describes the means of inferring an abstract type witness. enum class AbstractTypeWitnessKind : uint8_t { diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp index 21fe9d350ff71..23a6957b930ef 100644 --- a/lib/Sema/TypeCheckProtocolInference.cpp +++ b/lib/Sema/TypeCheckProtocolInference.cpp @@ -595,15 +595,21 @@ AssociatedTypeInference::inferTypeWitnessesViaAssociatedType( defaultName = DeclNameRef(getASTContext().getIdentifier(defaultNameStr)); } + NLOptions subOptions = (NL_QualifiedDefault | + NL_OnlyTypes | + NL_ProtocolMembers); + // Look for types with the given default name that have appropriate // @_implements attributes. + SmallVector lookupResults; + dc->lookupQualified(adoptee->getAnyNominal(), defaultName, + subOptions, lookupResults); + InferredAssociatedTypesByWitnesses result; - auto lookupOptions = defaultMemberTypeLookupOptions; - lookupOptions -= NameLookupFlags::PerformConformanceCheck; - for (auto candidate : - TypeChecker::lookupMember(dc, adoptee, defaultName, lookupOptions)) { + + for (auto decl : lookupResults) { // We want type declarations. - auto typeDecl = dyn_cast(candidate.getValueDecl()); + auto typeDecl = dyn_cast(decl); if (!typeDecl || isa(typeDecl)) continue; @@ -1166,6 +1172,7 @@ AssociatedTypeDecl *AssociatedTypeInference::completeSolution( // Check each abstract type witness we computed against the generic // requirements on the corresponding associated type. + const auto substOptions = getSubstOptionsWithCurrentTypeWitnesses(); for (const auto &witness : abstractTypeWitnesses) { Type type = witness.getType(); if (type->hasTypeParameter()) { @@ -1178,8 +1185,7 @@ AssociatedTypeDecl *AssociatedTypeInference::completeSolution( return Type(); }, - LookUpConformanceInModule(dc->getParentModule()), - getSubstOptionsWithCurrentTypeWitnesses()); + LookUpConformanceInModule(dc->getParentModule()), substOptions); // If the substitution produced an error, we're done. if (type->hasError()) @@ -1188,8 +1194,8 @@ AssociatedTypeDecl *AssociatedTypeInference::completeSolution( type = dc->mapTypeIntoContext(type); } - if (const auto &failed = - checkTypeWitness(type, witness.getAssocType(), conformance)) { + if (const auto &failed = checkTypeWitness(type, witness.getAssocType(), + conformance, substOptions)) { // We failed to satisfy a requirement. If this is a default type // witness failure and we haven't seen one already, write it down. if (witness.getKind() == AbstractTypeWitnessKind::Default && diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 5de97e3012634..102b11d5fed94 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -691,7 +691,8 @@ class StmtChecker : public StmtVisitor { // is equivalent to what we have here. if (LS->getStartLoc().isValid() && sourceFile && SC.getASTContext().LangOpts.EnableASTScopeLookup && - !SC.getASTContext().Diags.hadAnyError()) { + !SC.getASTContext().Diags.hadAnyError() && + !SC.LeaveBraceStmtBodyUnchecked) { // The labeled statements from ASTScope lookup have the // innermost labeled statement first, so reverse it to // match the data structure maintained here. @@ -1698,7 +1699,7 @@ static Type getFunctionBuilderType(FuncDecl *FD) { bool TypeChecker::typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD) { auto res = evaluateOrDefault(AFD->getASTContext().evaluator, TypeCheckFunctionBodyRequest{AFD}, true); - TypeChecker::checkFunctionErrorHandling(AFD); + TypeChecker::checkFunctionEffects(AFD); TypeChecker::computeCaptures(AFD); return res; } @@ -1754,19 +1755,21 @@ static bool checkSuperInit(ConstructorDecl *fromCtor, // For an implicitly generated super.init() call, make sure there's // only one designated initializer. if (implicitlyGenerated) { - auto superclassTy = ctor->getDeclContext()->getDeclaredInterfaceType(); - auto lookupOptions = defaultConstructorLookupOptions; - lookupOptions |= NameLookupFlags::KnownPrivate; - - // If a constructor is only visible as a witness for a protocol - // requirement, it must be an invalid override. Also, protocol - // extensions cannot yet define designated initializers. - lookupOptions -= NameLookupFlags::ProtocolMembers; - lookupOptions -= NameLookupFlags::PerformConformanceCheck; - - for (auto member : TypeChecker::lookupConstructors(fromCtor, superclassTy, - lookupOptions)) { - auto superclassCtor = dyn_cast(member.getValueDecl()); + auto *dc = ctor->getDeclContext(); + auto *superclassDecl = dc->getSelfClassDecl(); + + superclassDecl->synthesizeSemanticMembersIfNeeded( + DeclBaseName::createConstructor()); + + NLOptions subOptions = NL_QualifiedDefault | NL_KnownNonCascadingDependency; + + SmallVector lookupResults; + fromCtor->lookupQualified(superclassDecl, + DeclNameRef::createConstructor(), + subOptions, lookupResults); + + for (auto decl : lookupResults) { + auto superclassCtor = dyn_cast(decl); if (!superclassCtor || !superclassCtor->isDesignatedInit() || superclassCtor == ctor) continue; @@ -2152,7 +2155,7 @@ void TypeChecker::typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD) { BraceStmt *Body = TLCD->getBody(); StmtChecker(TLCD).typeCheckStmt(Body); TLCD->setBody(Body); - checkTopLevelErrorHandling(TLCD); + checkTopLevelEffects(TLCD); performTopLevelDeclDiagnostics(TLCD); } diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index eca917211a065..78c4d0b0066b8 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -1881,7 +1881,7 @@ static AccessorDecl *createGetterPrototype(AbstractStorageDecl *storage, /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), genericParams, getterParams, - TypeLoc(), + Type(), storage->getDeclContext()); // If we're stealing the 'self' from a lazy initializer, set it now. @@ -1930,7 +1930,7 @@ static AccessorDecl *createSetterPrototype(AbstractStorageDecl *storage, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None, /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), genericParams, params, - TypeLoc(), + Type(), storage->getDeclContext()); if (isMutating) @@ -2032,7 +2032,7 @@ createCoroutineAccessorPrototype(AbstractStorageDecl *storage, auto *params = buildIndexForwardingParamList(storage, {}, ctx); // Coroutine accessors always return (). - Type retTy = TupleType::getEmpty(ctx); + const Type retTy = TupleType::getEmpty(ctx); GenericParamList *genericParams = createAccessorGenericParams(storage); @@ -2041,7 +2041,7 @@ createCoroutineAccessorPrototype(AbstractStorageDecl *storage, kind, storage, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None, /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), - genericParams, params, TypeLoc::withoutLoc(retTy), dc); + genericParams, params, retTy, dc); if (isMutating) accessor->setSelfAccessKind(SelfAccessKind::Mutating); @@ -2491,7 +2491,7 @@ static void typeCheckSynthesizedWrapperInitializer( dyn_cast_or_null(pbd->getInitContext(i))) { TypeChecker::contextualizeInitializer(initializerContext, initializer); } - TypeChecker::checkPropertyWrapperErrorHandling(pbd, initializer); + TypeChecker::checkPropertyWrapperEffects(pbd, initializer); } static PropertyWrapperMutability::Value diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index c28005a603b29..a3845b07b62ae 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -197,7 +197,7 @@ Type TypeResolution::resolveDependentMemberType( TypoCorrectionResults corrections(ref->getNameRef(), ref->getNameLoc()); TypeChecker::performTypoCorrection(DC, DeclRefKind::Ordinary, MetatypeType::get(baseTy), - NameLookupFlags::ProtocolMembers, + defaultMemberLookupOptions, corrections, builder); // Check whether we have a single type result. @@ -597,26 +597,18 @@ static bool isPointerToVoid(ASTContext &Ctx, Type Ty, bool &IsMutable) { return BGT->getGenericArgs().front()->isVoid(); } -static Type checkContextualRequirements(Type type, - SourceLoc loc, - DeclContext *dc) { - // Even if the type is not generic, it might be inside of a generic - // context, so we need to check requirements. - GenericTypeDecl *decl; - Type parentTy; - if (auto *aliasTy = dyn_cast(type.getPointer())) { - decl = aliasTy->getDecl(); - parentTy = aliasTy->getParent(); - } else if (auto *nominalTy = type->getAs()) { - decl = nominalTy->getDecl(); - parentTy = nominalTy->getParent(); - } else { - return type; - } - +/// Even if the type is not generic, it might be inside of a generic +/// context or have a free-standing 'where' clause, so we need to +/// those check requirements too. +/// +/// Return true on success. +bool TypeChecker::checkContextualRequirements(GenericTypeDecl *decl, + Type parentTy, + SourceLoc loc, + DeclContext *dc) { if (!parentTy || parentTy->hasUnboundGenericType() || parentTy->hasTypeVariable()) { - return type; + return true; } auto &ctx = dc->getASTContext(); @@ -631,7 +623,7 @@ static Type checkContextualRequirements(Type type, else if (ext && ext->isConstrainedExtension()) noteLoc = ext->getLoc(); else - return type; + return true; if (noteLoc.isInvalid()) noteLoc = loc; @@ -640,15 +632,18 @@ static Type checkContextualRequirements(Type type, const auto subMap = parentTy->getContextSubstitutions(decl->getDeclContext()); const auto genericSig = decl->getGenericSignature(); if (!genericSig) { - ctx.Diags.diagnose(loc, diag::recursive_decl_reference, - decl->getDescriptiveKind(), decl->getName()); - decl->diagnose(diag::kind_declared_here, DescriptiveDeclKind::Type); - return ErrorType::get(ctx); + if (loc.isValid()) { + ctx.Diags.diagnose(loc, diag::recursive_decl_reference, + decl->getDescriptiveKind(), decl->getName()); + decl->diagnose(diag::kind_declared_here, DescriptiveDeclKind::Type); + } + return false; } const auto result = TypeChecker::checkGenericArguments( - dc, loc, noteLoc, type, + dc, loc, noteLoc, + decl->getDeclaredInterfaceType(), genericSig->getGenericParams(), genericSig->getRequirements(), QueryTypeSubstitutionMap{subMap}); @@ -656,9 +651,9 @@ static Type checkContextualRequirements(Type type, switch (result) { case RequirementCheckResult::Failure: case RequirementCheckResult::SubstitutionFailure: - return ErrorType::get(ctx); + return false; case RequirementCheckResult::Success: - return type; + return true; } llvm_unreachable("invalid requirement check type"); } @@ -709,7 +704,22 @@ static Type applyGenericArguments(Type type, TypeResolution resolution, if (resolution.getStage() == TypeResolutionStage::Structural) return type; - return checkContextualRequirements(type, loc, dc); + GenericTypeDecl *decl; + Type parentTy; + if (auto *aliasTy = dyn_cast(type.getPointer())) { + decl = aliasTy->getDecl(); + parentTy = aliasTy->getParent(); + } else if (auto *nominalTy = type->getAs()) { + decl = nominalTy->getDecl(); + parentTy = nominalTy->getParent(); + } else { + return type; + } + + if (TypeChecker::checkContextualRequirements(decl, parentTy, loc, dc)) + return type; + + return ErrorType::get(resolution.getASTContext()); } if (type->hasError()) { @@ -1489,8 +1499,6 @@ static Type resolveNestedIdentTypeComponent(TypeResolution resolution, NameLookupOptions lookupOptions = defaultMemberLookupOptions; if (isKnownNonCascading) lookupOptions |= NameLookupFlags::KnownPrivate; - if (options.is(TypeResolverContext::ExtensionBinding)) - lookupOptions -= NameLookupFlags::ProtocolMembers; LookupTypeResult memberTypes; if (parentTy->mayHaveMembers()) memberTypes = TypeChecker::lookupMemberType(DC, parentTy, @@ -2070,7 +2078,7 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs, static const TypeAttrKind FunctionAttrs[] = { TAK_convention, TAK_pseudogeneric, TAK_callee_owned, TAK_callee_guaranteed, TAK_noescape, TAK_autoclosure, - TAK_differentiable, TAK_escaping, TAK_yield_once, TAK_yield_many + TAK_differentiable, TAK_escaping, TAK_yield_once, TAK_yield_many, TAK_async }; auto checkUnsupportedAttr = [&](TypeAttrKind attr) { @@ -2216,7 +2224,8 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs, // [TODO: Store-SIL-Clang-type] auto extInfo = SILFunctionType::ExtInfoBuilder( rep, attrs.has(TAK_pseudogeneric), - attrs.has(TAK_noescape), diffKind, nullptr) + attrs.has(TAK_noescape), attrs.has(TAK_async), + diffKind, nullptr) .build(); ty = resolveSILFunctionType(fnRepr, options, coroutineKind, extInfo, @@ -2462,6 +2471,13 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs, attrs.clearAttribute(TAK_dynamic_self); } + // In SIL *only*, allow @async to specify an async function + if ((options & TypeResolutionFlags::SILMode) && attrs.has(TAK_async)) { + if (fnRepr != nullptr) { + attrs.clearAttribute(TAK_async); + } + } + for (unsigned i = 0; i != TypeAttrKind::TAK_Count; ++i) if (attrs.has((TypeAttrKind)i)) { diagnoseInvalid(repr, attrs.getLoc((TypeAttrKind)i), diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index cefdf503fc1f6..ddc5711d4ed5e 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -188,27 +188,12 @@ inline TypeCheckExprOptions operator|(TypeCheckExprFlags flag1, enum class NameLookupFlags { /// Whether we know that this lookup is always a private dependency. KnownPrivate = 0x01, - /// Whether name lookup should be able to find protocol members. - ProtocolMembers = 0x02, - /// Whether we should map the requirement to the witness if we - /// find a protocol member and the base type is a concrete type. - /// - /// If this is not set but ProtocolMembers is set, we will - /// find protocol extension members, but not protocol requirements - /// that do not yet have a witness (such as inferred associated - /// types, or witnesses for derived conformances). - PerformConformanceCheck = 0x04, - /// Whether to perform 'dynamic' name lookup that finds @objc - /// members of any class or protocol. - DynamicLookup = 0x08, /// Whether to ignore access control for this lookup, allowing inaccessible /// results to be returned. IgnoreAccessControl = 0x10, /// Whether to include results from outside the innermost scope that has a /// result. IncludeOuterResults = 0x20, - /// Whether to consider synonyms declared through @_implements(). - IncludeAttributeImplements = 0x40, }; /// A set of options that control name lookup. @@ -220,24 +205,13 @@ inline NameLookupOptions operator|(NameLookupFlags flag1, } /// Default options for member name lookup. -const NameLookupOptions defaultMemberLookupOptions - = NameLookupFlags::ProtocolMembers | - NameLookupFlags::PerformConformanceCheck; - -/// Default options for constructor lookup. -const NameLookupOptions defaultConstructorLookupOptions - = NameLookupFlags::ProtocolMembers | - NameLookupFlags::PerformConformanceCheck; +const NameLookupOptions defaultMemberLookupOptions; /// Default options for member type lookup. -const NameLookupOptions defaultMemberTypeLookupOptions - = NameLookupFlags::ProtocolMembers | - NameLookupFlags::PerformConformanceCheck; +const NameLookupOptions defaultMemberTypeLookupOptions; /// Default options for unqualified name lookup. -const NameLookupOptions defaultUnqualifiedLookupOptions - = NameLookupFlags::ProtocolMembers | - NameLookupFlags::PerformConformanceCheck; +const NameLookupOptions defaultUnqualifiedLookupOptions; /// Describes the result of comparing two entities, of which one may be better /// or worse than the other, or they are unordered. @@ -315,7 +289,11 @@ Type getOptionalType(SourceLoc loc, Type elementType); /// Bind an UnresolvedDeclRefExpr by performing name lookup and /// returning the resultant expression. Context is the DeclContext used /// for the lookup. -Expr *resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *Context); +/// +/// \param replaceInvalidRefsWithErrors Indicates whether it's allowed +/// to replace any discovered invalid member references with `ErrorExpr`. +Expr *resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *Context, + bool replaceInvalidRefsWithErrors); /// Check for unsupported protocol types in the given declaration. void checkUnsupportedProtocolType(Decl *decl); @@ -601,6 +579,11 @@ RequirementCheckResult checkGenericArguments( ArrayRef requirements, TypeSubstitutionFn substitutions, SubstOptions options = None); +bool checkContextualRequirements(GenericTypeDecl *decl, + Type parentTy, + SourceLoc loc, + DeclContext *dc); + /// Add any implicitly-defined constructors required for the given /// struct or class. void addImplicitConstructors(NominalTypeDecl *typeDecl); @@ -936,17 +919,6 @@ LookupTypeResult lookupMemberType(DeclContext *dc, Type type, DeclNameRef name, NameLookupOptions options = defaultMemberTypeLookupOptions); -/// Look up the constructors of the given type. -/// -/// \param dc The context that needs the constructor. -/// \param type The type for which we will look for constructors. -/// \param options Options that control name lookup. -/// -/// \returns the constructors found for this type. -LookupResult lookupConstructors( - DeclContext *dc, Type type, - NameLookupOptions options = defaultConstructorLookupOptions); - /// Given an expression that's known to be an infix operator, /// look up its precedence group. PrecedenceGroupDecl *lookupPrecedenceGroupForInfixOperator(DeclContext *dc, @@ -1147,11 +1119,11 @@ void diagnoseIfDeprecated(SourceRange SourceRange, void checkForForbiddenPrefix(ASTContext &C, DeclBaseName Name); /// Check error handling in the given type-checked top-level code. -void checkTopLevelErrorHandling(TopLevelCodeDecl *D); -void checkFunctionErrorHandling(AbstractFunctionDecl *D); -void checkInitializerErrorHandling(Initializer *I, Expr *E); -void checkEnumElementErrorHandling(EnumElementDecl *D, Expr *expr); -void checkPropertyWrapperErrorHandling(PatternBindingDecl *binding, +void checkTopLevelEffects(TopLevelCodeDecl *D); +void checkFunctionEffects(AbstractFunctionDecl *D); +void checkInitializerEffects(Initializer *I, Expr *E); +void checkEnumElementEffects(EnumElementDecl *D, Expr *expr); +void checkPropertyWrapperEffects(PatternBindingDecl *binding, Expr *expr); /// If an expression references 'self.init' or 'super.init' in an @@ -1235,6 +1207,11 @@ bool requirePointerArgumentIntrinsics(ASTContext &ctx, SourceLoc loc); /// Require that the library intrinsics for creating /// array literals exist. bool requireArrayLiteralIntrinsics(ASTContext &ctx, SourceLoc loc); + +/// Gets the \c UnresolvedMemberExpr at the base of a chain of member accesses. +/// If \c expr is not part of a member chain or the base is something other than +/// an \c UnresolvedMemberExpr, \c nullptr is returned. +UnresolvedMemberExpr *getUnresolvedMemberChainBase(Expr *expr); }; // namespace TypeChecker /// Temporary on-stack storage and unescaping for encoded diagnostic @@ -1391,6 +1368,10 @@ void checkUnknownAttrRestrictions( /// it to later stages. void bindSwitchCasePatternVars(DeclContext *dc, CaseStmt *stmt); +/// Add notes suggesting the addition of 'async' or '@asyncHandler', as +/// appropriate, to a diagnostic for a function that isn't an async context. +void addAsyncNotes(FuncDecl *func); + } // end namespace swift #endif diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index ddbc8f9a513d0..724aef5da6b76 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -1611,6 +1611,14 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) { getXRefDeclNameForError()); } + if (memberName.getKind() == DeclBaseName::Kind::Destructor) { + assert(isa(nominal)); + // Force creation of an implicit destructor + auto CD = dyn_cast(nominal); + values.push_back(CD->getDestructor()); + break; + } + if (!privateDiscriminator.empty()) { ModuleDecl *searchModule = M; if (!searchModule) @@ -2995,6 +3003,7 @@ class DeclDeserializer { DeclID accessorStorageDeclID; bool overriddenAffectsABI, needsNewVTableEntry, isTransparent; DeclID opaqueReturnTypeID; + bool isUserAccessible; ArrayRef nameAndDependencyIDs; if (!isAccessor) { @@ -3012,6 +3021,7 @@ class DeclDeserializer { rawAccessLevel, needsNewVTableEntry, opaqueReturnTypeID, + isUserAccessible, nameAndDependencyIDs); } else { decls_block::AccessorLayout::readRecord(scratch, contextID, isImplicit, @@ -3123,21 +3133,19 @@ class DeclDeserializer { if (declOrOffset.isComplete()) return declOrOffset; + const auto resultType = MF.getType(resultInterfaceTypeID); + if (declOrOffset.isComplete()) + return declOrOffset; + FuncDecl *fn; if (!isAccessor) { - fn = FuncDecl::createDeserialized( - ctx, /*StaticLoc=*/SourceLoc(), staticSpelling.getValue(), - /*FuncLoc=*/SourceLoc(), name, /*NameLoc=*/SourceLoc(), - async, /*AsyncLoc=*/SourceLoc(), - /*Throws=*/throws, /*ThrowsLoc=*/SourceLoc(), - genericParams, DC); + fn = FuncDecl::createDeserialized(ctx, staticSpelling.getValue(), name, + async, throws, genericParams, + resultType, DC); } else { auto *accessor = AccessorDecl::createDeserialized( - ctx, /*FuncLoc=*/SourceLoc(), /*AccessorKeywordLoc=*/SourceLoc(), - accessorKind, storage, - /*StaticLoc=*/SourceLoc(), staticSpelling.getValue(), - /*Throws=*/throws, /*ThrowsLoc=*/SourceLoc(), - genericParams, DC); + ctx, accessorKind, storage, staticSpelling.getValue(), + /*Throws=*/throws, genericParams, resultType, DC); accessor->setIsTransparent(isTransparent); fn = accessor; @@ -3173,8 +3181,6 @@ class DeclDeserializer { } fn->setStatic(isStatic); - - fn->getBodyResultTypeLoc().setType(MF.getType(resultInterfaceTypeID)); fn->setImplicitlyUnwrappedOptional(isIUO); ParameterList *paramList = MF.readParameterList(); @@ -3203,6 +3209,9 @@ class DeclDeserializer { cast(MF.getDecl(opaqueReturnTypeID))); } + if (!isAccessor) + fn->setUserAccessible(isUserAccessible); + return fn; } @@ -3850,11 +3859,12 @@ class DeclDeserializer { if (!staticSpelling.hasValue()) MF.fatal(); - auto subscript = MF.createDecl(name, - SourceLoc(), *staticSpelling, - SourceLoc(), nullptr, - SourceLoc(), TypeLoc(), - parent, genericParams); + const auto elemInterfaceType = MF.getType(elemInterfaceTypeID); + if (declOrOffset.isComplete()) + return declOrOffset; + + auto *const subscript = SubscriptDecl::createDeserialized( + ctx, name, *staticSpelling, elemInterfaceType, parent, genericParams); subscript->setIsGetterMutating(isGetterMutating); subscript->setIsSetterMutating(isSetterMutating); declOrOffset = subscript; @@ -3878,8 +3888,6 @@ class DeclDeserializer { MF.fatal(); } - auto elemInterfaceType = MF.getType(elemInterfaceTypeID); - subscript->getElementTypeLoc().setType(elemInterfaceType); subscript->setImplicitlyUnwrappedOptional(isIUO); if (isImplicit) @@ -5360,6 +5368,7 @@ class TypeDeserializer { Expected deserializeSILFunctionType(ArrayRef scratch, StringRef blobData) { + bool async; uint8_t rawCoroutineKind; uint8_t rawCalleeConvention; uint8_t rawRepresentation; @@ -5377,6 +5386,7 @@ class TypeDeserializer { ClangTypeID clangFunctionTypeID; decls_block::SILFunctionTypeLayout::readRecord(scratch, + async, rawCoroutineKind, rawCalleeConvention, rawRepresentation, @@ -5403,21 +5413,18 @@ class TypeDeserializer { if (!diffKind.hasValue()) MF.fatal(); - const clang::FunctionType *clangFunctionType = nullptr; + const clang::Type *clangFunctionType = nullptr; if (clangFunctionTypeID) { auto clangType = MF.getClangType(clangFunctionTypeID); if (!clangType) return clangType.takeError(); - // FIXME: allow block pointers here. - clangFunctionType = - dyn_cast_or_null(clangType.get()); - if (!clangFunctionType) - MF.fatal(); + clangFunctionType = clangType.get(); } auto extInfo = SILFunctionType::ExtInfoBuilder(*representation, pseudogeneric, - noescape, *diffKind, clangFunctionType) + noescape, async, *diffKind, + clangFunctionType) .build(); // Process the coroutine kind. diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 97c84001d009c..b2cfae7bfd405 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -510,18 +510,17 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, IdentifierID replacedFunctionID; GenericSignatureID genericSigID; unsigned rawLinkage, isTransparent, isSerialized, isThunk, - isWithoutactuallyEscapingThunk, isAsync, specialPurpose, inlineStrategy, - optimizationMode, effect, numSpecAttrs, hasQualifiedOwnership, - isWeakImported, LIST_VER_TUPLE_PIECES(available), + isWithoutactuallyEscapingThunk, specialPurpose, inlineStrategy, + optimizationMode, subclassScope, effect, numSpecAttrs, + hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), isDynamic, isExactSelfClass; ArrayRef SemanticsIDs; SILFunctionLayout::readRecord( scratch, rawLinkage, isTransparent, isSerialized, isThunk, - isWithoutactuallyEscapingThunk, isAsync, specialPurpose, inlineStrategy, - optimizationMode, effect, numSpecAttrs, hasQualifiedOwnership, - isWeakImported, LIST_VER_TUPLE_PIECES(available), - isDynamic, isExactSelfClass, - funcTyID, replacedFunctionID, genericSigID, + isWithoutactuallyEscapingThunk, specialPurpose, inlineStrategy, + optimizationMode, subclassScope, effect, numSpecAttrs, + hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), + isDynamic, isExactSelfClass, funcTyID, replacedFunctionID, genericSigID, clangNodeOwnerID, SemanticsIDs); if (funcTyID == 0) { @@ -626,11 +625,6 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, MF->fatal(); } - if (fn->isAsync() != isAsync) { - LLVM_DEBUG(llvm::dbgs() << "SILFunction type mismatch.\n"); - MF->fatal(); - } - } else { // Otherwise, create a new function. fn = builder.createDeclaration(name, ty, loc); @@ -639,12 +633,12 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, fn->setSerialized(IsSerialized_t(isSerialized)); fn->setThunk(IsThunk_t(isThunk)); fn->setWithoutActuallyEscapingThunk(bool(isWithoutactuallyEscapingThunk)); - fn->setAsync((bool)isAsync); fn->setInlineStrategy(Inline_t(inlineStrategy)); fn->setSpecialPurpose(SILFunction::Purpose(specialPurpose)); fn->setEffectsKind(EffectsKind(effect)); fn->setOptimizationMode(OptimizationMode(optimizationMode)); fn->setAlwaysWeakImported(isWeakImported); + fn->setClassSubclassScope(SubclassScope(subclassScope)); llvm::VersionTuple available; DECODE_VER_TUPLE(available); @@ -2829,18 +2823,17 @@ bool SILDeserializer::hasSILFunction(StringRef Name, IdentifierID replacedFunctionID; GenericSignatureID genericSigID; unsigned rawLinkage, isTransparent, isSerialized, isThunk, - isWithoutactuallyEscapingThunk, isAsync, isGlobal, inlineStrategy, - optimizationMode, effect, numSpecAttrs, hasQualifiedOwnership, - isWeakImported, LIST_VER_TUPLE_PIECES(available), + isWithoutactuallyEscapingThunk, isGlobal, inlineStrategy, + optimizationMode, subclassScope, effect, numSpecAttrs, + hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), isDynamic, isExactSelfClass; ArrayRef SemanticsIDs; SILFunctionLayout::readRecord( scratch, rawLinkage, isTransparent, isSerialized, isThunk, - isWithoutactuallyEscapingThunk, isAsync, isGlobal, inlineStrategy, - optimizationMode, effect, numSpecAttrs, hasQualifiedOwnership, - isWeakImported, LIST_VER_TUPLE_PIECES(available), - isDynamic, isExactSelfClass, - funcTyID, replacedFunctionID, genericSigID, + isWithoutactuallyEscapingThunk, isGlobal, inlineStrategy, + optimizationMode, subclassScope, effect, numSpecAttrs, + hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), + isDynamic, isExactSelfClass, funcTyID, replacedFunctionID, genericSigID, clangOwnerID, SemanticsIDs); auto linkage = fromStableSILLinkage(rawLinkage); if (!linkage) { diff --git a/lib/Serialization/ModuleDependencyScanner.cpp b/lib/Serialization/ModuleDependencyScanner.cpp index c0d4b8ce4b931..fbe77f062b9b6 100644 --- a/lib/Serialization/ModuleDependencyScanner.cpp +++ b/lib/Serialization/ModuleDependencyScanner.cpp @@ -19,149 +19,81 @@ #include "swift/Basic/FileTypes.h" #include "swift/Frontend/ModuleInterfaceLoader.h" #include "swift/Serialization/SerializedModuleLoader.h" +#include "swift/Serialization/ModuleDependencyScanner.h" #include "swift/Subsystems.h" using namespace swift; using llvm::ErrorOr; -namespace { -/// A module "loader" that looks for .swiftinterface and .swiftmodule files -/// for the purpose of determining dependencies, but does not attempt to -/// load the module files. -class ModuleDependencyScanner : public SerializedModuleLoaderBase { - /// The module we're scanning dependencies of. - Identifier moduleName; - - /// Scan the given interface file to determine dependencies. - ErrorOr scanInterfaceFile( - Twine moduleInterfacePath); - - InterfaceSubContextDelegate &astDelegate; -public: - Optional dependencies; - - /// Describes the kind of dependencies this scanner is able to identify - ModuleDependenciesKind dependencyKind; - - ModuleDependencyScanner( - ASTContext &ctx, ModuleLoadingMode LoadMode, Identifier moduleName, - InterfaceSubContextDelegate &astDelegate, - ModuleDependenciesKind dependencyKind = ModuleDependenciesKind::Swift) - : SerializedModuleLoaderBase(ctx, nullptr, LoadMode, - /*IgnoreSwiftSourceInfoFile=*/true), - moduleName(moduleName), astDelegate(astDelegate), - dependencyKind(dependencyKind) {} - - virtual std::error_code findModuleFilesInDirectory( - AccessPathElem ModuleID, - const SerializedModuleBaseName &BaseName, - SmallVectorImpl *ModuleInterfacePath, - std::unique_ptr *ModuleBuffer, - std::unique_ptr *ModuleDocBuffer, - std::unique_ptr *ModuleSourceInfoBuffer) override { - using namespace llvm::sys; - - auto &fs = *Ctx.SourceMgr.getFileSystem(); - - auto ModPath = BaseName.getName(file_types::TY_SwiftModuleFile); - auto InPath = BaseName.getName(file_types::TY_SwiftModuleInterfaceFile); - - if (LoadMode == ModuleLoadingMode::OnlySerialized || !fs.exists(InPath)) { - if (fs.exists(ModPath)) { - // The module file will be loaded directly. - auto dependencies = scanModuleFile(ModPath); - if (dependencies) { - this->dependencies = std::move(dependencies.get()); - return std::error_code(); - } - return dependencies.getError(); - } else { - return std::make_error_code(std::errc::no_such_file_or_directory); +std::error_code ModuleDependencyScanner::findModuleFilesInDirectory( + AccessPathElem ModuleID, + const SerializedModuleBaseName &BaseName, + SmallVectorImpl *ModuleInterfacePath, + std::unique_ptr *ModuleBuffer, + std::unique_ptr *ModuleDocBuffer, + std::unique_ptr *ModuleSourceInfoBuffer, + bool IsFramework) { + using namespace llvm::sys; + + auto &fs = *Ctx.SourceMgr.getFileSystem(); + + auto ModPath = BaseName.getName(file_types::TY_SwiftModuleFile); + auto InPath = BaseName.getName(file_types::TY_SwiftModuleInterfaceFile); + + if (LoadMode == ModuleLoadingMode::OnlySerialized || !fs.exists(InPath)) { + if (fs.exists(ModPath)) { + // The module file will be loaded directly. + auto dependencies = scanModuleFile(ModPath); + if (dependencies) { + this->dependencies = std::move(dependencies.get()); + return std::error_code(); } + return dependencies.getError(); + } else { + return std::make_error_code(std::errc::no_such_file_or_directory); } - assert(fs.exists(InPath)); - auto dependencies = scanInterfaceFile(InPath); - if (dependencies) { - this->dependencies = std::move(dependencies.get()); - return std::error_code(); - } - - return dependencies.getError(); } - - virtual void collectVisibleTopLevelModuleNames( - SmallVectorImpl &names) const override { - llvm_unreachable("Not used"); + assert(fs.exists(InPath)); + // Use the private interface file if exits. + auto PrivateInPath = + BaseName.getName(file_types::TY_PrivateSwiftModuleInterfaceFile); + if (fs.exists(PrivateInPath)) { + InPath = PrivateInPath; } -}; - -/// A ModuleLoader that loads placeholder dependency module stubs specified in -/// -placeholder-dependency-module-map-file -/// This loader is used only in dependency scanning to inform the scanner that a -/// set of modules constitute placeholder dependencies that are not visible to the -/// scanner but will nevertheless be provided by the scanner's clients. -/// This "loader" will not attempt to load any module files. -class PlaceholderSwiftModuleScanner : public ModuleDependencyScanner { - /// Scan the given placeholder module map - void parsePlaceholderModuleMap(StringRef fileName) { - ExplicitModuleMapParser parser(Allocator); - auto result = - parser.parseSwiftExplicitModuleMap(fileName, PlaceholderDependencyModuleMap); - if (result == std::errc::invalid_argument) { - Ctx.Diags.diagnose(SourceLoc(), - diag::placeholder_dependency_module_map_corrupted, - fileName); - } - else if (result == std::errc::no_such_file_or_directory) { - Ctx.Diags.diagnose(SourceLoc(), - diag::placeholder_dependency_module_map_missing, - fileName); - } + auto dependencies = scanInterfaceFile(InPath, IsFramework); + if (dependencies) { + this->dependencies = std::move(dependencies.get()); + return std::error_code(); } - llvm::StringMap PlaceholderDependencyModuleMap; - llvm::BumpPtrAllocator Allocator; - -public: - PlaceholderSwiftModuleScanner(ASTContext &ctx, ModuleLoadingMode LoadMode, - Identifier moduleName, - StringRef PlaceholderDependencyModuleMap, - InterfaceSubContextDelegate &astDelegate) - : ModuleDependencyScanner(ctx, LoadMode, moduleName, astDelegate, - ModuleDependenciesKind::SwiftPlaceholder) { - - // FIXME: Find a better place for this map to live, to avoid - // doing the parsing on every module. - if (!PlaceholderDependencyModuleMap.empty()) { - parsePlaceholderModuleMap(PlaceholderDependencyModuleMap); - } - } + return dependencies.getError(); +} - std::error_code findModuleFilesInDirectory( - AccessPathElem ModuleID, const SerializedModuleBaseName &BaseName, - SmallVectorImpl *ModuleInterfacePath, - std::unique_ptr *ModuleBuffer, - std::unique_ptr *ModuleDocBuffer, - std::unique_ptr *ModuleSourceInfoBuffer) override { - StringRef moduleName = ModuleID.Item.str(); - auto it = PlaceholderDependencyModuleMap.find(moduleName); - // If no placeholder module stub path is given matches the name, return with an - // error code. - if (it == PlaceholderDependencyModuleMap.end()) { - return std::make_error_code(std::errc::not_supported); - } - auto &moduleInfo = it->getValue(); - assert(!moduleInfo.moduleBuffer && - "Placeholder dependency module stubs cannot have an associated buffer"); - auto dependencies = ModuleDependencies::forPlaceholderSwiftModuleStub( - moduleInfo.modulePath, moduleInfo.moduleDocPath, - moduleInfo.moduleSourceInfoPath); - this->dependencies = std::move(dependencies); - return std::error_code{}; +std::error_code PlaceholderSwiftModuleScanner::findModuleFilesInDirectory( + AccessPathElem ModuleID, const SerializedModuleBaseName &BaseName, + SmallVectorImpl *ModuleInterfacePath, + std::unique_ptr *ModuleBuffer, + std::unique_ptr *ModuleDocBuffer, + std::unique_ptr *ModuleSourceInfoBuffer, + bool IsFramework) { + StringRef moduleName = ModuleID.Item.str(); + auto it = PlaceholderDependencyModuleMap.find(moduleName); + // If no placeholder module stub path is given matches the name, return with an + // error code. + if (it == PlaceholderDependencyModuleMap.end()) { + return std::make_error_code(std::errc::not_supported); } -}; -} // namespace + auto &moduleInfo = it->getValue(); + assert(!moduleInfo.moduleBuffer && + "Placeholder dependency module stubs cannot have an associated buffer"); + + auto dependencies = ModuleDependencies::forPlaceholderSwiftModuleStub( + moduleInfo.modulePath, moduleInfo.moduleDocPath, + moduleInfo.moduleSourceInfoPath); + this->dependencies = std::move(dependencies); + return std::error_code{}; +} static std::vector getCompiledCandidates(ASTContext &ctx, StringRef moduleName, @@ -172,7 +104,7 @@ static std::vector getCompiledCandidates(ASTContext &ctx, } ErrorOr ModuleDependencyScanner::scanInterfaceFile( - Twine moduleInterfacePath) { + Twine moduleInterfacePath, bool isFramework) { // Create a module filename. // FIXME: Query the module interface loader to determine an appropriate // name for the module, which includes an appropriate hash. @@ -180,8 +112,8 @@ ErrorOr ModuleDependencyScanner::scanInterfaceFile( llvm::SmallString<32> modulePath = moduleName.str(); llvm::sys::path::replace_extension(modulePath, newExt); Optional Result; - std::error_code code; - auto hasError = astDelegate.runInSubContext(moduleName.str(), + std::error_code code = + astDelegate.runInSubContext(moduleName.str(), moduleInterfacePath.str(), StringRef(), SourceLoc(), @@ -196,13 +128,13 @@ ErrorOr ModuleDependencyScanner::scanInterfaceFile( compiledCandidates, Args, PCMArgs, - Hash); + Hash, + isFramework); // Open the interface file. auto &fs = *Ctx.SourceMgr.getFileSystem(); auto interfaceBuf = fs.getBufferForFile(moduleInterfacePath); if (!interfaceBuf) { - code = interfaceBuf.getError(); - return true; + return interfaceBuf.getError(); } // Create a source file. @@ -221,10 +153,10 @@ ErrorOr ModuleDependencyScanner::scanInterfaceFile( for (auto name: imInfo.ModuleNames) { Result->addModuleDependency(name.str(), &alreadyAddedModules); } - return false; + return std::error_code(); }); - if (hasError) { + if (code) { return code; } return *Result; diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index b3a7a893f0932..2b95150e58ff2 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -55,7 +55,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 = 568; // removed UTF16 +const uint16_t SWIFTMODULE_VERSION_MINOR = 575; // GlobalInitOnceFunction SILFunction purpose /// A standard hash seed used for all string hashes in a serialized module. /// @@ -1049,6 +1049,7 @@ namespace decls_block { using SILFunctionTypeLayout = BCRecordLayout< SIL_FUNCTION_TYPE, + BCFixed<1>, // async? SILCoroutineKindField, // coroutine kind ParameterConventionField, // callee convention SILFunctionTypeRepresentationField, // representation @@ -1307,6 +1308,7 @@ namespace decls_block { AccessLevelField, // access level BCFixed<1>, // requires a new vtable slot DeclIDField, // opaque result type decl + BCFixed<1>, // isUserAccessible? BCArray // name components, // followed by TypeID dependencies // The record is trailed by: diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h index dfa1ea155b886..c1178d5f551ad 100644 --- a/lib/Serialization/SILFormat.h +++ b/lib/Serialization/SILFormat.h @@ -277,10 +277,10 @@ namespace sil_block { BCFixed<2>, // serialized BCFixed<2>, // thunks: signature optimized/reabstraction BCFixed<1>, // without_actually_escaping - BCFixed<1>, // async BCFixed<3>, // specialPurpose BCFixed<2>, // inlineStrategy BCFixed<2>, // optimizationMode + BCFixed<2>, // classSubclassScope BCFixed<3>, // side effect info. BCVBR<8>, // number of specialize attributes BCFixed<1>, // has qualified ownership diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index c17453abfcf41..c8b5946e80f25 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -856,6 +856,8 @@ void Serializer::writeBlockInfoBlock() { BLOCK_RECORD(sil_index_block, SIL_DEFAULT_WITNESS_TABLE_NAMES); BLOCK_RECORD(sil_index_block, SIL_DEFAULT_WITNESS_TABLE_OFFSETS); BLOCK_RECORD(sil_index_block, SIL_PROPERTY_OFFSETS); + BLOCK_RECORD(sil_index_block, SIL_DIFFERENTIABILITY_WITNESS_NAMES); + BLOCK_RECORD(sil_index_block, SIL_DIFFERENTIABILITY_WITNESS_OFFSETS); #undef BLOCK #undef BLOCK_RECORD @@ -2354,7 +2356,7 @@ class Serializer::DeclSerializer : public DeclVisitor { S.Out, S.ScratchRecord, abbrCode, (unsigned)SA->isExported(), (unsigned)SA->getSpecializationKind(), - S.addGenericSignatureRef(SA->getSpecializedSgnature())); + S.addGenericSignatureRef(SA->getSpecializedSignature())); return; } @@ -3435,6 +3437,7 @@ class Serializer::DeclSerializer : public DeclVisitor { rawAccessLevel, fn->needsNewVTableEntry(), S.addDeclRef(fn->getOpaqueResultTypeDecl()), + fn->isUserAccessible(), nameComponentsAndDependencies); writeGenericParams(fn->getGenericParams()); @@ -3922,6 +3925,10 @@ class Serializer::TypeSerializer : public TypeVisitor { llvm_unreachable("should not serialize an invalid type"); } + void visitHoleType(const HoleType *) { + llvm_unreachable("should not serialize an invalid type"); + } + void visitModuleType(const ModuleType *) { llvm_unreachable("modules are currently not first-class values"); } @@ -4230,7 +4237,7 @@ class Serializer::TypeSerializer : public TypeVisitor { unsigned abbrCode = S.DeclTypeAbbrCodes[SILFunctionTypeLayout::Code]; SILFunctionTypeLayout::emitRecord( S.Out, S.ScratchRecord, abbrCode, - stableCoroutineKind, stableCalleeConvention, + fnTy->isAsync(), stableCoroutineKind, stableCalleeConvention, stableRepresentation, fnTy->isPseudogeneric(), fnTy->isNoEscape(), stableDiffKind, fnTy->hasErrorResult(), fnTy->getParameters().size(), fnTy->getNumYields(), fnTy->getNumResults(), diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index 00e9443213ea0..da46d36dd1b0a 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -433,13 +433,13 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) { Out, ScratchRecord, abbrCode, toStableSILLinkage(Linkage), (unsigned)F.isTransparent(), (unsigned)F.isSerialized(), (unsigned)F.isThunk(), (unsigned)F.isWithoutActuallyEscapingThunk(), - (unsigned)F.isAsync(), (unsigned)F.getSpecialPurpose(), + (unsigned)F.getSpecialPurpose(), (unsigned)F.getInlineStrategy(), (unsigned)F.getOptimizationMode(), - (unsigned)F.getEffectsKind(), (unsigned)numSpecAttrs, - (unsigned)F.hasOwnership(), F.isAlwaysWeakImported(), - LIST_VER_TUPLE_PIECES(available), (unsigned)F.isDynamicallyReplaceable(), - (unsigned)F.isExactSelfClass(), FnID, replacedFunctionID, genericSigID, - clangNodeOwnerID, SemanticsIDs); + (unsigned)F.getClassSubclassScope(), (unsigned)F.getEffectsKind(), + (unsigned)numSpecAttrs, (unsigned)F.hasOwnership(), + F.isAlwaysWeakImported(), LIST_VER_TUPLE_PIECES(available), + (unsigned)F.isDynamicallyReplaceable(), (unsigned)F.isExactSelfClass(), + FnID, replacedFunctionID, genericSigID, clangNodeOwnerID, SemanticsIDs); if (NoBody) return; @@ -2240,8 +2240,8 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) { } case SILInstructionKind::LinearFunctionExtractInst: { auto *lfei = cast(&SI); - auto operandRef = addValueRef(lfei->getFunctionOperand()); - auto operandType = lfei->getFunctionOperand()->getType(); + auto operandRef = addValueRef(lfei->getOperand()); + auto operandType = lfei->getOperand()->getType(); auto operandTypeRef = S.addTypeRef(operandType.getASTType()); auto rawExtractee = (unsigned)lfei->getExtractee(); SILInstLinearFunctionExtractLayout::emitRecord(Out, ScratchRecord, @@ -2345,6 +2345,11 @@ void SILSerializer::writeIndexTables() { DefaultWitnessTableOffset); } + if (!PropertyOffset.empty()) { + Offset.emit(ScratchRecord, sil_index_block::SIL_PROPERTY_OFFSETS, + PropertyOffset); + } + if (!DifferentiabilityWitnessList.empty()) { writeIndexTable(S, List, sil_index_block::SIL_DIFFERENTIABILITY_WITNESS_NAMES, @@ -2354,11 +2359,6 @@ void SILSerializer::writeIndexTables() { DifferentiabilityWitnessOffset); } - if (!PropertyOffset.empty()) { - Offset.emit(ScratchRecord, sil_index_block::SIL_PROPERTY_OFFSETS, - PropertyOffset); - } - } void SILSerializer::writeSILGlobalVar(const SILGlobalVariable &g) { diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 77d0a0a2154a0..a82ee47568e5a 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -396,7 +396,7 @@ llvm::ErrorOr SerializedModuleLoaderBase::scanModuleFile( &extInfo); // Map the set of dependencies over to the "module dependencies". - auto dependencies = ModuleDependencies::forSwiftModule(modulePath.str()); + auto dependencies = ModuleDependencies::forSwiftModule(modulePath.str(), isFramework); llvm::StringSet<> addedModuleNames; for (const auto &dependency : loadedModuleFile->getDependencies()) { // FIXME: Record header dependency? @@ -422,7 +422,8 @@ std::error_code ImplicitSerializedModuleLoader::findModuleFilesInDirectory( SmallVectorImpl *ModuleInterfacePath, std::unique_ptr *ModuleBuffer, std::unique_ptr *ModuleDocBuffer, - std::unique_ptr *ModuleSourceInfoBuffer) { + std::unique_ptr *ModuleSourceInfoBuffer, + bool IsFramework) { assert(((ModuleBuffer && ModuleDocBuffer) || (!ModuleBuffer && !ModuleDocBuffer)) && "Module and Module Doc buffer must both be initialized or NULL"); @@ -538,7 +539,7 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID, /// Returns true if a target-specific module file was found, false if an error /// was diagnosed, or None if neither one happened and the search should /// continue. - auto findTargetSpecificModuleFiles = [&]() -> Optional { + auto findTargetSpecificModuleFiles = [&](bool IsFramework) -> Optional { Optional firstAbsoluteBaseName; for (const auto &targetSpecificBaseName : targetSpecificBaseNames) { @@ -552,7 +553,8 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID, absoluteBaseName, moduleInterfacePath, moduleBuffer, moduleDocBuffer, - moduleSourceInfoBuffer); + moduleSourceInfoBuffer, + IsFramework); if (!result) { return true; } else if (result == std::errc::not_supported) { @@ -603,13 +605,13 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID, if (checkTargetSpecificModule) // A .swiftmodule directory contains architecture-specific files. - return findTargetSpecificModuleFiles(); + return findTargetSpecificModuleFiles(isFramework); SerializedModuleBaseName absoluteBaseName{currPath, genericBaseName}; auto result = findModuleFilesInDirectory( moduleID, absoluteBaseName, moduleInterfacePath, - moduleBuffer, moduleDocBuffer, moduleSourceInfoBuffer); + moduleBuffer, moduleDocBuffer, moduleSourceInfoBuffer, isFramework); if (!result) return true; else if (result == std::errc::not_supported) @@ -628,7 +630,7 @@ SerializedModuleLoaderBase::findModule(AccessPathElem moduleID, // Frameworks always use architecture-specific files within a // .swiftmodule directory. llvm::sys::path::append(currPath, "Modules"); - return findTargetSpecificModuleFiles(); + return findTargetSpecificModuleFiles(isFramework); } } llvm_unreachable("covered switch"); @@ -680,7 +682,6 @@ FileUnit *SerializedModuleLoaderBase::loadAST( std::unique_ptr moduleSourceInfoInputBuffer, bool isFramework) { assert(moduleInputBuffer); - StringRef moduleBufferID = moduleInputBuffer->getBufferIdentifier(); StringRef moduleDocBufferID; if (moduleDocInputBuffer) @@ -991,7 +992,6 @@ SerializedModuleLoaderBase::loadModule(SourceLoc importLoc, StringRef moduleInterfacePathStr = Ctx.AllocateCopy(moduleInterfacePath.str()); - auto *file = loadAST(*M, moduleID.Loc, moduleInterfacePathStr, std::move(moduleInputBuffer), std::move(moduleDocInputBuffer), @@ -1081,7 +1081,8 @@ std::error_code MemoryBufferSerializedModuleLoader::findModuleFilesInDirectory( SmallVectorImpl *ModuleInterfacePath, std::unique_ptr *ModuleBuffer, std::unique_ptr *ModuleDocBuffer, - std::unique_ptr *ModuleSourceInfoBuffer) { + std::unique_ptr *ModuleSourceInfoBuffer, + bool IsFramework) { // This is a soft error instead of an llvm_unreachable because this API is // primarily used by LLDB which makes it more likely that unwitting changes to // the Swift compiler accidentally break the contract. diff --git a/lib/SymbolGraphGen/DeclarationFragmentPrinter.cpp b/lib/SymbolGraphGen/DeclarationFragmentPrinter.cpp index 4ef5f70b5ab4b..be82f22395e37 100644 --- a/lib/SymbolGraphGen/DeclarationFragmentPrinter.cpp +++ b/lib/SymbolGraphGen/DeclarationFragmentPrinter.cpp @@ -138,7 +138,15 @@ void DeclarationFragmentPrinter::printTypeRef(Type T, const TypeDecl *RefTo, openFragment(FragmentKind::TypeIdentifier); printText(Name.str()); USR.clear(); - if (Name.str() != "Self") { + + auto ShouldLink = Name.str() != "Self"; + if (const auto *TD = T->getAnyNominal()) { + if (SG->isImplicitlyPrivate(TD)) { + ShouldLink = false; + } + } + + if (ShouldLink) { llvm::raw_svector_ostream OS(USR); ide::printDeclUSR(RefTo, OS); } diff --git a/lib/SymbolGraphGen/DeclarationFragmentPrinter.h b/lib/SymbolGraphGen/DeclarationFragmentPrinter.h index 580a37e2303ff..16e011669e062 100644 --- a/lib/SymbolGraphGen/DeclarationFragmentPrinter.h +++ b/lib/SymbolGraphGen/DeclarationFragmentPrinter.h @@ -59,6 +59,9 @@ class DeclarationFragmentPrinter : public ASTPrinter { Text, }; private: + /// The symbol graph for which a declaration is being printed. + const SymbolGraph *SG; + /// The output stream to print fragment objects to. llvm::json::OStream &OS; @@ -81,9 +84,11 @@ class DeclarationFragmentPrinter : public ASTPrinter { unsigned NumFragments; public: - DeclarationFragmentPrinter(llvm::json::OStream &OS, + DeclarationFragmentPrinter(const SymbolGraph *SG, + llvm::json::OStream &OS, Optional Key = None) - : OS(OS), + : SG(SG), + OS(OS), Kind(FragmentKind::None), NumFragments(0) { if (Key) { diff --git a/lib/SymbolGraphGen/SymbolGraph.cpp b/lib/SymbolGraphGen/SymbolGraph.cpp index 8ef75088237b8..cb2a2a1741504 100644 --- a/lib/SymbolGraphGen/SymbolGraph.cpp +++ b/lib/SymbolGraphGen/SymbolGraph.cpp @@ -558,7 +558,7 @@ void SymbolGraph::serializeDeclarationFragments(StringRef Key, const Symbol &S, llvm::json::OStream &OS) { - DeclarationFragmentPrinter Printer(OS, Key); + DeclarationFragmentPrinter Printer(this, OS, Key); auto Options = getDeclarationFragmentsPrintOptions(); if (S.getSynthesizedBaseType()) { Options.setBaseType(S.getSynthesizedBaseType()); @@ -570,7 +570,7 @@ void SymbolGraph::serializeNavigatorDeclarationFragments(StringRef Key, const Symbol &S, llvm::json::OStream &OS) { - DeclarationFragmentPrinter Printer(OS, Key); + DeclarationFragmentPrinter Printer(this, OS, Key); if (const auto *TD = dyn_cast(S.getSymbolDecl())) { Printer.printAbridgedType(TD, /*PrintKeyword=*/false); @@ -587,7 +587,7 @@ void SymbolGraph::serializeSubheadingDeclarationFragments(StringRef Key, const Symbol &S, llvm::json::OStream &OS) { - DeclarationFragmentPrinter Printer(OS, Key); + DeclarationFragmentPrinter Printer(this, OS, Key); if (const auto *TD = dyn_cast(S.getSymbolDecl())) { Printer.printAbridgedType(TD, /*PrintKeyword=*/true); @@ -603,7 +603,7 @@ SymbolGraph::serializeSubheadingDeclarationFragments(StringRef Key, void SymbolGraph::serializeDeclarationFragments(StringRef Key, Type T, llvm::json::OStream &OS) { - DeclarationFragmentPrinter Printer(OS, Key); + DeclarationFragmentPrinter Printer(this, OS, Key); T->print(Printer, getDeclarationFragmentsPrintOptions()); } diff --git a/lib/SymbolGraphGen/SymbolGraphASTWalker.h b/lib/SymbolGraphGen/SymbolGraphASTWalker.h index 9a1ebae5e4908..81c9db978468c 100644 --- a/lib/SymbolGraphGen/SymbolGraphASTWalker.h +++ b/lib/SymbolGraphGen/SymbolGraphASTWalker.h @@ -86,7 +86,7 @@ struct SymbolGraphASTWalker : public SourceEntityWalker { // MARK: - SourceEntityWalker - virtual bool walkToDeclPre(Decl *D, CharSourceRange Range); + virtual bool walkToDeclPre(Decl *D, CharSourceRange Range) override; }; } // end namespace symbolgraphgen diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp index bb90f41674faa..623e3d02ffb3e 100644 --- a/lib/TBDGen/TBDGen.cpp +++ b/lib/TBDGen/TBDGen.cpp @@ -61,16 +61,15 @@ static bool isGlobalOrStaticVar(VarDecl *VD) { return VD->isStatic() || VD->getDeclContext()->isModuleScopeContext(); } -TBDGenVisitor::TBDGenVisitor(TBDGenDescriptor desc, +TBDGenVisitor::TBDGenVisitor(const TBDGenDescriptor &desc, SymbolCallbackFn symbolCallback) : TBDGenVisitor(desc.getTarget(), desc.getDataLayout(), desc.getParentModule(), desc.getOptions(), symbolCallback) {} -void TBDGenVisitor::addSymbolInternal(StringRef name, - llvm::MachO::SymbolKind kind, - bool isLinkerDirective) { - if (!isLinkerDirective && Opts.LinkerDirectivesOnly) +void TBDGenVisitor::addSymbolInternal(StringRef name, SymbolKind kind, + SymbolSource source) { + if (!source.isLinkerDirective() && Opts.LinkerDirectivesOnly) return; #ifndef NDEBUG @@ -81,7 +80,7 @@ void TBDGenVisitor::addSymbolInternal(StringRef name, } } #endif - SymbolCallback(name, kind); + SymbolCallback(name, kind, source); } static std::vector @@ -337,8 +336,8 @@ void TBDGenVisitor::addLinkerDirectiveSymbolsLdPrevious(StringRef name, OS << IntroVer->getMajor() << "." << getMinor(IntroVer->getMinor()) << "$"; OS << Ver.Version.getMajor() << "." << getMinor(Ver.Version.getMinor()) << "$"; OS << name << "$"; - addSymbolInternal(OS.str(), llvm::MachO::SymbolKind::GlobalSymbol, - /*LinkerDirective*/true); + addSymbolInternal(OS.str(), SymbolKind::GlobalSymbol, + SymbolSource::forLinkerDirective()); } } @@ -383,18 +382,19 @@ void TBDGenVisitor::addLinkerDirectiveSymbolsLdHide(StringRef name, llvm::SmallString<64> Buffer; llvm::raw_svector_ostream OS(Buffer); OS << "$ld$hide$os" << CurMaj << "." << CurMin << "$" << name; - addSymbolInternal(OS.str(), llvm::MachO::SymbolKind::GlobalSymbol, - /*LinkerDirective*/true); + addSymbolInternal(OS.str(), SymbolKind::GlobalSymbol, + SymbolSource::forLinkerDirective()); } } } -void TBDGenVisitor::addSymbol(StringRef name, SymbolKind kind) { +void TBDGenVisitor::addSymbol(StringRef name, SymbolSource source, + SymbolKind kind) { // The linker expects to see mangled symbol names in TBD files, so make sure // to mangle before inserting the symbol. SmallString<32> mangled; llvm::Mangler::getNameWithPrefix(mangled, name, DataLayout); - addSymbolInternal(mangled, kind); + addSymbolInternal(mangled, kind, source); if (previousInstallNameMap) { addLinkerDirectiveSymbolsLdPrevious(mangled, kind); } else { @@ -406,8 +406,10 @@ void TBDGenVisitor::addSymbol(SILDeclRef declRef) { auto linkage = effectiveLinkageForClassMember( declRef.getLinkage(ForDefinition), declRef.getSubclassScope()); - if (linkage == SILLinkage::Public) - addSymbol(declRef.mangle()); + if (Opts.PublicSymbolsOnly && linkage != SILLinkage::Public) + return; + + addSymbol(declRef.mangle(), SymbolSource::forSILDeclRef(declRef)); } void TBDGenVisitor::addSymbol(LinkEntity entity) { @@ -418,8 +420,10 @@ void TBDGenVisitor::addSymbol(LinkEntity entity) { llvm::GlobalValue::isExternalLinkage(linkage.getLinkage()) && linkage.getVisibility() != llvm::GlobalValue::HiddenVisibility; - if (externallyVisible) - addSymbol(linkage.getName()); + if (Opts.PublicSymbolsOnly && !externallyVisible) + return; + + addSymbol(linkage.getName(), SymbolSource::forIRLinkEntity(entity)); } void TBDGenVisitor::addDispatchThunk(SILDeclRef declRef) { @@ -486,13 +490,21 @@ void TBDGenVisitor::addConformances(const IterableDeclContext *IDC) { auto addSymbolIfNecessary = [&](ValueDecl *requirementDecl, ValueDecl *witnessDecl) { auto witnessRef = SILDeclRef(witnessDecl); - if (conformanceIsFixed && - (isa(rootConformance) || - fixmeWitnessHasLinkageThatNeedsToBePublic(witnessRef))) { - Mangle::ASTMangler Mangler; - addSymbol( - Mangler.mangleWitnessThunk(rootConformance, requirementDecl)); + if (Opts.PublicSymbolsOnly) { + if (!conformanceIsFixed) + return; + + if (!isa(rootConformance) && + !fixmeWitnessHasLinkageThatNeedsToBePublic(witnessRef)) { + return; + } } + + Mangle::ASTMangler Mangler; + + // FIXME: We should have a SILDeclRef SymbolSource for this. + addSymbol(Mangler.mangleWitnessThunk(rootConformance, requirementDecl), + SymbolSource::forUnknown()); }; rootConformance->forEachValueWitness([&](ValueDecl *valueReq, @@ -523,11 +535,11 @@ void TBDGenVisitor::addAutoDiffLinearMapFunction(AbstractFunctionDecl *original, auto declRef = SILDeclRef(original).asForeign(requiresForeignEntryPoint(original)); - if (!declRef.isSerialized()) - return; - // Linear maps are public only when the original function is serialized. - if (!declRef.isSerialized()) + // Linear maps are public only when the original function is serialized. So + // if we're only including public symbols and it's not serialized, bail. + if (Opts.PublicSymbolsOnly && !declRef.isSerialized()) return; + // Differential functions are emitted only when forward-mode is enabled. if (kind == AutoDiffLinearMapKind::Differential && !ctx.LangOpts.EnableExperimentalForwardModeDifferentiation) @@ -542,7 +554,7 @@ void TBDGenVisitor::addAutoDiffLinearMapFunction(AbstractFunctionDecl *original, original->getGenericSignature(), config.derivativeGenericSignature)}; std::string linearMapName = mangler.mangleAutoDiffLinearMapHelper(declRef.mangle(), kind, silConfig); - addSymbol(linearMapName); + addSymbol(linearMapName, SymbolSource::forSILDeclRef(declRef)); } void TBDGenVisitor::addAutoDiffDerivativeFunction( @@ -571,7 +583,7 @@ void TBDGenVisitor::addDifferentiabilityWitness( auto originalLinkage = declRef.getLinkage(ForDefinition); if (foreign) originalLinkage = stripExternalFromLinkage(originalLinkage); - if (originalLinkage != SILLinkage::Public) + if (Opts.PublicSymbolsOnly && originalLinkage != SILLinkage::Public) return; auto *silParamIndices = autodiff::getLoweredParameterIndices( @@ -587,7 +599,7 @@ void TBDGenVisitor::addDifferentiabilityWitness( Mangle::ASTMangler mangler; auto mangledName = mangler.mangleSILDifferentiabilityWitnessKey(key); - addSymbol(mangledName); + addSymbol(mangledName, SymbolSource::forSILDeclRef(declRef)); } void TBDGenVisitor::addDerivativeConfiguration(AbstractFunctionDecl *original, @@ -629,7 +641,7 @@ static bool shouldUseAllocatorMangling(const AbstractFunctionDecl *afd) { void TBDGenVisitor::visitDefaultArguments(ValueDecl *VD, ParameterList *PL) { auto publicDefaultArgGenerators = SwiftModule->isTestingEnabled() || SwiftModule->arePrivateImportsEnabled(); - if (!publicDefaultArgGenerators) + if (Opts.PublicSymbolsOnly && !publicDefaultArgGenerators) return; // In Swift 3 (or under -enable-testing), default arguments (of public @@ -769,10 +781,12 @@ void TBDGenVisitor::visitVarDecl(VarDecl *VD) { // statically/globally stored variables have some special handling. if (VD->hasStorage() && isGlobalOrStaticVar(VD)) { - if (getDeclLinkage(VD) == FormalLinkage::PublicUnique) { + if (!Opts.PublicSymbolsOnly || + getDeclLinkage(VD) == FormalLinkage::PublicUnique) { // The actual variable has a symbol. + // FIXME: We ought to have a symbol source for this. Mangle::ASTMangler mangler; - addSymbol(mangler.mangleEntity(VD)); + addSymbol(mangler.mangleEntity(VD), SymbolSource::forUnknown()); } if (VD->isLazilyInitializedGlobal()) @@ -811,7 +825,8 @@ void TBDGenVisitor::visitNominalTypeDecl(NominalTypeDecl *NTD) { } void TBDGenVisitor::visitClassDecl(ClassDecl *CD) { - if (getDeclLinkage(CD) != FormalLinkage::PublicUnique) + if (Opts.PublicSymbolsOnly && + getDeclLinkage(CD) != FormalLinkage::PublicUnique) return; auto &ctxt = CD->getASTContext(); @@ -835,8 +850,10 @@ void TBDGenVisitor::visitClassDecl(ClassDecl *CD) { addSymbol(LinkEntity::forSwiftMetaclassStub(CD)); if (addObjCClass) { + // FIXME: We ought to have a symbol source for this. SmallString<128> buffer; - addSymbol(CD->getObjCRuntimeName(buffer), SymbolKind::ObjectiveCClass); + addSymbol(CD->getObjCRuntimeName(buffer), SymbolSource::forUnknown(), + SymbolKind::ObjectiveCClass); } } @@ -1048,8 +1065,10 @@ void TBDGenVisitor::visitEnumElementDecl(EnumElementDecl *EED) { void TBDGenVisitor::addFirstFileSymbols() { if (!Opts.ModuleLinkName.empty()) { + // FIXME: We ought to have a symbol source for this. SmallString<32> buf; - addSymbol(irgen::encodeForceLoadSymbolName(buf, Opts.ModuleLinkName)); + addSymbol(irgen::encodeForceLoadSymbolName(buf, Opts.ModuleLinkName), + SymbolSource::forUnknown()); } } @@ -1196,7 +1215,7 @@ TBDFile GenerateTBDRequest::evaluate(Evaluator &evaluator, } llvm::MachO::TargetList targets{target}; - auto addSymbol = [&](StringRef symbol, SymbolKind kind) { + auto addSymbol = [&](StringRef symbol, SymbolKind kind, SymbolSource source) { file.addSymbol(kind, symbol, targets); }; @@ -1209,7 +1228,7 @@ std::vector PublicSymbolsRequest::evaluate(Evaluator &evaluator, TBDGenDescriptor desc) const { std::vector symbols; - auto addSymbol = [&](StringRef symbol, SymbolKind kind) { + auto addSymbol = [&](StringRef symbol, SymbolKind kind, SymbolSource source) { if (kind == SymbolKind::GlobalSymbol) symbols.push_back(symbol.str()); }; @@ -1231,3 +1250,24 @@ void swift::writeTBDFile(ModuleDecl *M, llvm::raw_ostream &os, llvm::cantFail(llvm::MachO::TextAPIWriter::writeToStream(os, file), "YAML writing should be error-free"); } + +SymbolSourceMap SymbolSourceMapRequest::evaluate(Evaluator &evaluator, + TBDGenDescriptor desc) const { + using Map = SymbolSourceMap::Storage; + Map symbolSources; + + auto addSymbol = [&](StringRef symbol, SymbolKind kind, SymbolSource source) { + symbolSources.insert({symbol, source}); + }; + + TBDGenVisitor visitor(desc, addSymbol); + visitor.visit(desc); + + // FIXME: Once the evaluator supports returning a reference to a cached value + // in storage, this won't be necessary. + auto &ctx = desc.getParentModule()->getASTContext(); + auto *memory = ctx.Allocate(); + *memory = std::move(symbolSources); + ctx.addCleanup([memory](){ memory->~Map(); }); + return SymbolSourceMap(memory); +} diff --git a/lib/TBDGen/TBDGenVisitor.h b/lib/TBDGen/TBDGenVisitor.h index 0f14e71476568..3c93e8d02db56 100644 --- a/lib/TBDGen/TBDGenVisitor.h +++ b/lib/TBDGen/TBDGenVisitor.h @@ -42,6 +42,7 @@ namespace swift { class TBDGenDescriptor; struct TBDGenOptions; +class SymbolSource; namespace tbdgen { @@ -72,7 +73,8 @@ class TBDGenVisitor : public ASTVisitor { const TBDGenOptions &Opts; using SymbolKind = llvm::MachO::SymbolKind; - using SymbolCallbackFn = llvm::function_ref; + using SymbolCallbackFn = + llvm::function_ref; SymbolCallbackFn SymbolCallback; @@ -90,11 +92,11 @@ class TBDGenVisitor : public ASTVisitor { std::unique_ptr> parsePreviousModuleInstallNameMap(); void addSymbolInternal(StringRef name, llvm::MachO::SymbolKind kind, - bool isLinkerDirective = false); + SymbolSource source); void addLinkerDirectiveSymbolsLdHide(StringRef name, llvm::MachO::SymbolKind kind); void addLinkerDirectiveSymbolsLdPrevious(StringRef name, llvm::MachO::SymbolKind kind); - void addSymbol(StringRef name, llvm::MachO::SymbolKind kind = - llvm::MachO::SymbolKind::GlobalSymbol); + void addSymbol(StringRef name, SymbolSource source, + SymbolKind kind = SymbolKind::GlobalSymbol); void addSymbol(SILDeclRef declRef); @@ -150,7 +152,7 @@ class TBDGenVisitor : public ASTVisitor { /// Create a new visitor using the target and layout information from a /// TBDGenDescriptor. - TBDGenVisitor(TBDGenDescriptor desc, SymbolCallbackFn symbolCallback); + TBDGenVisitor(const TBDGenDescriptor &desc, SymbolCallbackFn symbolCallback); ~TBDGenVisitor() { assert(DeclStack.empty()); } void addMainIfNecessary(FileUnit *file) { @@ -160,8 +162,9 @@ class TBDGenVisitor : public ASTVisitor { // // Make sure to only add the main symbol for the module that we're emitting // TBD for, and not for any statically linked libraries. + // FIXME: We should have a SymbolSource for main. if (file->hasEntryPoint() && file->getParentModule() == SwiftModule) - addSymbol("main"); + addSymbol("main", SymbolSource::forUnknown()); } /// Adds the global symbols associated with the first file. diff --git a/localization/CMakeLists.txt b/localization/CMakeLists.txt index 764b378f97b44..6a4ac7b0351fa 100644 --- a/localization/CMakeLists.txt +++ b/localization/CMakeLists.txt @@ -4,12 +4,13 @@ add_custom_command(TARGET diagnostic-database COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/diagnostics/ ${CMAKE_BINARY_DIR}/share/swift/diagnostics/ COMMAND - $ + "${SWIFT_NATIVE_SWIFT_TOOLS_PATH}/swift-serialize-diagnostics" --input-file-path ${CMAKE_BINARY_DIR}/share/swift/diagnostics/en.yaml --output-directory ${CMAKE_BINARY_DIR}/share/swift/diagnostics/ ) add_dependencies(swift-frontend diagnostic-database) +add_dependencies(diagnostic-database swift-serialize-diagnostics) swift_install_in_component( DIRECTORY ${CMAKE_BINARY_DIR}/share/swift/diagnostics/ diff --git a/localization/diagnostics/en.yaml b/localization/diagnostics/en.yaml index 8c3be67b2c0db..d8b545c646460 100644 --- a/localization/diagnostics/en.yaml +++ b/localization/diagnostics/en.yaml @@ -13,11821 +13,8309 @@ # This file defines the diagnostic messages for the English language. # Each diagnostic is described in the following format: # - id: -# msg: >- -# +# msg: "" +# +# The diagnostic message should be in double quotes and in one line, that +# means we will break the 80 characters line limit rule. That's mainly +# because currently `llvm::YAMLParser` doesn't support literal string +# folding, therefore we can't use YAML block scalars i.e. `>-`. # #===----------------------------------------------------------------------===# - id: invalid_diagnostic - msg: >- - INTERNAL ERROR: this diagnostic should not be produced + msg: "INTERNAL ERROR: this diagnostic should not be produced" - id: not_implemented - msg: >- - INTERNAL ERROR: feature not implemented: %0 + msg: "INTERNAL ERROR: feature not implemented: %0" - id: error_opening_output - msg: >- - error opening '%0' for output: %1 + msg: "error opening '%0' for output: %1" - id: cannot_find_group_info_file - msg: >- - cannot find group info file at path: '%0' + msg: "cannot find group info file at path: '%0'" - id: cannot_parse_group_info_file - msg: >- - cannot parse group info file at path: '%0' + msg: "cannot parse group info file at path: '%0'" - id: error_no_group_info - msg: >- - no group info found for file: '%0' + msg: "no group info found for file: '%0'" - id: previous_decldef - msg: >- - previous definition of %0 is here + msg: "previous definition of %0 is here" - id: brace_stmt_suggest_do - msg: >- - did you mean to use a 'do' statement? + msg: "did you mean to use a 'do' statement?" - id: while_parsing_as_left_angle_bracket - msg: >- - while parsing this '<' as a type parameter bracket + msg: "while parsing this '<' as a type parameter bracket" - id: remark_max_determinism_overriding - msg: >- - SWIFTC_MAXIMUM_DETERMINISM overriding %0 + msg: "SWIFTC_MAXIMUM_DETERMINISM overriding %0" - id: super_not_in_class_method - msg: >- - 'super' cannot be used outside of class members + msg: "'super' cannot be used outside of class members" - id: class_func_not_in_class - msg: >- - class methods are only allowed within classes; use 'static' to declare a - %select{static|requirement fulfilled by either a static or class}0 method + msg: "class methods are only allowed within classes; use 'static' to declare a %select{static|requirement fulfilled by either a static or class}0 method" - id: class_var_not_in_class - msg: >- - class properties are only allowed within classes; use 'static' to declare - a %select{static|requirement fulfilled by either a static or class}0 - property + msg: "class properties are only allowed within classes; use 'static' to declare a %select{static|requirement fulfilled by either a static or class}0 property" - id: class_subscript_not_in_class - msg: >- - class subscripts are only allowed within classes; use 'static' to declare - a %select{static|requirement fulfilled by either a static or class}0 - subscript + msg: "class subscripts are only allowed within classes; use 'static' to declare a %select{static|requirement fulfilled by either a static or class}0 subscript" - id: func_decl_without_brace - msg: >- - expected '{' in body of function declaration + msg: "expected '{' in body of function declaration" - id: convert_let_to_var - msg: >- - change 'let' to 'var' to make it mutable + msg: "change 'let' to 'var' to make it mutable" - id: note_typo_candidate - msg: >- - did you mean '%0'? + msg: "did you mean '%0'?" - id: profile_read_error - msg: >- - failed to load profile data '%0': '%1' + msg: "failed to load profile data '%0': '%1'" - id: protocol_extension_redundant_requirement - msg: >- - requirement of '%1' to '%2' is redundant in an extension of '%0' + msg: "requirement of '%1' to '%2' is redundant in an extension of '%0'" - id: attr_only_on_parameters - msg: >- - '%0' may only be used on parameters + msg: "'%0' may only be used on parameters" - id: function_type_no_parens - msg: >- - single argument function types require parentheses + msg: "single argument function types require parentheses" - id: error_underlying_module_not_found - msg: >- - underlying Objective-C module %0 not found + msg: "underlying Objective-C module %0 not found" - id: generic_signature_not_minimal - msg: >- - generic requirement '%0' is redundant in %1 + msg: "generic requirement '%0' is redundant in %1" - id: generic_signature_not_valid - msg: >- - generic signature %0 is invalid + msg: "generic signature %0 is invalid" - id: generic_signature_not_equal - msg: >- - generic signature %0 is not equal to new signature %1 + msg: "generic signature %0 is not equal to new signature %1" - id: sdk_node_unrecognized_key - msg: >- - unrecognized key '%0' in SDK node + msg: "unrecognized key '%0' in SDK node" - id: sdk_node_unrecognized_node_kind - msg: >- - unrecognized SDK node kind '%0' + msg: "unrecognized SDK node kind '%0'" - id: sdk_node_unrecognized_type_attr_kind - msg: >- - unrecognized type attribute '%0' in SDK node + msg: "unrecognized type attribute '%0' in SDK node" - id: sdk_node_unrecognized_decl_attr_kind - msg: >- - unrecognized declaration attribute '%0' in SDK node + msg: "unrecognized declaration attribute '%0' in SDK node" - id: sdk_node_unrecognized_decl_kind - msg: >- - unrecognized declaration kind '%0' in SDK node + msg: "unrecognized declaration kind '%0' in SDK node" - id: sdk_node_unrecognized_accessor_kind - msg: >- - unrecognized accessor kind '%0' in SDK node + msg: "unrecognized accessor kind '%0' in SDK node" - id: source_location_creates_file_id_conflicts - msg: >- - '#sourceLocation' directive produces '#fileID' string of '%0', which - conflicts with '#fileID' strings produced by other paths in the module + msg: "'#sourceLocation' directive produces '#fileID' string of '%0', which conflicts with '#fileID' strings produced by other paths in the module" - id: fixit_correct_source_location_file - msg: >- - change file in '#sourceLocation' to '%0' + msg: "change file in '#sourceLocation' to '%0'" + +- id: error_two_files_same_name + msg: "filename \"%0\" used twice: '%1' and '%2'" + +- id: note_explain_two_files_same_name + msg: "filenames are used to distinguish private declarations with the same name" - id: circular_reference - msg: >- - circular reference + msg: "circular reference" - id: circular_reference_through - msg: >- - through reference here + msg: "through reference here" - id: circular_class_inheritance - msg: >- - %0 inherits from itself + msg: "%0 inherits from itself" - id: circular_enum_inheritance - msg: >- - %0 has a raw type that depends on itself + msg: "%0 has a raw type that depends on itself" - id: circular_protocol_def - msg: >- - protocol %0 refines itself + msg: "protocol %0 refines itself" - id: kind_declname_declared_here - msg: >- - %0 %1 declared here + msg: "%0 %1 declared here" - id: warn_property_wrapper_module_scope - msg: >- - ignoring associated type %0 in favor of module-scoped property wrapper - %0; please qualify the reference with %1 + msg: "ignoring associated type %0 in favor of module-scoped property wrapper %0; please qualify the reference with %1" - id: circular_type_resolution_note - msg: >- - while resolving type %0 + msg: "while resolving type %0" - id: cannot_load_swiftoverlay_file - msg: >- - cannot load cross-import overlay for '%0' and '%1': %2 (declared by '%3') + msg: "cannot load cross-import overlay for '%0' and '%1': %2 (declared by '%3')" - id: cannot_list_swiftcrossimport_dir - msg: >- - cannot list cross-import overlays for '%0': %1 (declared in '%2') + msg: "cannot list cross-import overlays for '%0': %1 (declared in '%2')" - id: cross_imported_by_both_modules - msg: >- - modules %0 and %1 both declare module %2 as a cross-import overlay, which - may cause paradoxical behavior when looking up names in them; please report this - bug to the maintainers of these modules + msg: "modules %0 and %1 both declare module %2 as a cross-import overlay, which may cause paradoxical behavior when looking up names in them; please report this bug to the maintainers of these modules" + +- id: scanner_find_cycle + msg: "dependency scanner detected dependency cycle: '%0'" - id: opening_brace - msg: >- - to match this opening '{' + msg: "to match this opening '{'" - id: opening_bracket - msg: >- - to match this opening '[' + msg: "to match this opening '['" - id: opening_paren - msg: >- - to match this opening '(' + msg: "to match this opening '('" - id: opening_angle - msg: >- - to match this opening '<' + msg: "to match this opening '<'" - id: extra_rbrace - msg: >- - extraneous '}' at top level + msg: "extraneous '}' at top level" - id: structure_overflow - msg: >- - structure nesting level exceeded maximum of %0 + msg: "structure nesting level exceeded maximum of %0" - id: expected_close_to_if_directive - msg: >- - expected #else or #endif at end of conditional compilation block + msg: "expected #else or #endif at end of conditional compilation block" - id: expected_close_after_else_directive - msg: >- - further conditions after #else are unreachable + msg: "further conditions after #else are unreachable" - id: unexpected_conditional_compilation_block_terminator - msg: >- - unexpected conditional compilation block terminator + msg: "unexpected conditional compilation block terminator" - id: incomplete_conditional_compilation_directive - msg: >- - incomplete condition in conditional compilation directive + msg: "incomplete condition in conditional compilation directive" - id: extra_tokens_conditional_compilation_directive - msg: >- - extra tokens following conditional compilation directive + msg: "extra tokens following conditional compilation directive" - id: unexpected_rbrace_in_conditional_compilation_block - msg: >- - unexpected '}' in conditional compilation block + msg: "unexpected '}' in conditional compilation block" - id: unexpected_if_following_else_compilation_directive - msg: >- - unexpected 'if' keyword following '#else' conditional compilation - directive; did you mean '#elseif'? + msg: "unexpected 'if' keyword following '#else' conditional compilation directive; did you mean '#elseif'?" - id: pound_diagnostic_expected_string - msg: >- - expected string literal in %select{#warning|#error}0 directive + msg: "expected string literal in %select{#warning|#error}0 directive" - id: pound_diagnostic_expected - msg: >- - expected '%0' in %select{#warning|#error}1 directive + msg: "expected '%0' in %select{#warning|#error}1 directive" - id: pound_diagnostic_expected_parens - msg: >- - %select{#warning|#error}0 directive requires parentheses + msg: "%select{#warning|#error}0 directive requires parentheses" - id: pound_diagnostic_interpolation - msg: >- - string interpolation is not allowed in %select{#warning|#error}0 - directives + msg: "string interpolation is not allowed in %select{#warning|#error}0 directives" - id: extra_tokens_pound_diagnostic_directive - msg: >- - extra tokens following %select{#warning|#error}0 directive + msg: "extra tokens following %select{#warning|#error}0 directive" - id: sourceLocation_expected - msg: >- - expected '%0' in #sourceLocation directive + msg: "expected '%0' in #sourceLocation directive" - id: unexpected_line_directive - msg: >- - parameterless closing #sourceLocation() directive without prior opening - #sourceLocation(file:,line:) directive + msg: "parameterless closing #sourceLocation() directive without prior opening #sourceLocation(file:,line:) directive" - id: expected_line_directive_number - msg: >- - expected starting line number for #sourceLocation directive + msg: "expected starting line number for #sourceLocation directive" - id: expected_line_directive_name - msg: >- - expected filename string literal for #sourceLocation directive + msg: "expected filename string literal for #sourceLocation directive" - id: extra_tokens_line_directive - msg: >- - extra tokens at the end of #sourceLocation directive + msg: "extra tokens at the end of #sourceLocation directive" - id: line_directive_line_zero - msg: >- - the line number needs to be greater than zero + msg: "the line number needs to be greater than zero" - id: escaped_parameter_name - msg: >- - keyword '%0' does not need to be escaped in argument list + msg: "keyword '%0' does not need to be escaped in argument list" - id: forbidden_interpolated_string - msg: >- - %0 cannot be an interpolated string literal + msg: "%0 cannot be an interpolated string literal" - id: forbidden_extended_escaping_string - msg: >- - %0 cannot be an extended escaping string literal + msg: "%0 cannot be an extended escaping string literal" - id: lex_nul_character - msg: >- - nul character embedded in middle of file + msg: "nul character embedded in middle of file" - id: lex_utf16_bom_marker - msg: >- - input files must be encoded as UTF-8 instead of UTF-16 + msg: "input files must be encoded as UTF-8 instead of UTF-16" - id: lex_hashbang_not_allowed - msg: >- - hashbang line is allowed only in the main file + msg: "hashbang line is allowed only in the main file" - id: lex_unprintable_ascii_character - msg: >- - unprintable ASCII character found in source file + msg: "unprintable ASCII character found in source file" - id: lex_invalid_utf8 - msg: >- - invalid UTF-8 found in source file + msg: "invalid UTF-8 found in source file" - id: lex_single_quote_string - msg: >- - single-quoted string literal found, use '"' + msg: "single-quoted string literal found, use '\"'" - id: lex_invalid_curly_quote - msg: >- - unicode curly quote found, replace with '"' + msg: "unicode curly quote found, replace with '\"'" - id: lex_confusable_character - msg: >- - unicode character '%0' (%1) looks similar to '%2' (%3); did you mean to use '%2' (%3)? + msg: "unicode character '%0' (%1) looks similar to '%2' (%3); did you mean to use '%2' (%3)?" - id: lex_nonbreaking_space - msg: >- - non-breaking space (U+00A0) used instead of regular space + msg: "non-breaking space (U+00A0) used instead of regular space" - id: lex_unterminated_block_comment - msg: >- - unterminated '/*' comment + msg: "unterminated '/*' comment" - id: lex_comment_start - msg: >- - comment started here + msg: "comment started here" - id: lex_unterminated_string - msg: >- - unterminated string literal + msg: "unterminated string literal" - id: lex_invalid_escape - msg: >- - invalid escape sequence in literal + msg: "invalid escape sequence in literal" - id: lex_invalid_u_escape - msg: >- - \u{...} escape sequence expects between 1 and 8 hex digits + msg: "\\u{...} escape sequence expects between 1 and 8 hex digits" - id: lex_invalid_u_escape_rbrace - msg: >- - expected '}' in \u{...} escape sequence + msg: "expected '}' in \\u{...} escape sequence" - id: lex_invalid_escape_delimiter - msg: >- - too many '#' characters in delimited escape + msg: "too many '#' characters in delimited escape" - id: lex_invalid_closing_delimiter - msg: >- - too many '#' characters in closing delimiter + msg: "too many '#' characters in closing delimiter" - id: lex_invalid_unicode_scalar - msg: >- - invalid unicode scalar + msg: "invalid unicode scalar" - id: lex_unicode_escape_braces - msg: >- - expected hexadecimal code in braces after unicode escape + msg: "expected hexadecimal code in braces after unicode escape" - id: lex_illegal_multiline_string_start - msg: >- - multi-line string literal content must begin on a new line + msg: "multi-line string literal content must begin on a new line" - id: lex_illegal_multiline_string_end - msg: >- - multi-line string literal closing delimiter must begin on a new line + msg: "multi-line string literal closing delimiter must begin on a new line" - id: lex_multiline_string_indent_inconsistent - msg: >- - %select{unexpected space in|unexpected tab in|insufficient}2 indentation - of %select{line|next %1 lines}0 in multi-line string literal + msg: "%select{unexpected space in|unexpected tab in|insufficient}2 indentation of %select{line|next %1 lines}0 in multi-line string literal" - id: lex_multiline_string_indent_should_match_here - msg: >- - should match %select{space|tab}0 here + msg: "should match %select{space|tab}0 here" - id: lex_multiline_string_indent_change_line - msg: >- - change indentation of %select{this line|these lines}0 to match closing - delimiter + msg: "change indentation of %select{this line|these lines}0 to match closing delimiter" - id: lex_escaped_newline_at_lastline - msg: >- - escaped newline at the last line is not allowed + msg: "escaped newline at the last line is not allowed" - id: lex_invalid_character - msg: >- - invalid character in source file + msg: "invalid character in source file" - id: lex_invalid_identifier_start_character - msg: >- - an identifier cannot begin with this character + msg: "an identifier cannot begin with this character" - id: lex_expected_digit_in_fp_exponent - msg: >- - expected a digit in floating point exponent + msg: "expected a digit in floating point exponent" - id: lex_invalid_digit_in_fp_exponent - msg: >- - '%0' is not a valid %select{digit|first character}1 in floating point - exponent + msg: "'%0' is not a valid %select{digit|first character}1 in floating point exponent" - id: lex_invalid_digit_in_int_literal - msg: >- - '%0' is not a valid %select{binary digit (0 or 1)|octal digit - (0-7)|digit|hexadecimal digit (0-9, A-F)}1 in integer literal + msg: "'%0' is not a valid %select{binary digit (0 or 1)|octal digit (0-7)|digit|hexadecimal digit (0-9, A-F)}1 in integer literal" - id: lex_expected_binary_exponent_in_hex_float_literal - msg: >- - hexadecimal floating point literal must end with an exponent + msg: "hexadecimal floating point literal must end with an exponent" - id: lex_unexpected_block_comment_end - msg: >- - unexpected end of block comment + msg: "unexpected end of block comment" - id: lex_unary_equal - msg: >- - '=' must have consistent whitespace on both sides + msg: "'=' must have consistent whitespace on both sides" - id: extra_whitespace_period - msg: >- - extraneous whitespace after '.' is not permitted + msg: "extraneous whitespace after '.' is not permitted" - id: lex_editor_placeholder - msg: >- - editor placeholder in source file + msg: "editor placeholder in source file" - id: lex_editor_placeholder_in_playground - msg: >- - editor placeholder in source file + msg: "editor placeholder in source file" - id: lex_conflict_marker_in_file - msg: >- - source control conflict marker in source file + msg: "source control conflict marker in source file" - id: note_in_decl_extension - msg: >- - in %select{declaration|extension}0 of %1 + msg: "in %select{declaration|extension}0 of %1" - id: line_directive_style_deprecated - msg: >- - #line directive was renamed to #sourceLocation + msg: "#line directive was renamed to #sourceLocation" - id: declaration_same_line_without_semi - msg: >- - consecutive declarations on a line must be separated by ';' + msg: "consecutive declarations on a line must be separated by ';'" - id: expected_decl - msg: >- - expected declaration + msg: "expected declaration" - id: expected_identifier_in_decl - msg: >- - expected identifier in %0 declaration + msg: "expected identifier in %0 declaration" - id: expected_keyword_in_decl - msg: >- - expected '%0' keyword in %1 declaration + msg: "expected '%0' keyword in %1 declaration" - id: number_cant_start_decl_name - msg: >- - %0 name can only start with a letter or underscore, not a number + msg: "%0 name can only start with a letter or underscore, not a number" - id: expected_identifier_after_case_comma - msg: >- - expected identifier after comma in enum 'case' declaration + msg: "expected identifier after comma in enum 'case' declaration" - id: decl_redefinition - msg: >- - definition conflicts with previous value + msg: "definition conflicts with previous value" - id: let_cannot_be_computed_property - msg: >- - 'let' declarations cannot be computed properties + msg: "'let' declarations cannot be computed properties" - id: let_cannot_be_observing_property - msg: >- - 'let' declarations cannot be observing properties + msg: "'let' declarations cannot be observing properties" - id: let_cannot_be_addressed_property - msg: >- - 'let' declarations cannot have addressors + msg: "'let' declarations cannot have addressors" - id: disallowed_var_multiple_getset - msg: >- - 'var' declarations with multiple variables cannot have explicit - getters/setters + msg: "'var' declarations with multiple variables cannot have explicit getters/setters" - id: disallowed_init - msg: >- - initial value is not allowed here + msg: "initial value is not allowed here" - id: var_init_self_referential - msg: >- - variable used within its own initial value + msg: "variable used within its own initial value" - id: disallowed_enum_element - msg: >- - enum 'case' is not allowed outside of an enum + msg: "enum 'case' is not allowed outside of an enum" - id: decl_inner_scope - msg: >- - declaration is only valid at file scope + msg: "declaration is only valid at file scope" - id: decl_not_static - msg: >- - declaration cannot be marked %0 + msg: "declaration cannot be marked %0" - id: cskeyword_not_attribute - msg: >- - '%0' is a declaration modifier, not an attribute + msg: "'%0' is a declaration modifier, not an attribute" - id: decl_already_static - msg: >- - %0 cannot appear after another 'static' or 'class' keyword + msg: "%0 cannot appear after another 'static' or 'class' keyword" - id: enum_case_dot_prefix - msg: >- - extraneous '.' in enum 'case' declaration + msg: "extraneous '.' in enum 'case' declaration" - id: static_var_decl_global_scope - msg: >- - %select{%error|static properties|class properties}0 may only be declared - on a type + msg: "%select{%error|static properties|class properties}0 may only be declared on a type" - id: computed_property_no_accessors - msg: >- - %select{computed property|subscript}0 must have accessors specified + msg: "%select{computed property|subscript}0 must have accessors specified" - id: expected_getset_in_protocol - msg: >- - expected get or set in a protocol property + msg: "expected get or set in a protocol property" - id: computed_property_missing_type - msg: >- - computed property must have an explicit type + msg: "computed property must have an explicit type" - id: getset_nontrivial_pattern - msg: >- - getter/setter can only be defined for a single variable + msg: "getter/setter can only be defined for a single variable" - id: expected_rbrace_in_getset - msg: >- - expected '}' at end of variable get/set clause + msg: "expected '}' at end of variable get/set clause" - id: duplicate_accessor - msg: >- - %select{variable|subscript}0 already has %1 + msg: "%select{variable|subscript}0 already has %1" - id: conflicting_accessor - msg: >- - %select{variable|subscript}0 cannot provide both %1 and %2 + msg: "%select{variable|subscript}0 cannot provide both %1 and %2" - id: previous_accessor - msg: >- - %select{|previous definition of }1%0 %select{defined |}1here + msg: "%select{|previous definition of }1%0 %select{defined |}1here" - id: expected_accessor_parameter_name - msg: >- - expected %select{setter|willSet|didSet}0 parameter name + msg: "expected %select{setter|willSet|didSet}0 parameter name" - id: expected_rparen_set_name - msg: >- - expected ')' after setter parameter name + msg: "expected ')' after setter parameter name" - id: expected_rparen_willSet_name - msg: >- - expected ')' after willSet parameter name + msg: "expected ')' after willSet parameter name" - id: expected_rparen_didSet_name - msg: >- - expected ')' after didSet parameter name + msg: "expected ')' after didSet parameter name" - id: expected_lbrace_accessor - msg: >- - expected '{' to start %0 definition + msg: "expected '{' to start %0 definition" - id: expected_accessor_kw - msg: >- - expected 'get', 'set', 'willSet', or 'didSet' keyword to start an - accessor definition + msg: "expected 'get', 'set', 'willSet', or 'didSet' keyword to start an accessor definition" - id: missing_getter - msg: >- - %select{variable|subscript}0 with %1 must also have a getter + msg: "%select{variable|subscript}0 with %1 must also have a getter" - id: missing_reading_accessor - msg: >- - %select{variable|subscript}0 with %1 must also have a getter, addressor, - or 'read' accessor + msg: "%select{variable|subscript}0 with %1 must also have a getter, addressor, or 'read' accessor" - id: observing_accessor_conflicts_with_accessor - msg: >- - %select{'willSet'|'didSet'}0 cannot be provided together with %1 + msg: "%select{'willSet'|'didSet'}0 cannot be provided together with %1" - id: observing_accessor_in_subscript - msg: >- - %select{'willSet'|'didSet'}0 is not allowed in subscripts + msg: "%select{'willSet'|'didSet'}0 is not allowed in subscripts" - id: getset_cannot_be_implied - msg: >- - variable with implied type cannot have implied getter/setter + msg: "variable with implied type cannot have implied getter/setter" - id: decl_expected_module_name - msg: >- - expected module name in import declaration + msg: "expected module name in import declaration" - id: expected_lbrace_extension - msg: >- - expected '{' in extension + msg: "expected '{' in extension" - id: expected_rbrace_extension - msg: >- - expected '}' at end of extension + msg: "expected '}' at end of extension" - id: extension_type_expected - msg: >- - expected type name in extension declaration + msg: "expected type name in extension declaration" - id: expected_equal_in_typealias - msg: >- - expected '=' in type alias declaration + msg: "expected '=' in type alias declaration" - id: expected_type_in_typealias - msg: >- - expected type in type alias declaration + msg: "expected type in type alias declaration" - id: expected_type_in_associatedtype - msg: >- - expected type in associated type declaration + msg: "expected type in associated type declaration" - id: associated_type_generic_parameter_list - msg: >- - associated types must not have a generic parameter list + msg: "associated types must not have a generic parameter list" - id: func_decl_without_paren - msg: >- - expected '(' in argument list of function declaration + msg: "expected '(' in argument list of function declaration" - id: static_func_decl_global_scope - msg: >- - %select{%error|static methods|class methods}0 may only be declared on a - type + msg: "%select{%error|static methods|class methods}0 may only be declared on a type" - id: func_decl_expected_arrow - msg: >- - expected '->' after function parameter tuple + msg: "expected '->' after function parameter tuple" - id: operator_static_in_protocol - msg: >- - operator '%0' declared in protocol must be 'static' + msg: "operator '%0' declared in protocol must be 'static'" - id: expected_lbrace_enum - msg: >- - expected '{' in enum + msg: "expected '{' in enum" - id: expected_rbrace_enum - msg: >- - expected '}' at end of enum + msg: "expected '}' at end of enum" - id: expected_lbrace_struct - msg: >- - expected '{' in struct + msg: "expected '{' in struct" - id: expected_rbrace_struct - msg: >- - expected '}' in struct + msg: "expected '}' in struct" - id: expected_lbrace_class - msg: >- - expected '{' in class + msg: "expected '{' in class" - id: expected_rbrace_class - msg: >- - expected '}' in class + msg: "expected '}' in class" - id: expected_colon_class - msg: >- - expected ':' to begin inheritance clause + msg: "expected ':' to begin inheritance clause" - id: generic_arguments_protocol - msg: >- - protocols do not allow generic parameters; use associated types instead + msg: "protocols do not allow generic parameters; use associated types instead" - id: expected_lbrace_protocol - msg: >- - expected '{' in protocol type + msg: "expected '{' in protocol type" - id: expected_rbrace_protocol - msg: >- - expected '}' in protocol + msg: "expected '}' in protocol" - id: protocol_setter_name - msg: >- - setter in a protocol cannot have a name + msg: "setter in a protocol cannot have a name" - id: protocol_method_with_body - msg: >- - protocol methods must not have bodies + msg: "protocol methods must not have bodies" - id: protocol_init_with_body - msg: >- - protocol initializers must not have bodies + msg: "protocol initializers must not have bodies" - id: subscript_decl_wrong_scope - msg: >- - 'subscript' functions may only be declared within a type + msg: "'subscript' functions may only be declared within a type" - id: expected_lparen_subscript - msg: >- - expected '(' for subscript parameters + msg: "expected '(' for subscript parameters" - id: subscript_has_name - msg: >- - subscripts cannot have a name + msg: "subscripts cannot have a name" - id: expected_arrow_subscript - msg: >- - expected '->' for subscript element type + msg: "expected '->' for subscript element type" - id: expected_type_subscript - msg: >- - expected subscripting element type + msg: "expected subscripting element type" - id: expected_lbrace_subscript - msg: >- - expected '{' in subscript to specify getter and setter implementation + msg: "expected '{' in subscript to specify getter and setter implementation" - id: expected_lbrace_subscript_protocol - msg: >- - subscript in protocol must have explicit { get } or { get set } specifier + msg: "subscript in protocol must have explicit { get } or { get set } specifier" - id: subscript_without_get - msg: >- - subscript declarations must have a getter + msg: "subscript declarations must have a getter" - id: invalid_nested_init - msg: >- - missing '%select{super.|self.}0' at initializer invocation + msg: "missing '%select{super.|self.}0' at initializer invocation" - id: initializer_decl_wrong_scope - msg: >- - initializers may only be declared within a type + msg: "initializers may only be declared within a type" - id: expected_lparen_initializer - msg: >- - expected '(' for initializer parameters + msg: "expected '(' for initializer parameters" - id: initializer_has_name - msg: >- - initializers cannot have a name + msg: "initializers cannot have a name" - id: destructor_decl_outside_class - msg: >- - deinitializers may only be declared within a class + msg: "deinitializers may only be declared within a class" - id: expected_lbrace_destructor - msg: >- - expected '{' for deinitializer + msg: "expected '{' for deinitializer" - id: destructor_has_name - msg: >- - deinitializers cannot have a name + msg: "deinitializers cannot have a name" - id: opened_destructor_expected_rparen - msg: >- - expected ')' to close parameter list + msg: "expected ')' to close parameter list" - id: destructor_params - msg: >- - no parameter clause allowed on deinitializer + msg: "no parameter clause allowed on deinitializer" - id: operator_decl_inner_scope - msg: >- - 'operator' may only be declared at file scope + msg: "'operator' may only be declared at file scope" - id: expected_operator_name_after_operator - msg: >- - expected operator name in operator declaration + msg: "expected operator name in operator declaration" - id: identifier_within_operator_name - msg: >- - '%0' is considered an identifier and must not appear within an operator - name + msg: "'%0' is considered an identifier and must not appear within an operator name" - id: operator_name_invalid_char - msg: >- - '%0' is not allowed in operator names + msg: "'%0' is not allowed in operator names" - id: postfix_operator_name_cannot_start_with_unwrap - msg: >- - postfix operator names starting with '?' or '!' are disallowed to avoid - collisions with built-in unwrapping operators + msg: "postfix operator names starting with '?' or '!' are disallowed to avoid collisions with built-in unwrapping operators" - id: deprecated_operator_body - msg: >- - operator should no longer be declared with body + msg: "operator should no longer be declared with body" - id: deprecated_operator_body_use_group - msg: >- - operator should no longer be declared with body; use a precedence group - instead + msg: "operator should no longer be declared with body; use a precedence group instead" - id: operator_decl_no_fixity - msg: >- - operator must be declared as 'prefix', 'postfix', or 'infix' + msg: "operator must be declared as 'prefix', 'postfix', or 'infix'" - id: operator_decl_expected_type - msg: >- - expected designated type in operator declaration + msg: "expected designated type in operator declaration" - id: operator_decl_trailing_comma - msg: >- - trailing comma in operator declaration + msg: "trailing comma in operator declaration" - id: precedencegroup_not_infix - msg: >- - only infix operators may declare a precedence + msg: "only infix operators may declare a precedence" - id: expected_precedencegroup_name - msg: >- - expected identifier after 'precedencegroup' + msg: "expected identifier after 'precedencegroup'" - id: expected_precedencegroup_lbrace - msg: >- - expected '{' after name of precedence group + msg: "expected '{' after name of precedence group" - id: expected_precedencegroup_attribute - msg: >- - expected operator attribute identifier in precedence group body + msg: "expected operator attribute identifier in precedence group body" - id: unknown_precedencegroup_attribute - msg: >- - '%0' is not a valid precedence group attribute + msg: "'%0' is not a valid precedence group attribute" - id: expected_precedencegroup_attribute_colon - msg: >- - expected colon after attribute name in precedence group + msg: "expected colon after attribute name in precedence group" - id: precedencegroup_attribute_redeclared - msg: >- - '%0' attribute for precedence group declared multiple times + msg: "'%0' attribute for precedence group declared multiple times" - id: expected_precedencegroup_associativity - msg: >- - expected 'none', 'left', or 'right' after 'associativity' + msg: "expected 'none', 'left', or 'right' after 'associativity'" - id: expected_precedencegroup_assignment - msg: >- - expected 'true' or 'false' after 'assignment' + msg: "expected 'true' or 'false' after 'assignment'" - id: expected_precedencegroup_relation - msg: >- - expected name of related precedence group after '%0' + msg: "expected name of related precedence group after '%0'" - id: expected_sil_keyword - msg: >- - expected SIL keyword + msg: "expected SIL keyword" - id: inout_not_attribute - msg: >- - @inout is no longer an attribute + msg: "@inout is no longer an attribute" - id: only_allowed_in_sil - msg: >- - '%0' only allowed in SIL modules + msg: "'%0' only allowed in SIL modules" - id: expected_sil_type - msg: >- - expected type in SIL code + msg: "expected type in SIL code" - id: expected_sil_colon_value_ref - msg: >- - expected ':' before type in SIL value reference + msg: "expected ':' before type in SIL value reference" - id: expected_sil_value_name - msg: >- - expected SIL value name + msg: "expected SIL value name" - id: expected_sil_type_kind - msg: >- - expected SIL type to %0 + msg: "expected SIL type to %0" - id: expected_sil_constant - msg: >- - expected constant in SIL code + msg: "expected constant in SIL code" - id: referenced_value_no_accessor - msg: >- - referenced declaration has no %select{getter|setter}0 + msg: "referenced declaration has no %select{getter|setter}0" - id: expected_sil_value_ownership_kind - msg: >- - expected value ownership kind in SIL code + msg: "expected value ownership kind in SIL code" - id: silfunc_and_silarg_have_incompatible_sil_value_ownership - msg: >- - SILFunction and SILArgument have mismatching ValueOwnershipKinds. - Function type specifies: '@%0'. SIL argument specifies: '@%1'. + msg: "SILFunction and SILArgument have mismatching ValueOwnershipKinds. Function type specifies: '@%0'. SIL argument specifies: '@%1'." - id: expected_sil_colon - msg: >- - expected ':' before %0 + msg: "expected ':' before %0" - id: expected_sil_tuple_index - msg: >- - expected tuple element index + msg: "expected tuple element index" - id: invalid_index_subset - msg: >- - invalid index subset; expected '[SU]+' where 'S' represents set indices - and 'U' represents unset indices + msg: "invalid index subset; expected '[SU]+' where 'S' represents set indices and 'U' represents unset indices" - id: sil_value_redefinition - msg: >- - redefinition of value '%0' + msg: "redefinition of value '%0'" - id: sil_value_use_type_mismatch - msg: >- - value '%0' defined with mismatching type %1 (expected %2) + msg: "value '%0' defined with mismatching type %1 (expected %2)" - id: sil_value_def_type_mismatch - msg: >- - value '%0' used with mismatching type %1 (expected %2) + msg: "value '%0' used with mismatching type %1 (expected %2)" - id: sil_use_of_undefined_value - msg: >- - use of undefined value '%0' + msg: "use of undefined value '%0'" - id: sil_prior_reference - msg: >- - prior reference was here + msg: "prior reference was here" - id: expected_colon_in_sil_location - msg: >- - expected ':' in SIL location + msg: "expected ':' in SIL location" - id: sil_invalid_line_in_sil_location - msg: >- - line number must be a positive integer + msg: "line number must be a positive integer" - id: sil_invalid_column_in_sil_location - msg: >- - column number must be a positive integer + msg: "column number must be a positive integer" - id: sil_invalid_scope_slot - msg: >- - scope number must be a positive integer + msg: "scope number must be a positive integer " - id: sil_scope_undeclared - msg: >- - scope number %0 needs to be declared before first use + msg: "scope number %0 needs to be declared before first use" - id: sil_scope_redefined - msg: >- - scope number %0 is already defined + msg: "scope number %0 is already defined" - id: expected_sil_instr_start_of_line - msg: >- - SIL instructions must be at the start of a line + msg: "SIL instructions must be at the start of a line" - id: expected_equal_in_sil_instr - msg: >- - expected '=' in SIL instruction + msg: "expected '=' in SIL instruction" - id: wrong_result_count_in_sil_instr - msg: >- - wrong number of results for SIL instruction, expected %0 + msg: "wrong number of results for SIL instruction, expected %0" - id: expected_sil_instr_opcode - msg: >- - expected SIL instruction opcode + msg: "expected SIL instruction opcode" - id: expected_tok_in_sil_instr - msg: >- - expected '%0' in SIL instruction + msg: "expected '%0' in SIL instruction" - id: sil_property_generic_signature_mismatch - msg: >- - sil_property generic signature must match original declaration + msg: "sil_property generic signature must match original declaration" - id: sil_string_no_encoding - msg: >- - string_literal instruction requires an encoding + msg: "string_literal instruction requires an encoding" - id: sil_string_invalid_encoding - msg: >- - unknown string literal encoding '%0' + msg: "unknown string literal encoding '%0'" - id: expected_tuple_type_in_tuple - msg: >- - tuple instruction requires a tuple type + msg: "tuple instruction requires a tuple type" - id: sil_tuple_inst_wrong_value_count - msg: >- - tuple instruction requires %0 values + msg: "tuple instruction requires %0 values" - id: sil_tuple_inst_wrong_field - msg: >- - tuple instruction requires a field number + msg: "tuple instruction requires a field number" - id: sil_struct_inst_wrong_field - msg: >- - struct instruction requires a field name + msg: "struct instruction requires a field name" - id: sil_ref_inst_wrong_field - msg: >- - ref_element_addr instruction requires a field name + msg: "ref_element_addr instruction requires a field name" - id: sil_invalid_instr_operands - msg: >- - invalid instruction operands + msg: "invalid instruction operands" - id: sil_operand_not_address - msg: >- - %0 operand of '%1' must have address type + msg: "%0 operand of '%1' must have address type" - id: sil_operand_not_ref_storage_address - msg: >- - %0 operand of '%1' must have address of %2 type + msg: "%0 operand of '%1' must have address of %2 type" - id: sil_integer_literal_not_integer_type - msg: >- - integer_literal instruction requires a 'Builtin.Int' type + msg: "integer_literal instruction requires a 'Builtin.Int' type" - id: sil_integer_literal_not_well_formed - msg: >- - integer_literal value not well-formed for type %0 + msg: "integer_literal value not well-formed for type %0" - id: sil_float_literal_not_float_type - msg: >- - float_literal instruction requires a 'Builtin.FP' type + msg: "float_literal instruction requires a 'Builtin.FP' type" - id: sil_substitutions_on_non_polymorphic_type - msg: >- - apply of non-polymorphic function cannot have substitutions + msg: "apply of non-polymorphic function cannot have substitutions" - id: sil_witness_method_not_protocol - msg: >- - witness_method is not a protocol method + msg: "witness_method is not a protocol method" - id: sil_witness_method_type_does_not_conform - msg: >- - witness_method type does not conform to protocol + msg: "witness_method type does not conform to protocol" - id: sil_member_decl_not_found - msg: >- - member not found + msg: "member not found" - id: sil_named_member_decl_not_found - msg: >- - member %0 not found in type %1 + msg: "member %0 not found in type %1" - id: sil_member_lookup_bad_type - msg: >- - cannot lookup member %0 in non-nominal, non-module type %1 + msg: "cannot lookup member %0 in non-nominal, non-module type %1" - id: sil_member_decl_type_mismatch - msg: >- - member defined with mismatching type %0 (expected %1) + msg: "member defined with mismatching type %0 (expected %1)" - id: sil_substitution_mismatch - msg: >- - substitution replacement type %0 does not conform to protocol %1 + msg: "substitution replacement type %0 does not conform to protocol %1" - id: sil_not_class - msg: >- - substitution replacement type %0 is not a class type + msg: "substitution replacement type %0 is not a class type" - id: sil_missing_substitutions - msg: >- - missing substitutions + msg: "missing substitutions" - id: sil_too_many_substitutions - msg: >- - too many substitutions + msg: "too many substitutions" - id: sil_dbg_unknown_key - msg: >- - unknown key '%0' in debug variable declaration + msg: "unknown key '%0' in debug variable declaration" - id: sil_objc_with_tail_elements - msg: >- - alloc_ref [objc] cannot have tail allocated elements + msg: "alloc_ref [objc] cannot have tail allocated elements" - id: sil_expected_access_kind - msg: >- - %0 instruction must have explicit access kind + msg: "%0 instruction must have explicit access kind" - id: sil_expected_access_enforcement - msg: >- - %0 instruction must have explicit access enforcement + msg: "%0 instruction must have explicit access enforcement" - id: sil_keypath_expected_component_kind - msg: >- - expected keypath component kind + msg: "expected keypath component kind" - id: sil_keypath_unknown_component_kind - msg: >- - unknown keypath component kind %0 + msg: "unknown keypath component kind %0" - id: sil_keypath_computed_property_missing_part - msg: >- - keypath %select{gettable|settable}0_property component needs an - %select{id and getter|id, getter, and setter}0 + msg: "keypath %select{gettable|settable}0_property component needs an %select{id and getter|id, getter, and setter}0" - id: sil_keypath_no_root - msg: >- - keypath must have a root component declared + msg: "keypath must have a root component declared" - id: sil_keypath_index_not_hashable - msg: >- - key path index type %0 does not conform to Hashable + msg: "key path index type %0 does not conform to Hashable" - id: sil_keypath_index_operand_type_conflict - msg: >- - conflicting types for key path operand %0: %1 vs. %2 + msg: "conflicting types for key path operand %0: %1 vs. %2" - id: sil_keypath_no_use_of_operand_in_pattern - msg: >- - operand %0 is not referenced by any component in the pattern + msg: "operand %0 is not referenced by any component in the pattern" - id: expected_sil_block_name - msg: >- - expected basic block name or '}' + msg: "expected basic block name or '}'" - id: expected_sil_block_colon - msg: >- - expected ':' after basic block name + msg: "expected ':' after basic block name" - id: sil_undefined_basicblock_use - msg: >- - use of undefined basic block %0 + msg: "use of undefined basic block %0" - id: sil_basicblock_redefinition - msg: >- - redefinition of basic block %0 + msg: "redefinition of basic block %0" - id: sil_basicblock_arg_rparen - msg: >- - expected ')' in basic block argument list + msg: "expected ')' in basic block argument list" - id: expected_sil_function_name - msg: >- - expected SIL function name + msg: "expected SIL function name" - id: expected_sil_rbrace - msg: >- - expected '}' at the end of a sil body + msg: "expected '}' at the end of a sil body" - id: expected_sil_function_type - msg: >- - sil function expected to have SIL function type + msg: "sil function expected to have SIL function type" - id: sil_dynamically_replaced_func_not_found - msg: >- - dynamically replaced function not found %0 + msg: "dynamically replaced function not found %0" - id: sil_availability_expected_version - msg: >- - expected version number in 'available' attribute + msg: "expected version number in 'available' attribute" - id: expected_sil_stage_name - msg: >- - expected 'raw' or 'canonical' after 'sil_stage' + msg: "expected 'raw' or 'canonical' after 'sil_stage'" - id: multiple_sil_stage_decls - msg: >- - sil_stage declared multiple times + msg: "sil_stage declared multiple times" - id: expected_sil_vtable_colon - msg: >- - expected ':' in a vtable entry + msg: "expected ':' in a vtable entry" - id: sil_vtable_func_not_found - msg: >- - sil function not found %0 + msg: "sil function not found %0" - id: sil_vtable_class_not_found - msg: >- - sil class not found %0 + msg: "sil class not found %0" - id: sil_vtable_bad_entry_kind - msg: >- - expected 'inherited' or 'override' + msg: "expected 'inherited' or 'override'" - id: sil_vtable_expect_rsquare - msg: >- - expected ']' after vtable entry kind + msg: "expected ']' after vtable entry kind" - id: sil_global_variable_not_found - msg: >- - sil global not found %0 + msg: "sil global not found %0" - id: expected_sil_witness_colon - msg: >- - expected ':' in a witness table + msg: "expected ':' in a witness table" - id: expected_sil_witness_lparen - msg: >- - expected '(' in a witness table + msg: "expected '(' in a witness table" - id: expected_sil_witness_rparen - msg: >- - expected ')' in a witness table + msg: "expected ')' in a witness table" - id: sil_witness_func_not_found - msg: >- - sil function not found %0 + msg: "sil function not found %0" - id: sil_witness_protocol_not_found - msg: >- - sil protocol not found %0 + msg: "sil protocol not found %0" - id: sil_witness_assoc_not_found - msg: >- - sil associated type decl not found %0 + msg: "sil associated type decl not found %0" - id: sil_witness_assoc_conf_not_found - msg: >- - sil associated type path for conformance not found %0 + msg: "sil associated type path for conformance not found %0" - id: sil_witness_protocol_conformance_not_found - msg: >- - sil protocol conformance not found + msg: "sil protocol conformance not found" - id: sil_diff_witness_expected_token - msg: >- - expected '%0' in differentiability witness + msg: "expected '%0' in differentiability witness" - id: sil_diff_witness_serialized_declaration - msg: >- - differentiability witness declaration should not be serialized + msg: "differentiability witness declaration should not be serialized" - id: sil_diff_witness_undefined - msg: >- - reference to undefined differentiability witness + msg: "reference to undefined differentiability witness" - id: sil_diff_witness_invalid_generic_signature - msg: >- - expected witness generic signature '%0' does not have same generic - parameters as original function generic signature '%1' + msg: "expected witness generic signature '%0' does not have same generic parameters as original function generic signature '%1'" - id: sil_coverage_invalid_hash - msg: >- - expected coverage hash + msg: "expected coverage hash" - id: sil_coverage_expected_lbrace - msg: >- - expected '{' in coverage map + msg: "expected '{' in coverage map" - id: sil_coverage_expected_loc - msg: >- - expected line:column pair + msg: "expected line:column pair" - id: sil_coverage_expected_arrow - msg: >- - expected '->' after start location + msg: "expected '->' after start location" - id: sil_coverage_expected_colon - msg: >- - expected ':' after source range + msg: "expected ':' after source range" - id: sil_coverage_invalid_counter - msg: >- - expected counter expression, id, or 'zero' + msg: "expected counter expression, id, or 'zero'" - id: sil_coverage_expected_rparen - msg: >- - expected ')' to end counter expression + msg: "expected ')' to end counter expression" - id: sil_coverage_expected_quote - msg: >- - expected quotes surrounding PGO function name + msg: "expected quotes surrounding PGO function name" - id: sil_coverage_invalid_operator - msg: >- - expected '+' or '-' + msg: "expected '+' or '-'" - id: expected_type - msg: >- - expected type + msg: "expected type" - id: expected_init_value - msg: >- - expected initial value after '=' + msg: "expected initial value after '='" - id: expected_identifier_in_dotted_type - msg: >- - expected identifier in dotted type + msg: "expected identifier in dotted type" - id: expected_identifier_for_type - msg: >- - expected identifier for type name + msg: "expected identifier for type name" - id: expected_rangle_generic_arg_list - msg: >- - expected '>' to complete generic argument list + msg: "expected '>' to complete generic argument list" - id: expected_type_function_result - msg: >- - expected type for function result + msg: "expected type for function result" - id: generic_non_function - msg: >- - only syntactic function types can be generic + msg: "only syntactic function types can be generic" - id: rethrowing_function_type - msg: >- - only function declarations may be marked 'rethrows'; did you mean - 'throws'? + msg: "only function declarations may be marked 'rethrows'; did you mean 'throws'?" - id: async_or_throws_in_wrong_position - msg: >- - %select{'throws'|'rethrows'|'async'}0 may only occur before '->' + msg: "%select{'throws'|'rethrows'|'async'}0 may only occur before '->'" - id: throw_in_function_type - msg: >- - expected throwing specifier; did you mean 'throws'? + msg: "expected throwing specifier; did you mean 'throws'?" - id: expected_type_before_arrow - msg: >- - expected type before '->' + msg: "expected type before '->'" - id: expected_type_after_arrow - msg: >- - expected type after '->' + msg: "expected type after '->'" - id: function_type_argument_label - msg: >- - function types cannot have argument labels; use '_' before %0 + msg: "function types cannot have argument labels; use '_' before %0" - id: expected_dynamic_func_attr - msg: >- - expected a dynamically_replaceable function + msg: "expected a dynamically_replaceable function" + +- id: async_after_throws + msg: "'async' must precede %select{'throws'|'rethrows'}0" + +- id: async_init + msg: "initializer cannot be marked 'async'" - id: expected_expr_enum_case_raw_value - msg: >- - expected expression after '=' in 'case' + msg: "expected expression after '=' in 'case'" - id: nonliteral_enum_case_raw_value - msg: >- - raw value for enum case must be a literal + msg: "raw value for enum case must be a literal" - id: new_array_syntax - msg: >- - array types are now written with the brackets around the element type + msg: "array types are now written with the brackets around the element type" - id: expected_rbracket_array_type - msg: >- - expected ']' in array type + msg: "expected ']' in array type" - id: expected_element_type - msg: >- - expected element type + msg: "expected element type" - id: expected_dictionary_value_type - msg: >- - expected dictionary value type + msg: "expected dictionary value type" - id: expected_rbracket_dictionary_type - msg: >- - expected ']' in dictionary type + msg: "expected ']' in dictionary type" - id: extra_rbracket - msg: >- - unexpected ']' in type; did you mean to write an array type? + msg: "unexpected ']' in type; did you mean to write an array type?" - id: extra_colon - msg: >- - unexpected ':' in type; did you mean to write a dictionary type? + msg: "unexpected ':' in type; did you mean to write a dictionary type?" - id: subscript_array_element - msg: >- - unexpected subscript in array literal; did you mean to write two separate - elements instead? + msg: "unexpected subscript in array literal; did you mean to write two separate elements instead?" - id: subscript_array_element_fix_it_add_comma - msg: >- - add a separator between the elements + msg: "add a separator between the elements" - id: subscript_array_element_fix_it_remove_space - msg: >- - remove the space between the elements to silence this warning + msg: "remove the space between the elements to silence this warning" - id: expected_rparen_tuple_type_list - msg: >- - expected ')' at end of tuple list + msg: "expected ')' at end of tuple list" - id: multiple_ellipsis_in_tuple - msg: >- - only a single element can be variadic + msg: "only a single element can be variadic" - id: tuple_type_init - msg: >- - default argument not permitted in a tuple type + msg: "default argument not permitted in a tuple type" - id: protocol_method_argument_init - msg: >- - default argument not permitted in a protocol method + msg: "default argument not permitted in a protocol method" - id: protocol_init_argument_init - msg: >- - default argument not permitted in a protocol initializer + msg: "default argument not permitted in a protocol initializer" - id: tuple_type_multiple_labels - msg: >- - tuple element cannot have two labels + msg: "tuple element cannot have two labels" - id: expected_rangle_protocol - msg: >- - expected '>' to complete protocol-constrained type + msg: "expected '>' to complete protocol-constrained type" - id: deprecated_protocol_composition - msg: >- - 'protocol<...>' composition syntax has been removed; join the protocols - using '&' + msg: "'protocol<...>' composition syntax has been removed; join the protocols using '&'" - id: deprecated_protocol_composition_single - msg: >- - 'protocol<...>' composition syntax has been removed and is not needed - here + msg: "'protocol<...>' composition syntax has been removed and is not needed here" - id: deprecated_any_composition - msg: >- - 'protocol<>' syntax has been removed; use 'Any' instead + msg: "'protocol<>' syntax has been removed; use 'Any' instead" - id: sil_box_expected_var_or_let - msg: >- - expected 'var' or 'let' to introduce SIL box field type + msg: "expected 'var' or 'let' to introduce SIL box field type" - id: sil_box_expected_r_brace - msg: >- - expected '}' to complete SIL box field type list + msg: "expected '}' to complete SIL box field type list" - id: sil_box_expected_r_angle - msg: >- - expected '>' to complete SIL box generic argument list + msg: "expected '>' to complete SIL box generic argument list" - id: sil_function_subst_expected_l_angle - msg: >- - expected '<' to begin SIL function type substitution list after 'for' + msg: "expected '<' to begin SIL function type substitution list after 'for'" - id: sil_function_subst_expected_r_angle - msg: >- - expected '>' to end SIL function type substitution list after 'for <...' + msg: "expected '>' to end SIL function type substitution list after 'for <...'" - id: sil_function_subst_expected_generics - msg: >- - expected '<' to begin substituted parameter list after '@substituted' + msg: "expected '<' to begin substituted parameter list after '@substituted'" - id: sil_function_subst_expected_function - msg: >- - expected function type after '@substituted' + msg: "expected function type after '@substituted'" - id: sil_function_subst_expected_subs - msg: >- - expected 'for' to begin substitutions after '@substituted' function type + msg: "expected 'for' to begin substitutions after '@substituted' function type" - id: sil_function_subs_without_generics - msg: >- - unexpected 'for' to begin substitutions after non-generic function type + msg: "unexpected 'for' to begin substitutions after non-generic function type" - id: opaque_mid_composition - msg: >- - 'some' should appear at the beginning of a composition + msg: "'some' should appear at the beginning of a composition" - id: layout_size_should_be_positive - msg: >- - expected non-negative size to be specified in layout constraint + msg: "expected non-negative size to be specified in layout constraint" - id: layout_alignment_should_be_positive - msg: >- - expected non-negative alignment to be specified in layout constraint + msg: "expected non-negative alignment to be specified in layout constraint" - id: expected_rparen_layout_constraint - msg: >- - expected ')' to complete layout constraint + msg: "expected ')' to complete layout constraint" - id: layout_constraints_only_inside_specialize_attr - msg: >- - layout constraints are only allowed inside '_specialize' attributes + msg: "layout constraints are only allowed inside '_specialize' attributes" - id: expected_pattern - msg: >- - expected pattern + msg: "expected pattern" - id: keyword_cant_be_identifier - msg: >- - keyword '%0' cannot be used as an identifier here + msg: "keyword '%0' cannot be used as an identifier here" - id: repeated_identifier - msg: >- - found an unexpected second identifier in %0 declaration; is there an - accidental break? + msg: "found an unexpected second identifier in %0 declaration; is there an accidental break?" - id: join_identifiers - msg: >- - join the identifiers together + msg: "join the identifiers together" - id: join_identifiers_camel_case - msg: >- - join the identifiers together with camel-case + msg: "join the identifiers together with camel-case" - id: backticks_to_escape - msg: >- - if this name is unavoidable, use backticks to escape it + msg: "if this name is unavoidable, use backticks to escape it" - id: expected_rparen_tuple_pattern_list - msg: >- - expected ')' at end of tuple pattern + msg: "expected ')' at end of tuple pattern" - id: untyped_pattern_ellipsis - msg: >- - '...' cannot be applied to a subpattern which is not explicitly typed + msg: "'...' cannot be applied to a subpattern which is not explicitly typed" - id: no_default_arg_closure - msg: >- - default arguments are not allowed in closures + msg: "default arguments are not allowed in closures" - id: no_default_arg_curried - msg: >- - default arguments are not allowed in curried parameter lists + msg: "default arguments are not allowed in curried parameter lists" - id: var_pattern_in_var - msg: >- - '%select{var|let}0' cannot appear nested inside another 'var' or 'let' - pattern + msg: "'%select{var|let}0' cannot appear nested inside another 'var' or 'let' pattern" - id: extra_var_in_multiple_pattern_list - msg: >- - %0 must be bound in every pattern + msg: "%0 must be bound in every pattern" - id: let_pattern_in_immutable_context - msg: >- - 'let' pattern cannot appear nested in an already immutable context + msg: "'let' pattern cannot appear nested in an already immutable context" - id: specifier_must_have_type - msg: >- - %0 arguments must have a type specified + msg: "%0 arguments must have a type specified" - id: expected_rparen_parameter - msg: >- - expected ')' in parameter + msg: "expected ')' in parameter" - id: expected_parameter_type - msg: >- - expected parameter type following ':' + msg: "expected parameter type following ':'" - id: expected_parameter_name - msg: >- - expected parameter name followed by ':' + msg: "expected parameter name followed by ':'" - id: expected_parameter_colon - msg: >- - expected ':' following argument label and parameter name + msg: "expected ':' following argument label and parameter name" - id: expected_assignment_instead_of_comparison_operator - msg: >- - expected '=' instead of '==' to assign default value for parameter + msg: "expected '=' instead of '==' to assign default value for parameter" - id: multiple_parameter_ellipsis - msg: >- - only a single variadic parameter '...' is permitted + msg: "only a single variadic parameter '...' is permitted" - id: parameter_vararg_default - msg: >- - variadic parameter cannot have a default value + msg: "variadic parameter cannot have a default value" - id: parameter_specifier_as_attr_disallowed - msg: >- - '%0' before a parameter name is not allowed, place it before the - parameter type instead + msg: "'%0' before a parameter name is not allowed, place it before the parameter type instead" - id: parameter_specifier_repeated - msg: >- - parameter must not have multiple '__owned', 'inout', or '__shared' - specifiers + msg: "parameter must not have multiple '__owned', 'inout', or '__shared' specifiers" - id: parameter_let_var_as_attr - msg: >- - '%0' in this position is interpreted as an argument label + msg: "'%0' in this position is interpreted as an argument label" - id: parameter_extraneous_double_up - msg: >- - extraneous duplicate parameter name; %0 already has an argument label + msg: "extraneous duplicate parameter name; %0 already has an argument label" - id: parameter_operator_keyword_argument - msg: >- - %select{operator|closure|enum case}0 cannot have keyword arguments + msg: "%select{operator|closure|enum case}0 cannot have keyword arguments" - id: parameter_unnamed - msg: >- - unnamed parameters must be written with the empty name '_' + msg: "unnamed parameters must be written with the empty name '_'" - id: parameter_unnamed_warn - msg: >- - unnamed parameters must be written with the empty name '_' + msg: "unnamed parameters must be written with the empty name '_'" - id: parameter_curry_syntax_removed - msg: >- - cannot have more than one parameter list + msg: "cannot have more than one parameter list" - id: initializer_as_typed_pattern - msg: >- - unexpected initializer in pattern; did you mean to use '='? + msg: "unexpected initializer in pattern; did you mean to use '='?" - id: unlabeled_parameter_following_variadic_parameter - msg: >- - a parameter following a variadic parameter requires a label + msg: "a parameter following a variadic parameter requires a label" - id: enum_element_empty_arglist - msg: >- - enum element with associated values must have at least one associated - value + msg: "enum element with associated values must have at least one associated value" - id: enum_element_empty_arglist_swift4 - msg: >- - enum element with associated values must have at least one associated - value; this will be an error in the future version of Swift + msg: "enum element with associated values must have at least one associated value; this will be an error in the future version of Swift" - id: enum_element_empty_arglist_delete - msg: >- - did you mean to remove the empty associated value list? + msg: "did you mean to remove the empty associated value list?" - id: enum_element_empty_arglist_add_void - msg: >- - did you mean to explicitly add a 'Void' associated value? + msg: "did you mean to explicitly add a 'Void' associated value?" - id: expected_stmt - msg: >- - expected statement + msg: "expected statement" - id: illegal_top_level_stmt - msg: >- - statements are not allowed at the top level + msg: "statements are not allowed at the top level" - id: illegal_top_level_expr - msg: >- - expressions are not allowed at the top level + msg: "expressions are not allowed at the top level" - id: illegal_semi_stmt - msg: >- - ';' statements are not allowed + msg: "';' statements are not allowed" - id: statement_begins_with_closure - msg: >- - top-level statement cannot begin with a closure expression + msg: "top-level statement cannot begin with a closure expression" - id: statement_same_line_without_semi - msg: >- - consecutive statements on a line must be separated by ';' + msg: "consecutive statements on a line must be separated by ';'" - id: invalid_label_on_stmt - msg: >- - labels are only valid on loops, if, and switch statements + msg: "labels are only valid on loops, if, and switch statements" - id: labeled_block_needs_do - msg: >- - labeled block needs 'do' + msg: "labeled block needs 'do'" - id: snake_case_deprecated - msg: >- - %0 has been replaced with %1 in Swift 3 + msg: "%0 has been replaced with %1 in Swift 3" - id: expected_expr_assignment - msg: >- - expected expression in assignment + msg: "expected expression in assignment" - id: expected_rbrace_in_brace_stmt - msg: >- - expected '}' at end of brace statement + msg: "expected '}' at end of brace statement" - id: typealias_inside_protocol_without_type - msg: >- - type alias is missing an assigned type; use 'associatedtype' to define an - associated type requirement + msg: "type alias is missing an assigned type; use 'associatedtype' to define an associated type requirement" - id: associatedtype_outside_protocol - msg: >- - associated types can only be defined in a protocol; define a type or - introduce a 'typealias' to satisfy an associated type requirement + msg: "associated types can only be defined in a protocol; define a type or introduce a 'typealias' to satisfy an associated type requirement" - id: expected_expr_return - msg: >- - expected expression in 'return' statement + msg: "expected expression in 'return' statement" - id: unindented_code_after_return - msg: >- - expression following 'return' is treated as an argument of the 'return' + msg: "expression following 'return' is treated as an argument of the 'return'" - id: indent_expression_to_silence - msg: >- - indent the expression to silence this warning + msg: "indent the expression to silence this warning" - id: expected_expr_throw - msg: >- - expected expression in 'throw' statement + msg: "expected expression in 'throw' statement" - id: expected_expr_yield - msg: >- - expected expression in 'yield' statement + msg: "expected expression in 'yield' statement" - id: expected_lbrace_after_defer - msg: >- - expected '{' after 'defer' + msg: "expected '{' after 'defer'" - id: expected_comma_stmtcondition - msg: >- - expected ',' joining parts of a multi-clause condition + msg: "expected ',' joining parts of a multi-clause condition" - id: expected_expr_conditional - msg: >- - expected expression in conditional + msg: "expected expression in conditional" - id: expected_binding_keyword - msg: >- - expected '%0' in conditional + msg: "expected '%0' in conditional" - id: expected_expr_conditional_var - msg: >- - expected expression after '=' in conditional binding + msg: "expected expression after '=' in conditional binding" - id: conditional_var_initializer_required - msg: >- - variable binding in a condition requires an initializer + msg: "variable binding in a condition requires an initializer" - id: wrong_condition_case_location - msg: >- - pattern matching binding is spelled with 'case %0', not '%0 case' + msg: "pattern matching binding is spelled with 'case %0', not '%0 case'" - id: expected_condition_if - msg: >- - expected expression, var, or let in 'if' condition + msg: "expected expression, var, or let in 'if' condition" - id: missing_condition_after_if - msg: >- - missing condition in an 'if' statement + msg: "missing condition in an 'if' statement" - id: expected_lbrace_after_if - msg: >- - expected '{' after 'if' condition + msg: "expected '{' after 'if' condition" - id: expected_lbrace_or_if_after_else - msg: >- - expected '{' or 'if' after 'else' + msg: "expected '{' or 'if' after 'else'" - id: expected_lbrace_or_if_after_else_fixit - msg: >- - expected '{' or 'if' after 'else'; did you mean to write 'if'? + msg: "expected '{' or 'if' after 'else'; did you mean to write 'if'?" - id: unexpected_else_after_if - msg: >- - unexpected 'else' immediately following 'if' condition + msg: "unexpected 'else' immediately following 'if' condition" - id: suggest_removing_else - msg: >- - remove 'else' to execute the braced block of statements when the - condition is true + msg: "remove 'else' to execute the braced block of statements when the condition is true" - id: expected_condition_guard - msg: >- - expected expression, var, let or case in 'guard' condition + msg: "expected expression, var, let or case in 'guard' condition" - id: missing_condition_after_guard - msg: >- - missing condition in an 'guard' statement + msg: "missing condition in an 'guard' statement" - id: expected_else_after_guard - msg: >- - expected 'else' after 'guard' condition + msg: "expected 'else' after 'guard' condition" - id: expected_lbrace_after_guard - msg: >- - expected '{' after 'guard' else + msg: "expected '{' after 'guard' else" - id: bound_var_guard_body - msg: >- - variable declared in 'guard' condition is not usable in its body + msg: "variable declared in 'guard' condition is not usable in its body" - id: expected_condition_while - msg: >- - expected expression, var, or let in 'while' condition + msg: "expected expression, var, or let in 'while' condition" - id: missing_condition_after_while - msg: >- - missing condition in a 'while' statement + msg: "missing condition in a 'while' statement" - id: expected_lbrace_after_while - msg: >- - expected '{' after 'while' condition + msg: "expected '{' after 'while' condition" - id: expected_lbrace_after_repeat - msg: >- - expected '{' after 'repeat' + msg: "expected '{' after 'repeat'" - id: expected_while_after_repeat_body - msg: >- - expected 'while' after body of 'repeat' statement + msg: "expected 'while' after body of 'repeat' statement" - id: expected_expr_repeat_while - msg: >- - expected expression in 'repeat-while' condition + msg: "expected expression in 'repeat-while' condition" - id: do_while_now_repeat_while - msg: >- - 'do-while' statement is not allowed + msg: "'do-while' statement is not allowed" - id: do_while_expected_repeat_while - msg: >- - did you mean 'repeat-while' statement? + msg: "did you mean 'repeat-while' statement?" - id: do_while_expected_separate_stmt - msg: >- - did you mean separate 'do' and 'while' statements? + msg: "did you mean separate 'do' and 'while' statements?" - id: expected_lbrace_after_do - msg: >- - expected '{' after 'do' + msg: "expected '{' after 'do'" - id: expected_lbrace_after_catch - msg: >- - expected '{' after 'catch' pattern + msg: "expected '{' after 'catch' pattern" - id: expected_catch_where_expr - msg: >- - expected expression for 'where' guard of 'catch' + msg: "expected expression for 'where' guard of 'catch'" - id: docatch_not_trycatch - msg: >- - the 'do' keyword is used to specify a 'catch' region + msg: "the 'do' keyword is used to specify a 'catch' region" - id: c_style_for_stmt_removed - msg: >- - C-style for statement has been removed in Swift 3 + msg: "C-style for statement has been removed in Swift 3" - id: expected_foreach_in - msg: >- - expected 'in' after for-each pattern + msg: "expected 'in' after for-each pattern" - id: expected_foreach_container - msg: >- - expected Sequence expression for for-each loop + msg: "expected Sequence expression for for-each loop" - id: expected_foreach_lbrace - msg: >- - expected '{' to start the body of for-each loop + msg: "expected '{' to start the body of for-each loop" - id: expected_foreach_where_expr - msg: >- - expected expression in 'where' guard of 'for/in' + msg: "expected expression in 'where' guard of 'for/in'" - id: expected_switch_expr - msg: >- - expected expression in 'switch' statement + msg: "expected expression in 'switch' statement" - id: expected_lbrace_after_switch - msg: >- - expected '{' after 'switch' subject expression + msg: "expected '{' after 'switch' subject expression" - id: expected_rbrace_switch - msg: >- - expected '}' at end of 'switch' statement + msg: "expected '}' at end of 'switch' statement" - id: case_outside_of_switch - msg: >- - '%0' label can only appear inside a 'switch' statement + msg: "'%0' label can only appear inside a 'switch' statement" - id: stmt_in_switch_not_covered_by_case - msg: >- - all statements inside a switch must be covered by a 'case' or 'default' + msg: "all statements inside a switch must be covered by a 'case' or 'default'" - id: case_after_default - msg: >- - additional 'case' blocks cannot appear after the 'default' block of a - 'switch' + msg: "additional 'case' blocks cannot appear after the 'default' block of a 'switch'" - id: expected_case_where_expr - msg: >- - expected expression for 'where' guard of 'case' + msg: "expected expression for 'where' guard of 'case'" - id: expected_case_colon - msg: >- - expected ':' after '%0' + msg: "expected ':' after '%0'" - id: default_with_where - msg: >- - 'default' cannot be used with a 'where' guard expression + msg: "'default' cannot be used with a 'where' guard expression" - id: case_stmt_without_body - msg: >- - %select{'case'|'default'}0 label in a 'switch' should have at least one - executable statement + msg: "%select{'case'|'default'}0 label in a 'switch' should have at least one executable statement" - id: try_on_stmt - msg: >- - 'try' cannot be used with '%0' + msg: "'try' cannot be used with '%0'" - id: try_on_return_throw_yield - msg: >- - 'try' must be placed on the %select{returned|thrown|yielded}0 expression + msg: "'try' must be placed on the %select{returned|thrown|yielded}0 expression" - id: try_on_var_let - msg: >- - 'try' must be placed on the initial value expression + msg: "'try' must be placed on the initial value expression" - id: expected_expr - msg: >- - expected expression + msg: "expected expression" - id: expected_separator - msg: >- - expected '%0' separator + msg: "expected '%0' separator" - id: unexpected_separator - msg: >- - unexpected '%0' separator + msg: "unexpected '%0' separator" - id: expected_expr_after_operator - msg: >- - expected expression after operator + msg: "expected expression after operator" - id: expected_expr_after_unary_operator - msg: >- - expected expression after unary operator + msg: "expected expression after unary operator" - id: expected_prefix_operator - msg: >- - unary operator cannot be separated from its operand + msg: "unary operator cannot be separated from its operand" - id: expected_operator_ref - msg: >- - expected operator name in operator reference + msg: "expected operator name in operator reference" - id: invalid_postfix_operator - msg: >- - operator with postfix spacing cannot start a subexpression + msg: "operator with postfix spacing cannot start a subexpression" - id: expected_member_name - msg: >- - expected member name following '.' + msg: "expected member name following '.'" - id: dollar_numeric_too_large - msg: >- - numeric value following '$' is too large + msg: "numeric value following '$' is too large" - id: numeric_literal_numeric_member - msg: >- - expected named member of numeric literal + msg: "expected named member of numeric literal" - id: standalone_dollar_identifier - msg: >- - '$' is not an identifier; use backticks to escape it + msg: "'$' is not an identifier; use backticks to escape it" - id: dollar_identifier_decl - msg: >- - cannot declare entity named %0; the '$' prefix is reserved for - implicitly-synthesized declarations -- id: lazy_var_storage_access - msg: >- - access to the underlying storage of a lazy property is not allowed + msg: "cannot declare entity named %0; the '$' prefix is reserved for implicitly-synthesized declarations" - id: anon_closure_arg_not_in_closure - msg: >- - anonymous closure argument not contained in a closure + msg: "anonymous closure argument not contained in a closure" - id: anon_closure_arg_in_closure_with_args - msg: >- - anonymous closure arguments cannot be used inside a closure that has - explicit arguments + msg: "anonymous closure arguments cannot be used inside a closure that has explicit arguments" - id: anon_closure_arg_in_closure_with_args_typo - msg: >- - anonymous closure arguments cannot be used inside a closure that has - explicit arguments; did you mean '%0'? + msg: "anonymous closure arguments cannot be used inside a closure that has explicit arguments; did you mean '%0'?" - id: anon_closure_tuple_param_destructuring - msg: >- - closure tuple parameter does not support destructuring + msg: "closure tuple parameter does not support destructuring" - id: expected_closure_parameter_name - msg: >- - expected the name of a closure parameter + msg: "expected the name of a closure parameter" - id: expected_capture_specifier - msg: >- - expected 'weak', 'unowned', or no specifier in capture list + msg: "expected 'weak', 'unowned', or no specifier in capture list" - id: expected_capture_specifier_name - msg: >- - expected name of in closure capture list + msg: "expected name of in closure capture list" - id: expected_init_capture_specifier - msg: >- - expected initializer for closure capture specifier + msg: "expected initializer for closure capture specifier" - id: expected_capture_list_end_rsquare - msg: >- - expected ']' at end of capture list + msg: "expected ']' at end of capture list" - id: cannot_capture_fields - msg: >- - fields may only be captured by assigning to a specific name + msg: "fields may only be captured by assigning to a specific name" - id: expected_closure_result_type - msg: >- - expected closure result type after '->' + msg: "expected closure result type after '->'" - id: expected_closure_in - msg: >- - expected 'in' after the closure signature + msg: "expected 'in' after the closure signature" - id: unexpected_tokens_before_closure_in - msg: >- - unexpected tokens prior to 'in' + msg: "unexpected tokens prior to 'in'" - id: expected_closure_rbrace - msg: >- - expected '}' at end of closure + msg: "expected '}' at end of closure" - id: trailing_closure_after_newlines - msg: >- - braces here form a trailing closure separated from its callee by multiple - newlines + msg: "braces here form a trailing closure separated from its callee by multiple newlines" - id: trailing_closure_callee_here - msg: >- - callee is here + msg: "callee is here" - id: string_literal_no_atsign - msg: >- - string literals in Swift are not preceded by an '@' sign + msg: "string literals in Swift are not preceded by an '@' sign" - id: invalid_float_literal_missing_leading_zero - msg: >- - '.%0' is not a valid floating point literal; it must be written '0.%0' + msg: "'.%0' is not a valid floating point literal; it must be written '0.%0'" - id: availability_query_outside_if_stmt_guard - msg: >- - #available may only be used as condition of an 'if', 'guard' or 'while' - statement + msg: "#available may only be used as condition of an 'if', 'guard' or 'while' statement" - id: empty_arg_label_underscore - msg: >- - an empty argument label is spelled with '_' + msg: "an empty argument label is spelled with '_'" - id: expected_identifier_after_dot_expr - msg: >- - expected identifier after '.' expression + msg: "expected identifier after '.' expression" - id: expected_identifier_after_super_dot_expr - msg: >- - expected identifier or 'init' after super '.' expression + msg: "expected identifier or 'init' after super '.' expression" - id: expected_dot_or_subscript_after_super - msg: >- - expected '.' or '[' after 'super' + msg: "expected '.' or '[' after 'super'" - id: super_in_closure_with_capture - msg: >- - using 'super' in a closure where 'self' is explicitly captured is not yet - supported + msg: "using 'super' in a closure where 'self' is explicitly captured is not yet supported" - id: super_in_closure_with_capture_here - msg: >- - 'self' explicitly captured here + msg: "'self' explicitly captured here" - id: expected_expr_in_expr_list - msg: >- - expected expression in list of expressions + msg: "expected expression in list of expressions" - id: expected_expr_in_collection_literal - msg: >- - expected expression in container literal + msg: "expected expression in container literal" - id: expected_key_in_dictionary_literal - msg: >- - expected key expression in dictionary literal + msg: "expected key expression in dictionary literal" - id: expected_value_in_dictionary_literal - msg: >- - expected value in dictionary literal + msg: "expected value in dictionary literal" - id: expected_colon_in_dictionary_literal - msg: >- - expected ':' in dictionary literal + msg: "expected ':' in dictionary literal" - id: expected_rparen_expr_list - msg: >- - expected ')' in expression list + msg: "expected ')' in expression list" - id: expected_rsquare_expr_list - msg: >- - expected ']' in expression list + msg: "expected ']' in expression list" - id: expected_rsquare_array_expr - msg: >- - expected ']' in container literal expression + msg: "expected ']' in container literal expression" - id: expected_arg_list_in_object_literal - msg: >- - expected argument list in object literal + msg: "expected argument list in object literal" - id: legacy_object_literal - msg: >- - '%select{|[}0#%1(...)%select{|#]}0' has been renamed to '#%2(...)' + msg: "'%select{|[}0#%1(...)%select{|#]}0' has been renamed to '#%2(...)'" - id: unknown_pound_expr - msg: >- - use of unknown directive '#%0' + msg: "use of unknown directive '#%0'" - id: expected_expr_after_if_question - msg: >- - expected expression after '?' in ternary expression + msg: "expected expression after '?' in ternary expression" - id: expected_colon_after_if_question - msg: >- - expected ':' after '? ...' in ternary expression + msg: "expected ':' after '? ...' in ternary expression" - id: expected_expr_after_if_colon - msg: >- - expected expression after '? ... :' in ternary expression + msg: "expected expression after '? ... :' in ternary expression" + +- id: expected_expr_after_try + msg: "expected expression after 'try'" + +- id: expected_expr_after_await + msg: "expected expression after 'await'" - id: expected_type_after_is - msg: >- - expected type after 'is' + msg: "expected type after 'is'" - id: expected_type_after_as - msg: >- - expected type after 'as' + msg: "expected type after 'as'" - id: string_interpolation_extra - msg: >- - extra tokens after interpolated string expression + msg: "extra tokens after interpolated string expression" - id: string_interpolation_list_changing - msg: >- - interpolating multiple values will not form a tuple in Swift 5 + msg: "interpolating multiple values will not form a tuple in Swift 5" - id: string_interpolation_list_insert_parens - msg: >- - insert parentheses to keep current behavior + msg: "insert parentheses to keep current behavior" - id: string_interpolation_label_changing - msg: >- - labeled interpolations will not be ignored in Swift 5 + msg: "labeled interpolations will not be ignored in Swift 5" - id: string_interpolation_remove_label - msg: >- - remove %0 label to keep current behavior + msg: "remove %0 label to keep current behavior" - id: expr_keypath_expected_lparen - msg: >- - expected '(' following '#keyPath' + msg: "expected '(' following '#keyPath'" - id: expr_keypath_expected_property_or_type - msg: >- - expected property or type name within '#keyPath(...)' + msg: "expected property or type name within '#keyPath(...)'" - id: expr_keypath_expected_rparen - msg: >- - expected ')' to complete '#keyPath' expression + msg: "expected ')' to complete '#keyPath' expression" - id: expr_keypath_expected_expr - msg: >- - expected expression path in Swift key path + msg: "expected expression path in Swift key path" - id: expr_selector_expected_lparen - msg: >- - expected '(' following '#selector' + msg: "expected '(' following '#selector'" - id: expr_selector_expected_method_expr - msg: >- - expected expression naming a method within '#selector(...)' + msg: "expected expression naming a method within '#selector(...)'" - id: expr_selector_expected_property_expr - msg: >- - expected expression naming a property within '#selector(...)' + msg: "expected expression naming a property within '#selector(...)'" - id: expr_selector_expected_rparen - msg: >- - expected ')' to complete '#selector' expression + msg: "expected ')' to complete '#selector' expression" - id: expr_dynamictype_deprecated - msg: >- - '.dynamicType' is deprecated. Use 'type(of: ...)' instead + msg: "'.dynamicType' is deprecated. Use 'type(of: ...)' instead" - id: pound_assert_disabled - msg: >- - #assert is an experimental feature that is currently disabled + msg: "#assert is an experimental feature that is currently disabled" - id: pound_assert_expected_lparen - msg: >- - expected '(' in #assert directive + msg: "expected '(' in #assert directive" - id: pound_assert_expected_rparen - msg: >- - expected ')' in #assert directive + msg: "expected ')' in #assert directive" - id: pound_assert_expected_expression - msg: >- - expected a condition expression + msg: "expected a condition expression" - id: pound_assert_expected_string_literal - msg: >- - expected a string literal + msg: "expected a string literal" - id: replace_equal_with_colon_for_value - msg: >- - '=' has been replaced with ':' in attribute arguments + msg: "'=' has been replaced with ':' in attribute arguments" - id: expected_attribute_name - msg: >- - expected an attribute name + msg: "expected an attribute name" - id: unknown_attribute - msg: >- - unknown attribute '%0' + msg: "unknown attribute '%0'" - id: unexpected_lparen_in_attribute - msg: >- - unexpected '(' in attribute '%0' + msg: "unexpected '(' in attribute '%0'" - id: duplicate_attribute - msg: >- - duplicate %select{attribute|modifier}0 + msg: "duplicate %select{attribute|modifier}0" - id: previous_attribute - msg: >- - %select{attribute|modifier}0 already specified here + msg: "%select{attribute|modifier}0 already specified here" - id: mutually_exclusive_attrs - msg: >- - '%0' contradicts previous %select{attribute|modifier}2 '%1' + msg: "'%0' contradicts previous %select{attribute|modifier}2 '%1'" - id: invalid_infix_on_func - msg: >- - 'infix' modifier is not required or allowed on func declarations + msg: "'infix' modifier is not required or allowed on func declarations" - id: expected_in_attribute_list - msg: >- - expected ']' or ',' in attribute list + msg: "expected ']' or ',' in attribute list" - id: type_attribute_applied_to_decl - msg: >- - attribute can only be applied to types, not declarations + msg: "attribute can only be applied to types, not declarations" - id: decl_attribute_applied_to_type - msg: >- - attribute can only be applied to declarations, not types + msg: "attribute can only be applied to declarations, not types" - id: attr_expected_lparen - msg: >- - expected '(' in '%0' %select{attribute|modifier}1 + msg: "expected '(' in '%0' %select{attribute|modifier}1" - id: attr_expected_rparen - msg: >- - expected ')' in '%0' %select{attribute|modifier}1 + msg: "expected ')' in '%0' %select{attribute|modifier}1" - id: attr_expected_comma - msg: >- - expected ',' in '%0' %select{attribute|modifier}1 + msg: "expected ',' in '%0' %select{attribute|modifier}1" - id: attr_expected_string_literal - msg: >- - expected string literal in '%0' attribute + msg: "expected string literal in '%0' attribute" - id: attr_missing_label - msg: >- - missing label '%0:' in '@%1' attribute + msg: "missing label '%0:' in '@%1' attribute" - id: attr_expected_label - msg: >- - expected label '%0:' in '@%1' attribute + msg: "expected label '%0:' in '@%1' attribute" - id: alignment_must_be_positive_integer - msg: >- - alignment value must be a positive integer literal + msg: "alignment value must be a positive integer literal" - id: swift_native_objc_runtime_base_must_be_identifier - msg: >- - @_swift_native_objc_runtime_base class name must be an identifier + msg: "@_swift_native_objc_runtime_base class name must be an identifier" - id: objc_runtime_name_must_be_identifier - msg: >- - @_objcRuntimeName name must be an identifier + msg: "@_objcRuntimeName name must be an identifier" - id: attr_only_at_non_local_scope - msg: >- - attribute '%0' can only be used in a non-local scope + msg: "attribute '%0' can only be used in a non-local scope" - id: projection_value_property_not_identifier - msg: >- - @_projectedValueProperty name must be an identifier + msg: "@_projectedValueProperty name must be an identifier" - id: attr_access_expected_set - msg: >- - expected 'set' as subject of '%0' modifier + msg: "expected 'set' as subject of '%0' modifier" - id: attr_access_expected_spi_name - msg: >- - expected an SPI identifier as subject of the '@_spi' attribute + msg: "expected an SPI identifier as subject of the '@_spi' attribute" - id: attr_renamed - msg: >- - '@%0' has been renamed to '@%1' + msg: "'@%0' has been renamed to '@%1'" - id: attr_renamed_warning - msg: >- - '@%0' has been renamed to '@%1' + msg: "'@%0' has been renamed to '@%1'" - id: attr_name_close_match - msg: >- - no attribute named '@%0'; did you mean '@%1'? + msg: "no attribute named '@%0'; did you mean '@%1'?" - id: attr_unsupported_on_target - msg: >- - attribute '%0' is unsupported on target '%1' + msg: "attribute '%0' is unsupported on target '%1'" - id: attr_availability_platform - msg: >- - expected platform name or '*' for '%0' attribute + msg: "expected platform name or '*' for '%0' attribute" - id: attr_availability_unavailable_deprecated - msg: >- - '%0' attribute cannot be both unconditionally 'unavailable' and - 'deprecated' + msg: "'%0' attribute cannot be both unconditionally 'unavailable' and 'deprecated'" - id: attr_availability_invalid_duplicate - msg: >- - '%0' argument has already been specified + msg: "'%0' argument has already been specified" - id: attr_availability_unknown_platform - msg: >- - unknown platform '%0' for attribute '%1' + msg: "unknown platform '%0' for attribute '%1'" - id: attr_availability_invalid_renamed - msg: >- - 'renamed' argument of '%0' attribute must be an operator, identifier, or - full function name, optionally prefixed by a type name + msg: "'renamed' argument of '%0' attribute must be an operator, identifier, or full function name, optionally prefixed by a type name" - id: attr_availability_expected_option - msg: >- - expected '%0' option such as 'unavailable', 'introduced', 'deprecated', - 'obsoleted', 'message', or 'renamed' + msg: "expected '%0' option such as 'unavailable', 'introduced', 'deprecated', 'obsoleted', 'message', or 'renamed'" - id: attr_availability_expected_equal - msg: >- - expected ':' after '%1' in '%0' attribute + msg: "expected ':' after '%1' in '%0' attribute" - id: attr_availability_expected_version - msg: >- - expected version number in '%0' attribute + msg: "expected version number in '%0' attribute" - id: attr_availability_platform_agnostic_expected_option - msg: >- - expected 'introduced', 'deprecated', or 'obsoleted' in '%0' attribute for - platform '%1' + msg: "expected 'introduced', 'deprecated', or 'obsoleted' in '%0' attribute for platform '%1'" - id: attr_availability_platform_agnostic_expected_deprecated_version - msg: >- - expected version number with 'deprecated' in '%0' attribute for platform - '%1' + msg: "expected version number with 'deprecated' in '%0' attribute for platform '%1'" - id: attr_availability_platform_agnostic_infeasible_option - msg: >- - '%0' cannot be used in '%1' attribute for platform '%2' + msg: "'%0' cannot be used in '%1' attribute for platform '%2'" - id: attr_availability_nonspecific_platform_unexpected_version - msg: >- - unexpected version number in '%0' attribute for non-specific platform '*' + msg: "unexpected version number in '%0' attribute for non-specific platform '*'" - id: originally_defined_in_missing_rparen - msg: >- - expected ')' in @_originallyDefinedIn argument list + msg: "expected ')' in @_originallyDefinedIn argument list" - id: originally_defined_in_unrecognized_platform - msg: >- - unrecognized platform name in @_originallyDefinedIn argument list + msg: "unrecognized platform name in @_originallyDefinedIn argument list" - id: originally_defined_in_unrecognized_property - msg: >- - unrecognized property in @_originallyDefinedIn argument list + msg: "unrecognized property in @_originallyDefinedIn argument list" - id: originally_defined_in_need_original_module_name - msg: >- - expected 'module: "original"' in the first argument to - @_originallyDefinedIn + msg: "expected 'module: \"original\"' in the first argument to @_originallyDefinedIn" - id: originally_defined_in_need_nonempty_module_name - msg: >- - original module name cannot be empty in @_originallyDefinedIn + msg: "original module name cannot be empty in @_originallyDefinedIn" - id: originally_defined_in_need_platform_version - msg: >- - expected at least one platform version in @_originallyDefinedIn + msg: "expected at least one platform version in @_originallyDefinedIn" - id: originally_defined_in_major_minor_only - msg: >- - @_originallyDefinedIn only uses major and minor version number + msg: "@_originallyDefinedIn only uses major and minor version number" - id: originally_defined_in_missing_platform_name - msg: >- - * as platform name has no effect + msg: "* as platform name has no effect" - id: convention_attribute_expected_lparen - msg: >- - expected '(' after 'convention' attribute + msg: "expected '(' after 'convention' attribute" - id: convention_attribute_expected_name - msg: >- - expected convention name identifier in 'convention' attribute + msg: "expected convention name identifier in 'convention' attribute" - id: convention_attribute_expected_rparen - msg: >- - expected ')' after convention name for 'convention' attribute + msg: "expected ')' after convention name for 'convention' attribute" - id: convention_attribute_ctype_expected_label - msg: >- - expected 'cType' label in 'convention' attribute + msg: "expected 'cType' label in 'convention' attribute" - id: convention_attribute_ctype_expected_colon - msg: >- - expected ':' after 'cType' for 'convention' attribute + msg: "expected ':' after 'cType' for 'convention' attribute" - id: convention_attribute_ctype_expected_string - msg: >- - expected string literal containing clang type for 'cType' in 'convention' - attribute + msg: "expected string literal containing clang type for 'cType' in 'convention' attribute" - id: convention_attribute_witness_method_expected_colon - msg: >- - expected ':' after 'witness_method' for 'convention' attribute + msg: "expected ':' after 'witness_method' for 'convention' attribute" - id: convention_attribute_witness_method_expected_protocol - msg: >- - expected protocol name in 'witness_method' 'convention' attribute + msg: "expected protocol name in 'witness_method' 'convention' attribute" - id: attr_objc_missing_colon - msg: >- - missing ':' after selector piece in @objc attribute + msg: "missing ':' after selector piece in @objc attribute" - id: attr_objc_expected_rparen - msg: >- - expected ')' after name for @objc + msg: "expected ')' after name for @objc" - id: attr_objc_empty_name - msg: >- - expected name within parentheses of @objc attribute + msg: "expected name within parentheses of @objc attribute" - id: attr_dynamic_replacement_expected_rparen - msg: >- - expected ')' after function name for @_dynamicReplacement + msg: "expected ')' after function name for @_dynamicReplacement" - id: attr_dynamic_replacement_expected_function - msg: >- - expected a function name in @_dynamicReplacement(for:) + msg: "expected a function name in @_dynamicReplacement(for:)" - id: attr_dynamic_replacement_expected_for - msg: >- - expected 'for' in '_dynamicReplacement' attribute + msg: "expected 'for' in '_dynamicReplacement' attribute" - id: attr_dynamic_replacement_expected_colon - msg: >- - expected ':' after @_dynamicReplacement(for + msg: "expected ':' after @_dynamicReplacement(for" - id: attr_type_eraser_expected_type_name - msg: >- - expected a type name in @_typeEraser() + msg: "expected a type name in @_typeEraser()" - id: attr_type_eraser_expected_rparen - msg: >- - expected ')' after type name for @_typeEraser + msg: "expected ')' after type name for @_typeEraser" - id: attr_private_import_expected_rparen - msg: >- - expected ')' after function name for @_private + msg: "expected ')' after function name for @_private" - id: attr_private_import_expected_sourcefile - msg: >- - expected 'sourceFile' in '_private' attribute + msg: "expected 'sourceFile' in '_private' attribute" - id: attr_private_import_expected_sourcefile_name - msg: >- - expected a source file name in @_private(sourceFile:) + msg: "expected a source file name in @_private(sourceFile:)" - id: attr_private_import_expected_colon - msg: >- - expected ':' after @_private(sourceFile + msg: "expected ':' after @_private(sourceFile" - id: opened_attribute_expected_lparen - msg: >- - expected '(' after 'opened' attribute + msg: "expected '(' after 'opened' attribute" - id: opened_attribute_id_value - msg: >- - known id for 'opened' attribute must be a UUID string + msg: "known id for 'opened' attribute must be a UUID string" - id: opened_attribute_expected_rparen - msg: >- - expected ')' after id value for 'opened' attribute + msg: "expected ')' after id value for 'opened' attribute" - id: optimization_attribute_expect_option - msg: >- - expected '%0' option such as '%1' + msg: "expected '%0' option such as '%1'" - id: optimization_attribute_unknown_option - msg: >- - unknown option '%0' for attribute '%1' + msg: "unknown option '%0' for attribute '%1'" - id: effects_attribute_expect_option - msg: >- - expected '%0' option (readnone, readonly, readwrite) + msg: "expected '%0' option (readnone, readonly, readwrite)" - id: effects_attribute_unknown_option - msg: >- - unknown option '%0' for attribute '%1' + msg: "unknown option '%0' for attribute '%1'" - id: attr_unowned_invalid_specifier - msg: >- - expected 'safe' or 'unsafe' + msg: "expected 'safe' or 'unsafe'" - id: attr_unowned_expected_rparen - msg: >- - expected ')' after specifier for 'unowned' + msg: "expected ')' after specifier for 'unowned'" - id: attr_warn_unused_result_removed - msg: >- - 'warn_unused_result' attribute behavior is now the default + msg: "'warn_unused_result' attribute behavior is now the default" - id: attr_warn_unused_result_expected_rparen - msg: >- - expected ')' after 'warn_unused_result' attribute + msg: "expected ')' after 'warn_unused_result' attribute" - id: attr_specialize_missing_colon - msg: >- - missing ':' after %0 in '_specialize' attribute + msg: "missing ':' after %0 in '_specialize' attribute" - id: attr_specialize_missing_comma - msg: >- - missing ',' in '_specialize' attribute + msg: "missing ',' in '_specialize' attribute" - id: attr_specialize_unknown_parameter_name - msg: >- - unknown parameter %0 in '_specialize attribute' + msg: "unknown parameter %0 in '_specialize attribute'" - id: attr_specialize_expected_bool_value - msg: >- - expected a boolean true or false value in '_specialize' attribute + msg: "expected a boolean true or false value in '_specialize' attribute" - id: attr_specialize_export_true_no_op - msg: >- - 'exported: true' has no effect in '_specialize' attribute + msg: "'exported: true' has no effect in '_specialize' attribute" - id: attr_specialize_missing_parameter_label_or_where_clause - msg: >- - expected a parameter label or a where clause in '_specialize' attribute + msg: "expected a parameter label or a where clause in '_specialize' attribute" - id: attr_specialize_parameter_already_defined - msg: >- - parameter '%0' was already defined in '_specialize' attribute + msg: "parameter '%0' was already defined in '_specialize' attribute" - id: attr_specialize_expected_partial_or_full - msg: >- - expected 'partial' or 'full' as values of the 'kind' parameter in - '_specialize' attribute + msg: "expected 'partial' or 'full' as values of the 'kind' parameter in '_specialize' attribute" - id: attr_implements_expected_member_name - msg: >- - expected a member name as second parameter in '_implements' attribute + msg: "expected a member name as second parameter in '_implements' attribute" - id: attr_differentiable_expected_parameter_list - msg: >- - expected a list of parameters to differentiate with respect to + msg: "expected a list of parameters to differentiate with respect to" - id: attr_differentiable_use_wrt_not_withrespectto - msg: >- - use 'wrt:' to specify parameters to differentiate with respect to + msg: "use 'wrt:' to specify parameters to differentiate with respect to" - id: attr_differentiable_expected_label - msg: >- - expected 'wrt:' or 'where' in '@differentiable' attribute + msg: "expected 'wrt:' or 'where' in '@differentiable' attribute" - id: attr_differentiable_unexpected_argument - msg: >- - unexpected argument '%0' in '@differentiable' attribute + msg: "unexpected argument '%0' in '@differentiable' attribute" - id: expected_colon_after_label - msg: >- - expected a colon ':' after '%0' + msg: "expected a colon ':' after '%0'" - id: diff_params_clause_expected_parameter - msg: >- - expected a parameter, which can be a function parameter name, parameter - index, or 'self' + msg: "expected a parameter, which can be a function parameter name, parameter index, or 'self'" - id: diff_params_clause_expected_parameter_unnamed - msg: >- - expected a parameter, which can be a function parameter index or 'self' + msg: "expected a parameter, which can be a function parameter index or 'self'" - id: autodiff_attr_expected_original_decl_name - msg: >- - expected an original function name + msg: "expected an original function name" - id: sil_autodiff_expected_lsquare - msg: >- - expected '[' to start the %0 + msg: "expected '[' to start the %0" - id: sil_autodiff_expected_rsquare - msg: >- - expected ']' to complete the %0 + msg: "expected ']' to complete the %0" - id: sil_autodiff_expected_index_list - msg: >- - expected a space-separated list of indices, e.g. '0 1' + msg: "expected a space-separated list of indices, e.g. '0 1'" - id: sil_autodiff_expected_index_list_label - msg: >- - expected label '%0' in index list + msg: "expected label '%0' in index list" - id: sil_autodiff_expected_parameter_index - msg: >- - expected the index of a parameter to differentiate with respect to + msg: "expected the index of a parameter to differentiate with respect to" - id: sil_autodiff_expected_result_index - msg: >- - expected the index of a result to differentiate from + msg: "expected the index of a result to differentiate from" - id: sil_inst_autodiff_operand_list_expected_lbrace - msg: >- - expected '{' to start a derivative function list + msg: "expected '{' to start a derivative function list" - id: sil_inst_autodiff_operand_list_expected_comma - msg: >- - expected ',' between operands in a derivative function list + msg: "expected ',' between operands in a derivative function list" - id: sil_inst_autodiff_operand_list_expected_rbrace - msg: >- - expected '}' to start a derivative function list + msg: "expected '}' to start a derivative function list" - id: sil_inst_autodiff_expected_differentiable_extractee_kind - msg: >- - expected an extractee kind attribute, which can be one of '[original]', - '[jvp]', and '[vjp]' + msg: "expected an extractee kind attribute, which can be one of '[original]', '[jvp]', and '[vjp]'" - id: sil_inst_autodiff_expected_linear_extractee_kind - msg: >- - expected an extractee kind attribute, which can be one of '[original]' - and '[transpose]' + msg: "expected an extractee kind attribute, which can be one of '[original]' and '[transpose]'" - id: sil_inst_autodiff_expected_function_type_operand - msg: >- - expected an operand of a function type + msg: "expected an operand of a function type" - id: sil_inst_autodiff_expected_differentiability_witness_kind - msg: >- - expected a differentiability witness kind, which can be one of '[jvp]', - '[vjp]', or '[transpose]' + msg: "expected a differentiability witness kind, which can be one of '[jvp]', '[vjp]', or '[transpose]'" - id: sil_inst_autodiff_invalid_witness_generic_signature - msg: >- - expected witness_generic signature '%0' does not have same generic - parameters as original function generic signature '%1' + msg: "expected witness_generic signature '%0' does not have same generic parameters as original function generic signature '%1'" - id: expected_rangle_generics_param - msg: >- - expected '>' to complete generic parameter list + msg: "expected '>' to complete generic parameter list" - id: expected_generics_parameter_name - msg: >- - expected an identifier to name generic parameter + msg: "expected an identifier to name generic parameter" - id: unexpected_class_constraint - msg: >- - 'class' constraint can only appear on protocol declarations + msg: "'class' constraint can only appear on protocol declarations" - id: suggest_anyobject - msg: >- - did you mean to write an 'AnyObject' constraint? + msg: "did you mean to write an 'AnyObject' constraint?" - id: expected_generics_type_restriction - msg: >- - expected a class type or protocol-constrained type restricting %0 + msg: "expected a class type or protocol-constrained type restricting %0" - id: requires_single_equal - msg: >- - use '==' for same-type requirements rather than '=' + msg: "use '==' for same-type requirements rather than '='" - id: requires_comma - msg: >- - expected ',' to separate the requirements of this 'where' clause + msg: "expected ',' to separate the requirements of this 'where' clause" - id: expected_requirement_delim - msg: >- - expected ':' or '==' to indicate a conformance or same-type requirement + msg: "expected ':' or '==' to indicate a conformance or same-type requirement" - id: redundant_class_requirement - msg: >- - redundant 'class' requirement + msg: "redundant 'class' requirement" - id: late_class_requirement - msg: >- - 'class' must come first in the requirement list + msg: "'class' must come first in the requirement list" - id: where_inside_brackets - msg: >- - 'where' clause next to generic parameters is obsolete, must be written - following the declaration's type + msg: "'where' clause next to generic parameters is obsolete, must be written following the declaration's type" - id: unsupported_conditional_compilation_binary_expression - msg: >- - expected '&&' or '||' expression + msg: "expected '&&' or '||' expression" - id: unsupported_conditional_compilation_unary_expression - msg: >- - expected unary '!' expression + msg: "expected unary '!' expression" - id: unsupported_platform_condition_expression - msg: >- - unexpected platform condition (expected 'os', 'arch', or 'swift') + msg: "unexpected platform condition (expected 'os', 'arch', or 'swift')" - id: platform_condition_expected_one_argument - msg: >- - expected only one argument to platform condition + msg: "expected only one argument to platform condition" - id: unsupported_platform_runtime_condition_argument - msg: >- - unexpected argument for the '_runtime' condition; expected '_Native' or - '_ObjC' + msg: "unexpected argument for the '_runtime' condition; expected '_Native' or '_ObjC'" - id: unsupported_platform_condition_argument - msg: >- - unexpected platform condition argument: expected %0 + msg: "unexpected platform condition argument: expected %0" - id: unsupported_conditional_compilation_expression_type - msg: >- - invalid conditional compilation expression + msg: "invalid conditional compilation expression" - id: unsupported_conditional_compilation_integer - msg: >- - '%0' is not a valid conditional compilation expression, use '%1' + msg: "'%0' is not a valid conditional compilation expression, use '%1'" - id: version_component_not_number - msg: >- - version component contains non-numeric characters + msg: "version component contains non-numeric characters" - id: compiler_version_too_many_components - msg: >- - compiler version must not have more than five components + msg: "compiler version must not have more than five components" - id: unused_compiler_version_component - msg: >- - the second version component is not used for comparison + msg: "the second version component is not used for comparison" - id: empty_version_component - msg: >- - found empty version component + msg: "found empty version component" - id: compiler_version_component_out_of_range - msg: >- - compiler version component out of range: must be in [0, %0] + msg: "compiler version component out of range: must be in [0, %0]" - id: empty_version_string - msg: >- - version requirement is empty + msg: "version requirement is empty" - id: unknown_platform_condition_argument - msg: >- - unknown %0 for build configuration '%1' + msg: "unknown %0 for build configuration '%1'" - id: renamed_platform_condition_argument - msg: >- - '%0' has been renamed to '%1' + msg: "'%0' has been renamed to '%1'" - id: likely_simulator_platform_condition - msg: >- - platform condition appears to be testing for simulator environment; use - 'targetEnvironment(simulator)' instead + msg: "platform condition appears to be testing for simulator environment; use 'targetEnvironment(simulator)' instead" - id: avail_query_expected_condition - msg: >- - expected availability condition + msg: "expected availability condition" - id: avail_query_expected_platform_name - msg: >- - expected platform name + msg: "expected platform name" - id: avail_query_expected_version_number - msg: >- - expected version number + msg: "expected version number" - id: avail_query_expected_rparen - msg: >- - expected ')' in availability query + msg: "expected ')' in availability query" - id: avail_query_unrecognized_platform_name - msg: >- - unrecognized platform name %0 + msg: "unrecognized platform name %0" - id: avail_query_disallowed_operator - msg: >- - '%0' cannot be used in an availability condition + msg: "'%0' cannot be used in an availability condition" - id: avail_query_argument_and_shorthand_mix_not_allowed - msg: >- - '%0' can't be combined with shorthand specification '%1' + msg: "'%0' can't be combined with shorthand specification '%1'" - id: avail_query_meant_introduced - msg: >- - did you mean to specify an introduction version? + msg: "did you mean to specify an introduction version?" - id: avail_query_version_comparison_not_needed - msg: >- - version comparison not needed + msg: "version comparison not needed" - id: availability_query_wildcard_required - msg: >- - must handle potential future platforms with '*' + msg: "must handle potential future platforms with '*'" - id: availability_must_occur_alone - msg: >- - '%0' version-availability must be specified alone + msg: "'%0' version-availability must be specified alone" - id: pound_available_swift_not_allowed - msg: >- - Swift language version checks not allowed in #available(...) + msg: "Swift language version checks not allowed in #available(...)" - id: pound_available_package_description_not_allowed - msg: >- - PackageDescription version checks not allowed in #available(...) + msg: "PackageDescription version checks not allowed in #available(...)" - id: availability_query_repeated_platform - msg: >- - version for '%0' already specified + msg: "version for '%0' already specified" - id: unknown_syntax_entity - msg: >- - unknown %0 syntax exists in the source + msg: "unknown %0 syntax exists in the source" - id: expected_argument_label_followed_by_closure_literal - msg: >- - expected an argument label followed by a closure literal + msg: "expected an argument label followed by a closure literal" - id: expected_closure_literal - msg: >- - expected a closure literal + msg: "expected a closure literal" - id: expected_multiple_closures_block_rbrace - msg: >- - expected '}' at the end of a trailing closures block + msg: "expected '}' at the end of a trailing closures block" - id: decl_declared_here - msg: >- - %0 declared here + msg: "%0 declared here" - id: kind_declared_here - msg: >- - %0 declared here + msg: "%0 declared here" - id: implicit_member_declared_here - msg: >- - %1 '%0' is implicitly declared + msg: "%1 '%0' is implicitly declared" - id: extended_type_declared_here - msg: >- - extended type declared here + msg: "extended type declared here" - id: opaque_return_type_declared_here - msg: >- - opaque return type declared here + msg: "opaque return type declared here" - id: ambiguous_member_overload_set - msg: >- - ambiguous reference to member %0 + msg: "ambiguous reference to member %0" - id: ambiguous_reference_to_decl - msg: >- - ambiguous reference to %0 %1 + msg: "ambiguous reference to %0 %1" - id: no_overloads_match_exactly_in_call - msg: >- - no exact matches in %select{reference|call}0 to %1 %select{%3|}2 + msg: "no exact matches in %select{reference|call}0 to %1 %select{%3|}2" - id: candidate_partial_match - msg: >- - candidate has partially matching parameter list %0 + msg: "candidate has partially matching parameter list %0" - id: could_not_find_value_subscript - msg: >- - value of type %0 has no subscripts + msg: "value of type %0 has no subscripts" - id: could_not_find_tuple_member - msg: >- - value of tuple type %0 has no member %1 + msg: "value of tuple type %0 has no member %1" - id: could_not_find_value_member - msg: >- - value of type %0 has no member %1 + msg: "value of type %0 has no member %1" - id: could_not_find_value_member_corrected - msg: >- - value of type %0 has no member %1; did you mean %2? + msg: "value of type %0 has no member %1; did you mean %2?" - id: could_not_find_value_dynamic_member_corrected - msg: >- - value of type %0 has no dynamic member %2 using key path from root type - %1; did you mean %3? + msg: "value of type %0 has no dynamic member %2 using key path from root type %1; did you mean %3?" - id: could_not_find_value_dynamic_member - msg: >- - value of type %0 has no dynamic member %2 using key path from root type - %1 + msg: "value of type %0 has no dynamic member %2 using key path from root type %1" - id: cannot_infer_contextual_keypath_type_specify_root - msg: >- - cannot infer key path type from context; consider explicitly specifying a - root type + msg: "cannot infer key path type from context; consider explicitly specifying a root type" - id: cannot_infer_keypath_root_anykeypath_context - msg: >- - 'AnyKeyPath' does not provide enough context for root type to be - inferred; consider explicitly specifying a root type + msg: "'AnyKeyPath' does not provide enough context for root type to be inferred; consider explicitly specifying a root type" - id: could_not_find_type_member - msg: >- - type %0 has no member %1 + msg: "type %0 has no member %1" - id: could_not_find_type_member_corrected - msg: >- - type %0 has no member %1; did you mean %2? + msg: "type %0 has no member %1; did you mean %2?" - id: could_not_find_subscript_member_did_you_mean - msg: >- - value of type %0 has no property or method named 'subscript'; did you - mean to use the subscript operator? + msg: "value of type %0 has no property or method named 'subscript'; did you mean to use the subscript operator?" - id: could_not_find_subscript_member_tuple - msg: >- - cannot access element using subscript for tuple type %0; use '.' notation instead + msg: "cannot access element using subscript for tuple type %0; use '.' notation instead" - id: could_not_find_subscript_member_tuple_did_you_mean_use_dot - msg: >- - cannot access element using subscript for tuple type %0; did you mean to use '.%1'? + msg: "cannot access element using subscript for tuple type %0; did you mean to use '.%1'?" - id: could_not_find_enum_case - msg: >- - enum type %0 has no case %1; did you mean %2? + msg: "enum type %0 has no case %1; did you mean %2?" - id: did_you_mean_raw_type - msg: >- - did you mean to specify a raw type on the enum declaration? + msg: "did you mean to specify a raw type on the enum declaration?" - id: did_you_mean_generic_param_as_conformance - msg: >- - did you mean to declare %0 as a protocol conformance for %1? + msg: "did you mean to declare %0 as a protocol conformance for %1?" - id: any_as_anyobject_fixit - msg: >- - cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more - specific type to access members + msg: "cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members" - id: expected_argument_in_contextual_member - msg: >- - member %0 expects argument of type %1 + msg: "member %0 expects argument of type %1" - id: expected_parens_in_contextual_member + msg: "member %0 is a function; did you mean to call it?" + +- id: expected_parens_in_contextual_member_type msg: >- - member %0 is a function; did you mean to call it? + member %0 is a function that produces expected type %1; did you mean to call it? - id: expected_result_in_contextual_member - msg: >- - member %0 in %2 produces result of type %1, but context expects %2 + msg: "member %0 in %2 produces result of type %1, but context expects %2" - id: unexpected_arguments_in_enum_case - msg: >- - enum case %0 has no associated values + msg: "enum case %0 has no associated values" - id: could_not_use_type_member_on_instance - msg: >- - static member %1 cannot be used on instance of type %0 + msg: "static member %1 cannot be used on instance of type %0" - id: could_not_use_enum_element_on_instance - msg: >- - enum case %0 cannot be used as an instance member + msg: "enum case %0 cannot be used as an instance member" - id: could_not_use_type_member_on_protocol_metatype - msg: >- - static member %1 cannot be used on protocol metatype %0 + msg: "static member %1 cannot be used on protocol metatype %0" - id: could_not_use_instance_member_on_type - msg: >- - instance member %1%select{| of type %2}3 - cannot be used on%select{| instance of nested}3 type %0 + msg: "instance member %1%select{| of type %2}3 cannot be used on%select{| instance of nested}3 type %0" - id: could_not_use_member_on_existential - msg: >- - member %1 cannot be used on value of protocol type %0; use a generic - constraint instead + msg: "member %1 cannot be used on value of protocol type %0; use a generic constraint instead" - id: candidate_inaccessible - msg: >- - %0 is inaccessible due to - '%select{private|fileprivate|internal|@_spi|@_spi}1' protection level + msg: "%0 is inaccessible due to '%select{private|fileprivate|internal|@_spi|@_spi}1' protection level" - id: note_candidate_inaccessible - msg: >- - %0 is inaccessible due to - '%select{private|fileprivate|internal|@_spi|@_spi}1' protection level + msg: "%0 is inaccessible due to '%select{private|fileprivate|internal|@_spi|@_spi}1' protection level" - id: init_candidate_inaccessible - msg: >- - %0 initializer is inaccessible due to - '%select{private|fileprivate|internal|@_spi|@_spi}1' protection level + msg: "%0 initializer is inaccessible due to '%select{private|fileprivate|internal|@_spi|@_spi}1' protection level" - id: cannot_pass_rvalue_mutating_subelement - msg: >- - cannot use mutating member on immutable value: %0 + msg: "cannot use mutating member on immutable value: %0" - id: cannot_pass_rvalue_mutating - msg: >- - cannot use mutating member on immutable value of type %0 + msg: "cannot use mutating member on immutable value of type %0" - id: cannot_pass_rvalue_mutating_getter_subelement - msg: >- - cannot use mutating getter on immutable value: %0 + msg: "cannot use mutating getter on immutable value: %0" - id: cannot_pass_rvalue_mutating_getter - msg: >- - cannot use mutating getter on immutable value of type %0 + msg: "cannot use mutating getter on immutable value of type %0" - id: expression_too_complex - msg: >- - the compiler is unable to type-check this expression in reasonable time; - try breaking up the expression into distinct sub-expressions + msg: "the compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions" - id: value_type_comparison_with_nil_illegal_did_you_mean - msg: >- - value of type %0 cannot be compared by reference; did you mean to compare - by value? + msg: "value of type %0 cannot be compared by reference; did you mean to compare by value?" - id: value_type_comparison_with_nil_illegal - msg: >- - type %0 is not optional, value can never be nil + msg: "type %0 is not optional, value can never be nil" - id: cannot_match_expr_pattern_with_value - msg: >- - expression pattern of type %0 cannot match values of type %1 + msg: "expression pattern of type %0 cannot match values of type %1" - id: cannot_match_expr_tuple_pattern_with_nontuple_value - msg: >- - tuple pattern cannot match values of non-tuple type %0 + msg: "tuple pattern cannot match values of non-tuple type %0" - id: cannot_match_unresolved_expr_pattern_with_value - msg: >- - pattern cannot match values of type %0 + msg: "pattern cannot match values of type %0" - id: cannot_reference_compare_types - msg: >- - cannot check reference equality of functions; operands here have types %1 - and %2 + msg: "cannot check reference equality of functions; operands here have types %1 and %2" - id: cannot_apply_binop_to_args - msg: >- - binary operator '%0' cannot be applied to operands of type %1 and %2 + msg: "binary operator '%0' cannot be applied to operands of type %1 and %2" - id: cannot_apply_binop_to_same_args - msg: >- - binary operator '%0' cannot be applied to two %1 operands + msg: "binary operator '%0' cannot be applied to two %1 operands" - id: cannot_apply_unop_to_arg - msg: >- - unary operator '%0' cannot be applied to an operand of type %1 + msg: "unary operator '%0' cannot be applied to an operand of type %1" - id: cannot_apply_lvalue_unop_to_subelement - msg: >- - cannot pass immutable value to mutating operator: %0 + msg: "cannot pass immutable value to mutating operator: %0" - id: cannot_apply_lvalue_unop_to_rvalue - msg: >- - cannot pass immutable value of type %0 to mutating operator + msg: "cannot pass immutable value of type %0 to mutating operator" - id: cannot_apply_lvalue_binop_to_subelement - msg: >- - left side of mutating operator isn't mutable: %0 + msg: "left side of mutating operator isn't mutable: %0" - id: cannot_apply_lvalue_binop_to_rvalue - msg: >- - left side of mutating operator has immutable type %0 + msg: "left side of mutating operator has immutable type %0" - id: cannot_subscript_base - msg: >- - cannot subscript a value of type %0 + msg: "cannot subscript a value of type %0" - id: cannot_subscript_ambiguous_base - msg: >- - cannot subscript a value of incorrect or ambiguous type + msg: "cannot subscript a value of incorrect or ambiguous type" - id: cannot_subscript_nil_literal - msg: >- - cannot subscript a nil literal value + msg: "cannot subscript a nil literal value" - id: conditional_cast_from_nil - msg: >- - nil literal cannot be the source of a conditional cast + msg: "nil literal cannot be the source of a conditional cast" - id: cannot_pass_rvalue_inout_subelement - msg: >- - cannot pass immutable value as inout argument: %0 + msg: "cannot pass immutable value as inout argument: %0" - id: cannot_pass_rvalue_inout_converted - msg: >- - inout argument could be set to a value with a type other than %0; use a - value declared as type %1 instead + msg: "inout argument could be set to a value with a type other than %0; use a value declared as type %1 instead" - id: inout_change_var_type_if_possible - msg: >- - change variable type to %1 if it doesn't need to be declared as %0 + msg: "change variable type to %1 if it doesn't need to be declared as %0" - id: cannot_pass_rvalue_inout - msg: >- - cannot pass immutable value of type %0 as inout argument + msg: "cannot pass immutable value of type %0 as inout argument" - id: cannot_provide_default_value_inout - msg: >- - cannot provide default value to inout parameter %0 + msg: "cannot provide default value to inout parameter %0" - id: cannot_call_with_params - msg: >- - cannot invoke %select{|initializer for type }2'%0' with an argument list - of type '%1' + msg: "cannot invoke %select{|initializer for type }2'%0' with an argument list of type '%1'" - id: cannot_call_non_function_value - msg: >- - cannot call value of non-function type %0 + msg: "cannot call value of non-function type %0" - id: no_candidates_match_result_type - msg: >- - no '%0' candidates produce the expected contextual result type %1 + msg: "no '%0' candidates produce the expected contextual result type %1" - id: no_candidates_match_argument_type - msg: >- - no '%0' candidates produce the expected type %1 for parameter #%2 + msg: "no '%0' candidates produce the expected type %1 for parameter #%2" - id: cannot_infer_closure_parameter_type - msg: >- - unable to infer type of a closure parameter %0 in the current context + msg: "unable to infer type of a closure parameter %0 in the current context" - id: cannot_infer_closure_type - msg: >- - unable to infer closure type in the current context + msg: "unable to infer closure type in the current context" - id: cannot_infer_closure_result_type - msg: >- - unable to infer%select{ complex|}0 closure return type; add explicit type - to disambiguate + msg: "unable to infer%select{ complex|}0 closure return type; add explicit type to disambiguate" - id: incorrect_explicit_closure_result - msg: >- - declared closure result %0 is incompatible with contextual type %1 + msg: "declared closure result %0 is incompatible with contextual type %1" - id: suggest_expected_match - msg: >- - %select{expected an argument list|produces result}0 of type '%1' + msg: "%select{expected an argument list|produces result}0 of type '%1'" - id: suggest_partial_overloads - msg: >- - overloads for '%1' exist with these %select{partially matching parameter - lists|result types}0: %2 + msg: "overloads for '%1' exist with these %select{partially matching parameter lists|result types}0: %2" - id: no_binary_op_overload_for_enum_with_payload - msg: >- - binary operator '%0' cannot be synthesized for enums with associated - values + msg: "binary operator '%0' cannot be synthesized for enums with associated values" - id: cannot_convert_initializer_value - msg: >- - cannot convert value of type %0 to specified type %1 + msg: "cannot convert value of type %0 to specified type %1" - id: cannot_convert_initializer_value_protocol - msg: >- - value of type %0 does not conform to specified type %1 + msg: "value of type %0 does not conform to specified type %1" - id: cannot_convert_initializer_value_anyobject - msg: >- - value of type %0 expected to be instance of class or class-constrained - type + msg: "value of type %0 expected to be instance of class or class-constrained type" - id: cannot_convert_initializer_value_nil - msg: >- - 'nil' cannot initialize specified type %0 + msg: "'nil' cannot initialize specified type %0" - id: cannot_convert_to_return_type - msg: >- - cannot convert return expression of type %0 to return type %1 + msg: "cannot convert return expression of type %0 to return type %1" - id: cannot_convert_to_return_type_protocol - msg: >- - return expression of type %0 does not conform to %1 + msg: "return expression of type %0 does not conform to %1" - id: cannot_convert_return_type_to_anyobject - msg: >- - return expression of type %0 expected to be an instance of a class or - class-constrained type + msg: "return expression of type %0 expected to be an instance of a class or class-constrained type" - id: cannot_convert_to_return_type_nil - msg: >- - 'nil' is incompatible with return type %0 + msg: "'nil' is incompatible with return type %0" - id: cannot_convert_thrown_type - msg: >- - thrown expression type %0 does not conform to 'Error' + msg: "thrown expression type %0 does not conform to 'Error'" - id: cannot_throw_error_code - msg: >- - thrown error code type %0 does not conform to 'Error'; construct an %1 - instance + msg: "thrown error code type %0 does not conform to 'Error'; construct an %1 instance" - id: bad_yield_count - msg: >- - expected %0 yield value(s) + msg: "expected %0 yield value(s)" - id: cannot_throw_nil - msg: >- - cannot infer concrete Error for thrown 'nil' value + msg: "cannot infer concrete Error for thrown 'nil' value" - id: cannot_convert_raw_initializer_value - msg: >- - cannot convert value of type %0 to raw type %1 + msg: "cannot convert value of type %0 to raw type %1" - id: cannot_convert_raw_initializer_value_nil - msg: >- - cannot convert 'nil' to raw type %0 + msg: "cannot convert 'nil' to raw type %0" - id: cannot_convert_default_arg_value - msg: >- - default argument value of type %0 cannot be converted to type %1 + msg: "default argument value of type %0 cannot be converted to type %1" - id: cannot_convert_default_arg_value_protocol - msg: >- - default argument value of type %0 does not conform to %1 + msg: "default argument value of type %0 does not conform to %1" - id: cannot_convert_default_arg_value_nil - msg: >- - nil default argument value cannot be converted to type %0 + msg: "nil default argument value cannot be converted to type %0" - id: cannot_convert_argument_value - msg: >- - cannot convert value of type %0 to expected argument type %1 + msg: "cannot convert value of type %0 to expected argument type %1" - id: candidate_has_invalid_argument_at_position - msg: >- - candidate expects %select{|in-out }2value of type %0 for parameter #%1 + msg: "candidate expects %select{|in-out }2value of type %0 for parameter #%1" - id: cannot_convert_array_to_variadic - msg: >- - cannot pass array of type %0 as variadic arguments of type %1 + msg: "cannot pass array of type %0 as variadic arguments of type %1" - id: candidate_would_match_array_to_variadic - msg: >- - candidate would match if array elements were passed as variadic arguments - of type %0 + msg: "candidate would match if array elements were passed as variadic arguments of type %0" - id: suggest_pass_elements_directly - msg: >- - remove brackets to pass array elements directly + msg: "remove brackets to pass array elements directly" - id: cannot_convert_argument_value_generic - msg: >- - cannot convert value of type %0 (%1) to expected argument type %2 (%3) + msg: "cannot convert value of type %0 (%1) to expected argument type %2 (%3)" - id: conflicting_arguments_for_generic_parameter - msg: >- - conflicting arguments to generic parameter %0 (%1) + msg: "conflicting arguments to generic parameter %0 (%1)" - id: cannot_pass_type_to_non_ephemeral - msg: >- - cannot pass %0 to parameter; argument %1 must be a pointer that outlives - the call%select{| to %3}2 + msg: "cannot pass %0 to parameter; argument %1 must be a pointer that outlives the call%select{| to %3}2" - id: cannot_pass_type_to_non_ephemeral_warning - msg: >- - passing %0 to parameter, but argument %1 should be a pointer that - outlives the call%select{| to %3}2 + msg: "passing %0 to parameter, but argument %1 should be a pointer that outlives the call%select{| to %3}2" - id: cannot_use_inout_non_ephemeral - msg: >- - cannot use inout expression here; argument %0 must be a pointer that - outlives the call%select{| to %2}1 + msg: "cannot use inout expression here; argument %0 must be a pointer that outlives the call%select{| to %2}1" - id: cannot_use_inout_non_ephemeral_warning - msg: >- - inout expression creates a temporary pointer, but argument %0 should be a - pointer that outlives the call%select{| to %2}1 + msg: "inout expression creates a temporary pointer, but argument %0 should be a pointer that outlives the call%select{| to %2}1" - id: cannot_construct_dangling_pointer - msg: >- - initialization of %0 results in a dangling %select{|buffer }1pointer + msg: "initialization of %0 results in a dangling %select{|buffer }1pointer" - id: cannot_construct_dangling_pointer_warning - msg: >- - initialization of %0 results in a dangling %select{|buffer }1pointer + msg: "initialization of %0 results in a dangling %select{|buffer }1pointer" - id: ephemeral_pointer_argument_conversion_note - msg: >- - implicit argument conversion from %0 to %1 produces a pointer valid only - for the duration of the call%select{| to %3}2 + msg: "implicit argument conversion from %0 to %1 produces a pointer valid only for the duration of the call%select{| to %3}2" - id: ephemeral_use_with_unsafe_pointer - msg: >- - use 'withUnsafe%select{Bytes|MutableBytes|Pointer|MutablePointer}0' in - order to explicitly convert argument to %select{buffer |buffer ||}0pointer - valid for a defined scope + msg: "use 'withUnsafe%select{Bytes|MutableBytes|Pointer|MutablePointer}0' in order to explicitly convert argument to %select{buffer |buffer ||}0pointer valid for a defined scope" - id: ephemeral_use_string_with_c_string - msg: >- - use the 'withCString' method on String in order to explicitly convert - argument to pointer valid for a defined scope + msg: "use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope" - id: ephemeral_use_array_with_unsafe_buffer - msg: >- - use the - 'withUnsafe%select{Bytes|MutableBytes|BufferPointer|MutableBufferPointer}0' - method on Array in order to explicitly convert argument to buffer pointer valid - for a defined scope + msg: "use the 'withUnsafe%select{Bytes|MutableBytes|BufferPointer|MutableBufferPointer}0' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope" - id: candidate_performs_illegal_ephemeral_conv - msg: >- - candidate expects pointer that outlives the call for parameter #%0 + msg: "candidate expects pointer that outlives the call for parameter #%0" - id: cannot_convert_argument_value_protocol - msg: >- - argument type %0 does not conform to expected type %1 + msg: "argument type %0 does not conform to expected type %1" - id: cannot_convert_argument_value_anyobject - msg: >- - argument type %0 expected to be an instance of a class or - class-constrained type + msg: "argument type %0 expected to be an instance of a class or class-constrained type" - id: cannot_convert_argument_value_nil - msg: >- - 'nil' is not compatible with expected argument type %0 + msg: "'nil' is not compatible with expected argument type %0" - id: cannot_convert_condition_value - msg: >- - cannot convert value of type %0 to expected condition type %1 + msg: "cannot convert value of type %0 to expected condition type %1" - id: cannot_convert_condition_value_nil - msg: >- - 'nil' is not compatible with expected condition type %0 + msg: "'nil' is not compatible with expected condition type %0" - id: cannot_yield_rvalue_by_reference_same_type - msg: >- - cannot yield immutable value of type %0 as an inout yield + msg: "cannot yield immutable value of type %0 as an inout yield" - id: cannot_yield_rvalue_by_reference - msg: >- - cannot yield immutable value of type %0 as an inout yield of type %1 + msg: "cannot yield immutable value of type %0 as an inout yield of type %1" - id: cannot_yield_wrong_type_by_reference - msg: >- - cannot yield reference to storage of type %0 as an inout yield of type %1 + msg: "cannot yield reference to storage of type %0 as an inout yield of type %1" - id: cannot_convert_yield_value - msg: >- - cannot convert value of type %0 to expected yield type %1 + msg: "cannot convert value of type %0 to expected yield type %1" - id: cannot_convert_yield_value_protocol - msg: >- - yielded type %0 does not conform to expected type %1 + msg: "yielded type %0 does not conform to expected type %1" - id: cannot_convert_yield_value_nil - msg: >- - nil is not compatible with expected yield type %0 + msg: "nil is not compatible with expected yield type %0" - id: cannot_convert_closure_result - msg: >- - cannot convert value of type %0 to closure result type %1 + msg: "cannot convert value of type %0 to closure result type %1" - id: cannot_convert_closure_result_protocol - msg: >- - result value of type %0 does not conform to closure result type %1 + msg: "result value of type %0 does not conform to closure result type %1" - id: cannot_convert_closure_result_nil - msg: >- - 'nil' is not compatible with closure result type %0 + msg: "'nil' is not compatible with closure result type %0" - id: cannot_convert_parent_type + msg: "cannot convert parent type %0 to expected type %1" + +- id: cannot_convert_chain_result_type msg: >- - cannot convert parent type %0 to expected type %1 + member chain produces result of type %0 but contextual base was inferred as %1 - id: generic_argument_mismatch - msg: >- - arguments to generic parameter %0 (%1 and %2) are expected to be equal + msg: "arguments to generic parameter %0 (%1 and %2) are expected to be equal" - id: destructor_not_accessible - msg: >- - deinitializers cannot be accessed + msg: "deinitializers cannot be accessed" - id: cannot_convert_array_element - msg: >- - cannot convert value of type %0 to expected element type %1 + msg: "cannot convert value of type %0 to expected element type %1" - id: cannot_convert_array_element_protocol - msg: >- - value of type %0 does not conform to expected element type %1 + msg: "value of type %0 does not conform to expected element type %1" - id: cannot_convert_array_element_nil - msg: >- - 'nil' is not compatible with expected element type %0 + msg: "'nil' is not compatible with expected element type %0" - id: cannot_convert_dict_key - msg: >- - cannot convert value of type %0 to expected dictionary key type %1 + msg: "cannot convert value of type %0 to expected dictionary key type %1" - id: cannot_convert_dict_key_protocol - msg: >- - value of type %0 does not conform to expected dictionary key type %1 + msg: "value of type %0 does not conform to expected dictionary key type %1" - id: cannot_convert_dict_key_nil - msg: >- - 'nil' is not compatible with expected dictionary key type %0 + msg: "'nil' is not compatible with expected dictionary key type %0" - id: cannot_convert_dict_value - msg: >- - cannot convert value of type %0 to expected dictionary value type %1 + msg: "cannot convert value of type %0 to expected dictionary value type %1" - id: cannot_convert_dict_value_protocol - msg: >- - value of type %0 does not conform to expected dictionary value type %1 + msg: "value of type %0 does not conform to expected dictionary value type %1" - id: cannot_convert_dict_value_nil - msg: >- - 'nil' is not compatible with expected dictionary value type %0 + msg: "'nil' is not compatible with expected dictionary value type %0" - id: cannot_convert_coerce - msg: >- - cannot convert value of type %0 to type %1 in coercion + msg: "cannot convert value of type %0 to type %1 in coercion" - id: cannot_convert_coerce_protocol - msg: >- - value of type %0 does not conform to %1 in coercion + msg: "value of type %0 does not conform to %1 in coercion" - id: cannot_convert_coerce_nil - msg: >- - 'nil' is not compatible with type %0 in coercion + msg: "'nil' is not compatible with type %0 in coercion" - id: cannot_convert_assign - msg: >- - cannot assign value of type %0 to type %1 + msg: "cannot assign value of type %0 to type %1" - id: assign_protocol_conformance_fix_it - msg: >- - add missing conformance to %0 to %1 %2 + msg: "add missing conformance to %0 to %1 %2" - id: cannot_convert_assign_protocol - msg: >- - value of type %0 does not conform to %1 in assignment + msg: "value of type %0 does not conform to %1 in assignment" - id: cannot_convert_assign_anyobject - msg: >- - value of type %0 expected to be an instance of a class or - class-constrained type in assignment + msg: "value of type %0 expected to be an instance of a class or class-constrained type in assignment" - id: cannot_convert_assign_nil - msg: >- - 'nil' cannot be assigned to type %0 + msg: "'nil' cannot be assigned to type %0" - id: cannot_convert_subscript_assign - msg: >- - cannot assign value of type %0 to subscript of type %1 + msg: "cannot assign value of type %0 to subscript of type %1" - id: cannot_convert_subscript_assign_protocol - msg: >- - value of type %0 does not conform to %1 in subscript assignment + msg: "value of type %0 does not conform to %1 in subscript assignment" - id: cannot_convert_subscript_assign_nil - msg: >- - 'nil' cannot be assigned to subscript of type %0 + msg: "'nil' cannot be assigned to subscript of type %0" - id: cannot_convert_candidate_result_to_contextual_type - msg: >- - %0 produces %1, not the expected contextual result type %2 + msg: "%0 produces %1, not the expected contextual result type %2" - id: cannot_convert_sequence_element_value - msg: >- - cannot convert sequence element type %0 to expected type %1 + msg: "cannot convert sequence element type %0 to expected type %1" - id: cannot_convert_sequence_element_protocol - msg: >- - sequence element type %0 does not conform to expected protocol %1 + msg: "sequence element type %0 does not conform to expected protocol %1" - id: throws_functiontype_mismatch - msg: >- - invalid conversion from throwing function of type %0 to non-throwing - function type %1 + msg: "invalid conversion from throwing function of type %0 to non-throwing function type %1" - id: expr_keypath_no_objc_runtime - msg: >- - '#keyPath' can only be used with the Objective-C runtime + msg: "'#keyPath' can only be used with the Objective-C runtime" - id: expression_unused_keypath_result - msg: >- - result of key path is unused + msg: "result of key path is unused" - id: expr_keypath_non_objc_property - msg: >- - argument of '#keyPath' refers to non-'@objc' property %0 + msg: "argument of '#keyPath' refers to non-'@objc' property %0" - id: expr_keypath_swift3_objc_inference - msg: >- - argument of '#keyPath' refers to property %0 in %1 that depends on - '@objc' inference deprecated in Swift 4 + msg: "argument of '#keyPath' refers to property %0 in %1 that depends on '@objc' inference deprecated in Swift 4" - id: expr_keypath_type_of_property - msg: >- - cannot refer to type member %0 within instance of type %1 + msg: "cannot refer to type member %0 within instance of type %1" - id: expr_keypath_generic_type - msg: >- - key path cannot refer to generic type %0 + msg: "key path cannot refer to generic type %0" - id: expr_keypath_not_property - msg: >- - %select{key path|dynamic key path member lookup}2 cannot refer to %0 %1 + msg: "%select{key path|dynamic key path member lookup}2 cannot refer to %0 %1" - id: expr_keypath_mutating_getter - msg: >- - %select{key path|dynamic key path member lookup}1 cannot refer to %0, - which has a mutating getter + msg: "%select{key path|dynamic key path member lookup}1 cannot refer to %0, which has a mutating getter" - id: expr_keypath_static_member - msg: >- - %select{key path|dynamic key path member lookup}1 cannot refer to static - member %0 + msg: "%select{key path|dynamic key path member lookup}1 cannot refer to static member %0" - id: expr_keypath_enum_case - msg: >- - %select{key path|dynamic key path member lookup}1 cannot refer to enum - case %0 + msg: "%select{key path|dynamic key path member lookup}1 cannot refer to enum case %0" - id: expr_keypath_empty - msg: >- - empty key path does not refer to a property + msg: "empty key path does not refer to a property" - id: expr_unsupported_objc_key_path_component - msg: >- - an Objective-C key path cannot contain - %select{BAD|subscript|BAD|BAD|optional-forcing|optional-chaining|BAD} - components + msg: "an Objective-C key path cannot contain %select{BAD|subscript|BAD|BAD|optional-forcing|optional-chaining|BAD} components" - id: expr_unsupported_objc_key_path_compound_name - msg: >- - an Objective-C key path cannot reference a declaration with a compound name + msg: "an Objective-C key path cannot reference a declaration with a compound name" - id: expr_keypath_no_keypath_type - msg: >- - broken standard library: no 'KeyPath' type found + msg: "broken standard library: no 'KeyPath' type found" - id: expr_swift_keypath_invalid_component - msg: >- - invalid component of Swift key path + msg: "invalid component of Swift key path" - id: expr_swift_keypath_not_starting_with_type - msg: >- - a Swift key path must begin with a type + msg: "a Swift key path must begin with a type" - id: expr_swift_keypath_not_starting_with_dot - msg: >- - a Swift key path with contextual root must begin with a leading dot + msg: "a Swift key path with contextual root must begin with a leading dot" - id: expr_smart_keypath_value_covert_to_contextual_type - msg: >- - key path value type %0 cannot be converted to contextual type %1 + msg: "key path value type %0 cannot be converted to contextual type %1" - id: expr_swift_keypath_empty - msg: >- - key path must have at least one component + msg: "key path must have at least one component" - id: expr_string_interpolation_outside_string - msg: >- - string interpolation can only appear inside a string literal + msg: "string interpolation can only appear inside a string literal" - id: expr_keypath_subscript_index_not_hashable - msg: >- - subscript index of type %0 in a key path must be Hashable + msg: "subscript index of type %0 in a key path must be Hashable" - id: expr_smart_keypath_application_type_mismatch - msg: >- - key path of type %0 cannot be applied to a base of type %1 + msg: "key path of type %0 cannot be applied to a base of type %1" - id: expr_keypath_root_type_mismatch - msg: >- - key path with root type %0 cannot be applied to a base of type %1 + msg: "key path with root type %0 cannot be applied to a base of type %1" - id: expr_swift_keypath_anyobject_root - msg: >- - the root type of a Swift key path cannot be 'AnyObject' + msg: "the root type of a Swift key path cannot be 'AnyObject'" - id: expr_keypath_multiparam_func_conversion - msg: >- - cannot convert key path into a multi-argument function type %0 + msg: "cannot convert key path into a multi-argument function type %0" - id: expr_deprecated_writable_keypath - msg: >- - forming a writable keypath to property %0 that is read-only in this - context is deprecated and will be removed in a future release + msg: "forming a writable keypath to property %0 that is read-only in this context is deprecated and will be removed in a future release" - id: expr_selector_no_objc_runtime - msg: >- - '#selector' can only be used with the Objective-C runtime + msg: "'#selector' can only be used with the Objective-C runtime" - id: expr_selector_module_missing - msg: >- - import the 'ObjectiveC' module to use '#selector' + msg: "import the 'ObjectiveC' module to use '#selector'" - id: expr_selector_no_declaration - msg: >- - argument of '#selector' does not refer to an '@objc' method, property, or - initializer + msg: "argument of '#selector' does not refer to an '@objc' method, property, or initializer" - id: expr_selector_not_method - msg: >- - argument of '#selector' cannot refer to %select{local|global}0 function %1 + msg: "argument of '#selector' cannot refer to %select{local|global}0 function %1" - id: expr_selector_expected_property - msg: >- - cannot reference %1 %2 as a property; remove '%select{getter|setter}0:' + msg: "cannot reference %1 %2 as a property; remove '%select{getter|setter}0:'" - id: expr_selector_not_property - msg: >- - argument of '#selector' cannot refer to %select{variable|parameter}0 %1 + msg: "argument of '#selector' cannot refer to %select{variable|parameter}0 %1" - id: expr_selector_expected_method - msg: >- - use 'getter:'%select{| or 'setter:'}0 to refer to the Objective-C - getter%select{| or setter}0 of property %1%select{|, respectively}0 + msg: "use 'getter:'%select{| or 'setter:'}0 to refer to the Objective-C getter%select{| or setter}0 of property %1%select{|, respectively}0" - id: expr_selector_add_modifier - msg: >- - add '%select{getter|setter}0:' to reference the Objective-C - %select{getter|setter}0 for %1 + msg: "add '%select{getter|setter}0:' to reference the Objective-C %select{getter|setter}0 for %1" - id: expr_selector_property_not_settable - msg: >- - argument of '#selector(setter:)' refers to non-settable %0 %1 + msg: "argument of '#selector(setter:)' refers to non-settable %0 %1" - id: expr_selector_property_setter_inaccessible - msg: >- - setter of %0 %1 is inaccessible + msg: "setter of %0 %1 is inaccessible" - id: expr_selector_cannot_be_used - msg: >- - cannot use %0 as a selector because protocol %1 is not exposed to - Objective-C + msg: "cannot use %0 as a selector because protocol %1 is not exposed to Objective-C" - id: expr_selector_not_objc - msg: >- - argument of '#selector' refers to %0 %1 that is not exposed to Objective-C + msg: "argument of '#selector' refers to %0 %1 that is not exposed to Objective-C" - id: make_decl_objc - msg: >- - add '@objc' to expose this %0 to Objective-C + msg: "add '@objc' to expose this %0 to Objective-C" - id: expr_selector_swift3_objc_inference - msg: >- - argument of '#selector' refers to %0 %1 in %2 that depends on '@objc' - inference deprecated in Swift 4 + msg: "argument of '#selector' refers to %0 %1 in %2 that depends on '@objc' inference deprecated in Swift 4" - id: selector_literal_invalid - msg: >- - string literal is not a valid Objective-C selector + msg: "string literal is not a valid Objective-C selector" - id: selector_literal_undeclared - msg: >- - no method declared with Objective-C selector %0 + msg: "no method declared with Objective-C selector %0" - id: selector_literal_deprecated - msg: >- - use of string literal for Objective-C selectors is deprecated; use - '#selector' or explicitly construct a 'Selector' + msg: "use of string literal for Objective-C selectors is deprecated; use '#selector' or explicitly construct a 'Selector'" - id: selector_literal_deprecated_suggest - msg: >- - use of string literal for Objective-C selectors is deprecated; use - '#selector' instead + msg: "use of string literal for Objective-C selectors is deprecated; use '#selector' instead" - id: selector_construction_suggest - msg: >- - use '#selector' instead of explicitly constructing a 'Selector' + msg: "use '#selector' instead of explicitly constructing a 'Selector'" - id: selector_construction_suppress_warning - msg: >- - wrap the selector name in parentheses to suppress this warning + msg: "wrap the selector name in parentheses to suppress this warning" - id: cannot_return_value_from_void_func - msg: >- - unexpected non-void return value in void function + msg: "unexpected non-void return value in void function" - id: add_return_type_note - msg: >- - did you mean to add a return type? + msg: "did you mean to add a return type?" - id: sema_no_import - msg: >- - no such module '%0' + msg: "no such module '%0'" - id: sema_no_import_target - msg: >- - could not find module '%0' for target '%1'; found: %2 + msg: "could not find module '%0' for target '%1'; found: %2" - id: sema_no_import_repl - msg: >- - no such module '%0' + msg: "no such module '%0'" - id: sema_no_import_no_sdk - msg: >- - did you forget to set an SDK using -sdk or SDKROOT? + msg: "did you forget to set an SDK using -sdk or SDKROOT?" - id: sema_no_import_no_sdk_xcrun - msg: >- - use "xcrun swiftc" to select the default macOS SDK installed with Xcode + msg: "use \"xcrun swiftc\" to select the default macOS SDK installed with Xcode" - id: sema_import_current_module - msg: >- - this file is part of module %0; ignoring import + msg: "this file is part of module %0; ignoring import" - id: sema_import_current_module_with_file - msg: >- - file '%0' is part of module %1; ignoring import + msg: "file '%0' is part of module %1; ignoring import" - id: sema_opening_import - msg: >- - opening import file for module %0: %1 + msg: "opening import file for module %0: %1" - id: serialization_load_failed - msg: >- - failed to load module '%0' + msg: "failed to load module '%0'" - id: module_interface_build_failed - msg: >- - failed to build module '%0' from its module interface; %select{the - compiler that produced it, '%2', may have used features that aren't - supported by this compiler, '%3'|it may have been damaged - or it may have triggered a bug in the Swift compiler when it was produced}1 + msg: "failed to build module '%0' from its module interface; %select{the compiler that produced it, '%2', may have used features that aren't supported by this compiler, '%3'|it may have been damaged or it may have triggered a bug in the Swift compiler when it was produced}1" - id: serialization_malformed_module - msg: >- - malformed compiled module: %0 + msg: "malformed compiled module: %0" - id: serialization_module_too_new - msg: >- - compiled module was created by a newer version of the compiler: %0 + msg: "compiled module was created by a newer version of the compiler: %0" - id: serialization_module_language_version_mismatch - msg: >- - module compiled with Swift %0 cannot be imported by the Swift %1 - compiler: %2 + msg: "module compiled with Swift %0 cannot be imported by the Swift %1 compiler: %2" - id: serialization_module_too_old - msg: >- - compiled module was created by an older version of the compiler; rebuild - %0 and try again: %1 + msg: "compiled module was created by an older version of the compiler; rebuild %0 and try again: %1" - id: serialization_missing_single_dependency - msg: >- - missing required module '%0' + msg: "missing required module '%0'" - id: serialization_missing_dependencies - msg: >- - missing required modules: %0 + msg: "missing required modules: %0" - id: serialization_circular_dependency - msg: >- - circular dependency between modules '%0' and %1 + msg: "circular dependency between modules '%0' and %1" - id: serialization_missing_underlying_module - msg: >- - cannot load underlying module for %0 + msg: "cannot load underlying module for %0" - id: serialization_name_mismatch - msg: >- - cannot load module '%0' as '%1' + msg: "cannot load module '%0' as '%1'" - id: serialization_name_mismatch_repl - msg: >- - cannot load module '%0' as '%1' + msg: "cannot load module '%0' as '%1'" - id: serialization_target_incompatible - msg: >- - module %0 was created for incompatible target %1: %2 + msg: "module %0 was created for incompatible target %1: %2" - id: serialization_target_incompatible_repl - msg: >- - module %0 was created for incompatible target %1: %2 + msg: "module %0 was created for incompatible target %1: %2" - id: serialization_target_too_new - msg: >- - compiling for %0 %1, but module %2 has a minimum deployment target of %0 - %3: %4 + msg: "compiling for %0 %1, but module %2 has a minimum deployment target of %0 %3: %4" - id: serialization_target_too_new_repl - msg: >- - compiling for %0 %1, but module %2 has a minimum deployment target of %0 - %3: %4 + msg: "compiling for %0 %1, but module %2 has a minimum deployment target of %0 %3: %4" - id: serialization_fatal - msg: >- - fatal error encountered while reading from module '%0'; please file a bug - report with your project and the crash log + msg: "fatal error encountered while reading from module '%0'; please file a bug report with your project and the crash log" - id: serialization_misc_version - msg: >- - module '%0' full misc version is '%1' + msg: "module '%0' full misc version is '%1'" - id: serialization_compatibility_version_mismatch - msg: >- - compiling as Swift %0, with '%1' built as Swift %2 (this is supported but - may expose additional compiler issues) + msg: "compiling as Swift %0, with '%1' built as Swift %2 (this is supported but may expose additional compiler issues)" - id: reserved_member_name - msg: >- - type member must not be named %0, since it would conflict with the - 'foo.%1' expression + msg: "type member must not be named %0, since it would conflict with the 'foo.%1' expression" - id: invalid_redecl - msg: >- - invalid redeclaration of %0 + msg: "invalid redeclaration of %0" - id: invalid_redecl_init - msg: >- - invalid redeclaration of synthesized %select{|memberwise }1%0 + msg: "invalid redeclaration of synthesized %select{|memberwise }1%0" - id: invalid_redecl_implicit - msg: >- - invalid redeclaration of synthesized %select{%0|implementation for - protocol requirement}1 %2 + msg: "invalid redeclaration of synthesized %select{%0|implementation for protocol requirement}1 %2" - id: invalid_redecl_swift5_warning - msg: >- - redeclaration of %0 is deprecated and will be an error in Swift 5 + msg: "redeclaration of %0 is deprecated and will be an error in Swift 5" - id: invalid_redecl_prev - msg: >- - %0 previously declared here + msg: "%0 previously declared here" - id: invalid_redecl_implicit_wrapper - msg: >- - %0 synthesized for property wrapper %select{projected value|backing - storage}1 + msg: "%0 synthesized for property wrapper %select{projected value|backing storage}1" - id: ambiguous_type_base - msg: >- - %0 is ambiguous for type lookup in this context + msg: "%0 is ambiguous for type lookup in this context" - id: invalid_member_type - msg: >- - %0 is not a member type of %1 + msg: "%0 is not a member type of %1" - id: invalid_member_type_suggest - msg: >- - %0 does not have a member type named %1; did you mean %2? + msg: "%0 does not have a member type named %1; did you mean %2?" - id: invalid_member_reference - msg: >- - %0 %1 is not a member type of %2 + msg: "%0 %1 is not a member type of %2" - id: ambiguous_member_type - msg: >- - ambiguous type name %0 in %1 + msg: "ambiguous type name %0 in %1" - id: no_module_type - msg: >- - no type named %0 in module %1 + msg: "no type named %0 in module %1" - id: ambiguous_module_type - msg: >- - ambiguous type name %0 in module %1 + msg: "ambiguous type name %0 in module %1" - id: use_nonmatching_operator - msg: >- - %0 is not a %select{binary|prefix unary|postfix unary}1 operator + msg: "%0 is not a %select{binary|prefix unary|postfix unary}1 operator" - id: unsupported_recursion_in_associated_type_reference - msg: >- - unsupported recursion for reference to %select{associated type|type - alias}0 %1 of type %2 + msg: "unsupported recursion for reference to %select{associated type|type alias}0 %1 of type %2" - id: broken_associated_type_witness - msg: >- - reference to invalid %select{associated type|type alias}0 %1 of type %2 + msg: "reference to invalid %select{associated type|type alias}0 %1 of type %2" - id: unspaced_binary_operator_fixit - msg: >- - missing whitespace between %0 and %1 operators + msg: "missing whitespace between %0 and %1 operators" - id: unspaced_binary_operator - msg: >- - ambiguous missing whitespace between unary and binary operators + msg: "ambiguous missing whitespace between unary and binary operators" - id: unspaced_binary_operators_candidate - msg: >- - could be %select{binary|postfix}2 %0 and %select{prefix|binary}2 %1 + msg: "could be %select{binary|postfix}2 %0 and %select{prefix|binary}2 %1" - id: unspaced_unary_operator - msg: >- - unary operators must not be juxtaposed; parenthesize inner expression + msg: "unary operators must not be juxtaposed; parenthesize inner expression" - id: cannot_find_in_scope - msg: >- - cannot %select{find|find operator}1 %0 in scope + msg: "cannot %select{find|find operator}1 %0 in scope" - id: cannot_find_in_scope_corrected - msg: >- - cannot %select{find|find operator}1 %0 in scope; did you mean '%2'? + msg: "cannot %select{find|find operator}1 %0 in scope; did you mean '%2'?" - id: confusable_character - msg: >- - %select{identifier|operator}0 '%1' contains possibly confused characters; - did you mean to use '%2'? + msg: "%select{identifier|operator}0 '%1' contains possibly confused characters; did you mean to use '%2'?" + - id: single_confusable_character - msg: >- - %select{identifier|operator}0 '%1' (%2) looks similar to '%3' (%4); did you mean '%3' (%4)?" + msg: "%select{identifier|operator}0 '%1' (%2) looks similar to '%3' (%4); did you mean '%3' (%4)?" - id: cannot_find_type_in_scope - msg: >- - cannot find type %0 in scope + msg: "cannot find type %0 in scope" - id: cannot_find_type_in_scope_did_you_mean - msg: >- - cannot find type %0 in scope; did you mean to use '%1'? + msg: "cannot find type %0 in scope; did you mean to use '%1'?" - id: note_typo_candidate_implicit_member - msg: >- - did you mean the implicitly-synthesized %1 '%0'? + msg: "did you mean the implicitly-synthesized %1 '%0'?" - id: note_remapped_type - msg: >- - did you mean to use '%0'? + msg: "did you mean to use '%0'?" - id: note_module_as_type - msg: >- - cannot use module %0 as a type + msg: "cannot use module %0 as a type" - id: use_unknown_object_literal_protocol - msg: >- - cannot deduce protocol for %0 literal + msg: "cannot deduce protocol for %0 literal" - id: object_literal_default_type_missing - msg: >- - could not infer type of %0 literal + msg: "could not infer type of %0 literal" - id: object_literal_resolve_import - msg: >- - import %0 to use '%1' as the default %2 literal type + msg: "import %0 to use '%1' as the default %2 literal type" - id: use_local_before_declaration - msg: >- - use of local variable %0 before its declaration + msg: "use of local variable %0 before its declaration" - id: unsupported_existential_type - msg: >- - protocol %0 can only be used as a generic constraint because it has Self - or associated type requirements + msg: "protocol %0 can only be used as a generic constraint because it has Self or associated type requirements" - id: decl_does_not_exist_in_module - msg: >- - %select{%error|type|struct|class|enum|protocol|variable|function}0 %1 - does not exist in module %2 + msg: "%select{%error|type|struct|class|enum|protocol|variable|function}0 %1 does not exist in module %2" - id: imported_decl_is_wrong_kind - msg: >- - %0 was imported as '%1', but is %select{%error|a type|a struct|a class|an - enum|a protocol|a variable|a function}2 + msg: "%0 was imported as '%1', but is %select{%error|a type|a struct|a class|an enum|a protocol|a variable|a function}2" - id: imported_decl_is_wrong_kind_typealias - msg: >- - %0 %1 cannot be imported as '%2' + msg: "%0 %1 cannot be imported as '%2'" - id: ambiguous_decl_in_module - msg: >- - ambiguous name %0 in module %1 + msg: "ambiguous name %0 in module %1" - id: module_not_testable - msg: >- - module %0 was not compiled for testing + msg: "module %0 was not compiled for testing" - id: module_not_compiled_for_private_import - msg: >- - module %0 was not compiled for private import + msg: "module %0 was not compiled for private import" - id: import_implementation_cannot_be_exported - msg: >- - module %0 cannot be both exported and implementation-only + msg: "module %0 cannot be both exported and implementation-only" - id: module_not_compiled_with_library_evolution - msg: >- - module %0 was not compiled with library evolution support; using it means - binary compatibility for %1 can't be guaranteed + msg: "module %0 was not compiled with library evolution support; using it means binary compatibility for %1 can't be guaranteed" - id: cross_import_added - msg: >- - import of %0 and %1 triggered a cross-import of %2 + msg: "import of %0 and %1 triggered a cross-import of %2" - id: ambiguous_operator_decls - msg: >- - ambiguous operator declarations found for operator + msg: "ambiguous operator declarations found for operator" - id: found_this_operator_decl - msg: >- - found this matching operator declaration + msg: "found this matching operator declaration" - id: operator_redeclared - msg: >- - operator redeclared + msg: "operator redeclared" - id: previous_operator_decl - msg: >- - previous operator declaration here + msg: "previous operator declaration here" - id: declared_operator_without_operator_decl - msg: >- - operator implementation without matching operator declaration + msg: "operator implementation without matching operator declaration" - id: declared_unary_op_without_attribute - msg: >- - unary operator implementation must have a 'prefix' or 'postfix' modifier + msg: "unary operator implementation must have a 'prefix' or 'postfix' modifier" - id: unary_op_missing_prepos_attribute - msg: >- - %select{prefix|postfix}0 unary operator missing - '%select{prefix|postfix}0' modifier + msg: "%select{prefix|postfix}0 unary operator missing '%select{prefix|postfix}0' modifier" - id: unary_operator_declaration_here - msg: >- - %select{prefix|postfix}0 operator found here + msg: "%select{prefix|postfix}0 operator found here" - id: invalid_arg_count_for_operator - msg: >- - operators must have one or two arguments + msg: "operators must have one or two arguments" - id: operator_in_local_scope - msg: >- - operator functions can only be declared at global or in type scope + msg: "operator functions can only be declared at global or in type scope" - id: nonstatic_operator_in_nominal - msg: >- - operator %0 declared in type %1 must be 'static' + msg: "operator %0 declared in type %1 must be 'static'" - id: nonstatic_operator_in_extension - msg: >- - operator %0 declared in extension%select{| of %2}1 must be 'static' + msg: "operator %0 declared in extension%select{| of %2}1 must be 'static'" - id: nonfinal_operator_in_class - msg: >- - operator %0 declared in non-final class %1 must be 'final' + msg: "operator %0 declared in non-final class %1 must be 'final'" - id: operator_in_unrelated_type - msg: >- - member operator %2%select{| of protocol %0}1 must have at least one - argument of type %select{%0|'Self'}1 + msg: "member operator %2%select{| of protocol %0}1 must have at least one argument of type %select{%0|'Self'}1" - id: ambiguous_precedence_groups - msg: >- - multiple precedence groups found + msg: "multiple precedence groups found" - id: found_this_precedence_group - msg: >- - found this matching precedence group + msg: "found this matching precedence group" - id: unknown_precedence_group - msg: >- - unknown precedence group %0 + msg: "unknown precedence group %0" - id: precedence_group_cycle - msg: >- - cycle in '%select{lowerThan|higherThan}0' relation + msg: "cycle in '%select{lowerThan|higherThan}0' relation" - id: higher_than_precedence_group_cycle - msg: >- - cycle in higherThan relation: %0 + msg: "cycle in higherThan relation: %0" - id: precedence_group_lower_within_module - msg: >- - precedence group cannot be given lower precedence than group in same - module; make the other precedence group higher than this one instead + msg: "precedence group cannot be given lower precedence than group in same module; make the other precedence group higher than this one instead" - id: precedence_group_redeclared - msg: >- - precedence group redeclared + msg: "precedence group redeclared" - id: previous_precedence_group_decl - msg: >- - previous precedence group declaration here + msg: "previous precedence group declaration here" - id: circular_reference_through_precedence_group - msg: >- - through reference to precedence group %0 here + msg: "through reference to precedence group %0 here" - id: tuple_types_not_convertible_nelts - msg: >- - %0 is not convertible to %1, tuples have a different number of elements + msg: "%0 is not convertible to %1, tuples have a different number of elements" - id: tuple_types_not_convertible - msg: >- - tuple type %0 is not convertible to tuple type %1 + msg: "tuple type %0 is not convertible to tuple type %1" - id: invalid_force_unwrap - msg: >- - cannot force unwrap value of non-optional type %0 + msg: "cannot force unwrap value of non-optional type %0" - id: invalid_optional_chain - msg: >- - cannot use optional chaining on non-optional value of type %0 + msg: "cannot use optional chaining on non-optional value of type %0" - id: if_expr_cases_mismatch - msg: >- - result values in '? :' expression have mismatching types %0 and %1 + msg: "result values in '? :' expression have mismatching types %0 and %1" - id: did_not_call_function_value - msg: >- - function value was used as a property; add () to call it + msg: "function value was used as a property; add () to call it" - id: did_not_call_function - msg: >- - function %0 was used as a property; add () to call it + msg: "function %0 was used as a property; add () to call it" - id: did_not_call_method - msg: >- - method %0 was used as a property; add () to call it + msg: "method %0 was used as a property; add () to call it" - id: init_not_instance_member_use_assignment - msg: >- - 'init' is a member of the type; use assignment to initalize the value - instead + msg: "'init' is a member of the type; use assignment to initalize the value instead" - id: init_not_instance_member - msg: >- - 'init' is a member of the type; use 'type(of: ...)' to initialize a new - object of the same dynamic type + msg: "'init' is a member of the type; use 'type(of: ...)' to initialize a new object of the same dynamic type" - id: super_initializer_not_in_initializer - msg: >- - 'super.init' cannot be called outside of an initializer + msg: "'super.init' cannot be called outside of an initializer" - id: isa_is_always_true - msg: >- - '%0' test is always true + msg: "'%0' test is always true" - id: isa_is_foreign_check - msg: >- - 'is' test is always true because %0 is a Core Foundation type + msg: "'is' test is always true because %0 is a Core Foundation type" - id: conditional_downcast_coercion - msg: >- - conditional cast from %0 to %1 always succeeds + msg: "conditional cast from %0 to %1 always succeeds" - id: literal_conditional_downcast_to_coercion - msg: >- - conditional downcast from literal to %0 always fails; consider using 'as' - coercion + msg: "conditional downcast from literal to %0 always fails; consider using 'as' coercion" - id: forced_downcast_noop - msg: >- - forced cast of %0 to same type has no effect + msg: "forced cast of %0 to same type has no effect" - id: forced_downcast_coercion - msg: >- - forced cast from %0 to %1 always succeeds; did you mean to use 'as'? + msg: "forced cast from %0 to %1 always succeeds; did you mean to use 'as'?" - id: downcast_same_type - msg: >- - forced cast from %0 to %1 %select{only unwraps optionals|only unwraps and - bridges}3; did you mean to use '%2'%select{| with 'as'}3? + msg: "forced cast from %0 to %1 %select{only unwraps optionals|only unwraps and bridges}3; did you mean to use '%2'%select{| with 'as'}3?" - id: conditional_downcast_same_type - msg: >- - conditional downcast from %0 to %1 %select{does nothing|is equivalent to - an implicit conversion to an optional %1|is a bridging conversion; - did you mean to use 'as'?}2 + msg: "conditional downcast from %0 to %1 %select{does nothing|is equivalent to an implicit conversion to an optional %1|is a bridging conversion; did you mean to use 'as'?}2" - id: is_expr_same_type - msg: >- - checking a value with optional type %0 against dynamic type %1 succeeds - whenever the value is non-nil; did you mean to use '!= nil'? + msg: "checking a value with optional type %0 against dynamic type %1 succeeds whenever the value is non-nil; did you mean to use '!= nil'?" - id: downcast_to_unrelated - msg: >- - cast from %0 to unrelated type %1 always fails + msg: "cast from %0 to unrelated type %1 always fails" - id: downcast_to_unrelated_fixit - msg: >- - did you mean to call %0 with '()'? + msg: "did you mean to call %0 with '()'?" - id: downcast_to_more_optional - msg: >- - cannot downcast from %0 to a more optional type %1 + msg: "cannot downcast from %0 to a more optional type %1" - id: optional_chain_noop - msg: >- - optional chain has no effect, expression already produces %0 + msg: "optional chain has no effect, expression already produces %0" - id: optional_chain_isnt_chaining - msg: >- - '?' must be followed by a call, member lookup, or subscript + msg: "'?' must be followed by a call, member lookup, or subscript" - id: pattern_in_expr - msg: >- - %0 cannot appear in an expression + msg: "%0 cannot appear in an expression" - id: note_call_to_operator - msg: >- - in call to operator %0 + msg: "in call to operator %0" - id: note_call_to_func - msg: >- - in call to function %0 + msg: "in call to function %0" - id: note_call_to_subscript - msg: >- - in call to %0 + msg: "in call to %0" - id: note_call_to_initializer - msg: >- - in call to initializer + msg: "in call to initializer" - id: note_init_parameter - msg: >- - in initialization of parameter %0 + msg: "in initialization of parameter %0" - id: missing_nullary_call - msg: >- - function produces expected type %0; did you mean to call it with '()'? + msg: "function produces expected type %0; did you mean to call it with '()'?" - id: optional_not_unwrapped - msg: >- - value of optional type %0 must be unwrapped to a value of type %1 + msg: "value of optional type %0 must be unwrapped to a value of type %1" - id: unwrap_with_default_value - msg: >- - coalesce using '??' to provide a default when the optional value contains - 'nil' + msg: "coalesce using '??' to provide a default when the optional value contains 'nil'" - id: unwrap_with_force_value - msg: >- - force-unwrap using '!' to abort execution if the optional value contains - 'nil' + msg: "force-unwrap using '!' to abort execution if the optional value contains 'nil'" - id: unwrap_iuo_initializer - msg: >- - value inferred to be type %0 when initialized with an implicitly - unwrapped value + msg: "value inferred to be type %0 when initialized with an implicitly unwrapped value" - id: unwrap_with_guard - msg: >- - short-circuit using 'guard' to exit this function early if the optional - value contains 'nil' + msg: "short-circuit using 'guard' to exit this function early if the optional value contains 'nil'" - id: optional_base_not_unwrapped - msg: >- - value of optional type %0 must be unwrapped to refer to member %1 of - wrapped base type %2 + msg: "value of optional type %0 must be unwrapped to refer to member %1 of wrapped base type %2" + +- id: invalid_optional_infered_keypath_root + msg: "key path root inferred as optional type %0 must be unwrapped to refer to member %1 of unwrapped type %2" - id: optional_base_chain - msg: >- - chain the optional using '?' to access member %0 only for non-'nil' base - values + msg: "chain the optional using '?' to access member %0 only for non-'nil' base values" - id: optional_base_remove_optional_for_keypath_root - msg: >- - use unwrapped type %0 as key path root + msg: "use unwrapped type %0 as key path root" -- id: optional_keypath_application_base - msg: >- - use '?' to access key path subscript only for non-'nil' base values +- id: optional_keypath_application_base + msg: "use '?' to access key path subscript only for non-'nil' base values" + +- id: optional_key_path_root_base_chain + msg: "chain the optional using '?.' to access unwrapped type member %0" + +- id: optional_key_path_root_base_unwrap + msg: "unwrap the optional using '!.' to access unwrapped type member %0" - id: missing_unwrap_optional_try - msg: >- - value of optional type %0 not unwrapped; did you mean to use 'try!' or - chain with '?'? + msg: "value of optional type %0 not unwrapped; did you mean to use 'try!' or chain with '?'?" - id: missing_forced_downcast - msg: >- - %0 is not convertible to %1; did you mean to use 'as!' to force downcast? + msg: "%0 is not convertible to %1; did you mean to use 'as!' to force downcast?" - id: coercion_may_fail_warning - msg: >- - coercion from %0 to %1 may fail; use 'as?' or 'as!' instead + msg: "coercion from %0 to %1 may fail; use 'as?' or 'as!' instead" - id: missing_explicit_conversion - msg: >- - %0 is not implicitly convertible to %1; did you mean to use 'as' to - explicitly convert? + msg: "%0 is not implicitly convertible to %1; did you mean to use 'as' to explicitly convert?" - id: missing_address_of - msg: >- - passing value of type %0 to an inout parameter requires explicit '&' + msg: "passing value of type %0 to an inout parameter requires explicit '&'" - id: missing_address_of_yield - msg: >- - yielding mutable value of type %0 requires explicit '&' + msg: "yielding mutable value of type %0 requires explicit '&'" - id: extraneous_address_of - msg: >- - use of extraneous '&' + msg: "use of extraneous '&'" - id: extra_address_of - msg: >- - '&' used with non-inout argument of type %0 + msg: "'&' used with non-inout argument of type %0" - id: extra_address_of_unsafepointer - msg: >- - '&' is not allowed passing array value as %0 argument + msg: "'&' is not allowed passing array value as %0 argument" - id: cannot_pass_inout_arg_to_subscript - msg: >- - cannot pass an inout argument to a subscript; use - 'withUnsafeMutablePointer' to explicitly convert argument to a pointer + msg: "cannot pass an inout argument to a subscript; use 'withUnsafeMutablePointer' to explicitly convert argument to a pointer" - id: incorrect_property_wrapper_reference - msg: >- - cannot convert value %0 of type %1 to expected type %2, use - %select{wrapper|wrapped value}3 instead + msg: "cannot convert value %0 of type %1 to expected type %2, use %select{wrapper|wrapped value}3 instead" - id: incorrect_property_wrapper_reference_member - msg: >- - referencing %0 %1 requires %select{wrapper|wrapped value of type}2 %3 + msg: "referencing %0 %1 requires %select{wrapper|wrapped value of type}2 %3" - id: missing_init_on_metatype_initialization - msg: >- - initializing from a metatype value must reference 'init' explicitly + msg: "initializing from a metatype value must reference 'init' explicitly" - id: extra_argument_labels - msg: >- - extraneous argument label%select{|s}0 '%1' in %select{call|subscript}2 + msg: "extraneous argument label%select{|s}0 '%1' in %select{call|subscript}2" - id: missing_argument_labels - msg: >- - missing argument label%select{|s}0 '%1' in %select{call|subscript}2 + msg: "missing argument label%select{|s}0 '%1' in %select{call|subscript}2" - id: wrong_argument_labels - msg: >- - incorrect argument label%select{|s}0 in %select{call|subscript}3 (have - '%1', expected '%2') + msg: "incorrect argument label%select{|s}0 in %select{call|subscript}3 (have '%1', expected '%2')" - id: argument_out_of_order_named_named - msg: >- - argument %0 must precede argument %1 + msg: "argument %0 must precede argument %1" - id: argument_out_of_order_named_unnamed - msg: >- - argument %0 must precede unnamed argument #%1 + msg: "argument %0 must precede unnamed argument #%1" - id: argument_out_of_order_unnamed_named - msg: >- - unnamed argument #%0 must precede argument %1 + msg: "unnamed argument #%0 must precede argument %1" - id: argument_out_of_order_unnamed_unnamed - msg: >- - unnamed argument #%0 must precede unnamed argument #%1 + msg: "unnamed argument #%0 must precede unnamed argument #%1" - id: argument_out_of_order_binary_op - msg: >- - operator argument #%0 must precede operator argument #%1 + msg: "operator argument #%0 must precede operator argument #%1" - id: candidate_expected_different_labels - msg: >- - incorrect labels for candidate (have: '%0', expected: '%1') + msg: "incorrect labels for candidate (have: '%0', expected: '%1')" - id: member_shadows_function - msg: >- - use of %0 refers to %1 rather than %2 %3 + msg: "use of %0 refers to %1 rather than %2 %3" - id: member_shadows_global_function - msg: >- - use of %0 refers to %1 rather than %2 %3 in module %4 + msg: "use of %0 refers to %1 rather than %2 %3 in module %4" - id: instance_member_use_on_type - msg: >- - instance member %1 cannot be used on type %0; did you mean to use a value - of this type instead? + msg: "instance member %1 cannot be used on type %0; did you mean to use a value of this type instead?" - id: instance_member_in_initializer - msg: >- - cannot use instance member %0 within property initializer; property - initializers run before 'self' is available + msg: "cannot use instance member %0 within property initializer; property initializers run before 'self' is available" - id: instance_member_in_default_parameter - msg: >- - cannot use instance member %0 as a default parameter + msg: "cannot use instance member %0 as a default parameter" - id: missing_argument_named - msg: >- - missing argument for parameter %0 in call + msg: "missing argument for parameter %0 in call" - id: missing_argument_positional - msg: >- - missing argument for parameter #%0 in call + msg: "missing argument for parameter #%0 in call" - id: missing_arguments_in_call - msg: >- - missing arguments for parameters %0 in call + msg: "missing arguments for parameters %0 in call" - id: extra_argument_named - msg: >- - extra argument %0 in call + msg: "extra argument %0 in call" - id: extra_argument_positional - msg: >- - extra argument in call + msg: "extra argument in call" - id: extra_arguments_in_call - msg: >- - extra arguments at positions %0 in call + msg: "extra arguments at positions %0 in call" - id: extra_argument_to_nullary_call - msg: >- - argument passed to call that takes no arguments + msg: "argument passed to call that takes no arguments" - id: extra_trailing_closure_in_call - msg: >- - extra trailing closure passed in call + msg: "extra trailing closure passed in call" - id: trailing_closure_bad_param - msg: >- - trailing closure passed to parameter of type %0 that does not accept a - closure + msg: "trailing closure passed to parameter of type %0 that does not accept a closure" + +- id: unlabeled_trailing_closure_deprecated + msg: "backward matching of the unlabeled trailing closure is deprecated; label the argument with %0 to suppress this warning" + +- id: decl_multiple_defaulted_closure_parameters + msg: "%0 contains defaulted closure parameters %1 and %2" - id: candidate_with_extraneous_args - msg: >- - candidate %0 requires %1 argument%s1, but %2 %select{were|was}3 - %select{provided|used in closure body}4 + msg: "candidate %0 requires %1 argument%s1, but %2 %select{were|was}3 %select{provided|used in closure body}4" - id: no_accessible_initializers - msg: >- - %0 cannot be constructed because it has no accessible initializers + msg: "%0 cannot be constructed because it has no accessible initializers" - id: non_nominal_no_initializers - msg: >- - non-nominal type %0 does not support explicit initialization + msg: "non-nominal type %0 does not support explicit initialization" - id: unbound_generic_parameter - msg: >- - generic parameter %0 could not be inferred + msg: "generic parameter %0 could not be inferred" - id: unbound_generic_parameter_cast - msg: >- - generic parameter %0 could not be inferred in cast to %1 + msg: "generic parameter %0 could not be inferred in cast to %1" - id: archetype_declared_in_type - msg: >- - %0 declared as parameter to type %1 + msg: "%0 declared as parameter to type %1" - id: unbound_generic_parameter_explicit_fix - msg: >- - explicitly specify the generic arguments to fix this issue + msg: "explicitly specify the generic arguments to fix this issue" - id: invalid_dynamic_callable_type - msg: >- - @dynamicCallable attribute requires %0 to have either a valid - 'dynamicallyCall(withArguments:)' method or - 'dynamicallyCall(withKeywordArguments:)' method + msg: "@dynamicCallable attribute requires %0 to have either a valid 'dynamicallyCall(withArguments:)' method or 'dynamicallyCall(withKeywordArguments:)' method" - id: missing_dynamic_callable_kwargs_method - msg: >- - @dynamicCallable type %0 cannot be applied with keyword arguments; - missing 'dynamicCall(withKeywordArguments:)' method + msg: "@dynamicCallable type %0 cannot be applied with keyword arguments; missing 'dynamicCall(withKeywordArguments:)' method" - id: invalid_dynamic_member_lookup_type - msg: >- - @dynamicMemberLookup attribute requires %0 to have a - 'subscript(dynamicMember:)' method that accepts either - 'ExpressibleByStringLiteral' or a key path + msg: "@dynamicMemberLookup attribute requires %0 to have a 'subscript(dynamicMember:)' method that accepts either 'ExpressibleByStringLiteral' or a key path" - id: invalid_dynamic_member_subscript - msg: >- - add an explicit argument label to this subscript to satisfy the - @dynamicMemberLookup requirement + msg: "add an explicit argument label to this subscript to satisfy the @dynamicMemberLookup requirement" - id: string_index_not_integer - msg: >- - String must not be indexed with %0, it has variable size elements + msg: "String must not be indexed with %0, it has variable size elements" - id: string_index_not_integer_note - msg: >- - consider using an existing high level algorithm, - str.startIndex.advanced(by: n), or a projection like str.utf8 + msg: "consider using an existing high level algorithm, str.startIndex.advanced(by: n), or a projection like str.utf8" - id: invalid_c_function_pointer_conversion_expr - msg: >- - a C function pointer can only be formed from a reference to a 'func' or a - literal closure + msg: "a C function pointer can only be formed from a reference to a 'func' or a literal closure" - id: c_function_pointer_from_method - msg: >- - a C function pointer cannot be formed from a method + msg: "a C function pointer cannot be formed from a method" - id: c_function_pointer_from_generic_function - msg: >- - a C function pointer cannot be formed from a reference to a generic - function + msg: "a C function pointer cannot be formed from a reference to a generic function" - id: unsupported_linear_to_differentiable_conversion - msg: >- - conversion from '@differentiable(linear)' to '@differentiable' is not yet - supported + msg: "conversion from '@differentiable(linear)' to '@differentiable' is not yet supported" - id: invalid_autoclosure_forwarding - msg: >- - add () to forward @autoclosure parameter + msg: "add () to forward @autoclosure parameter" - id: invalid_differentiable_function_conversion_expr - msg: >- - a '@differentiable%select{|(linear)}0' function can only be formed from a - reference to a 'func' or 'init' or a literal closure + msg: "a '@differentiable%select{|(linear)}0' function can only be formed from a reference to a 'func' or 'init' or a literal closure" - id: invalid_differentiable_function_conversion_parameter - msg: >- - did you mean to take a '%0' closure? + msg: "did you mean to take a '%0' closure?" - id: invalid_autoclosure_pointer_conversion - msg: >- - cannot perform pointer conversion of value of type %0 to autoclosure - result type %1 + msg: "cannot perform pointer conversion of value of type %0 to autoclosure result type %1" - id: missing_initializer_def - msg: >- - initializer requires a body + msg: "initializer requires a body" - id: pound_warning - msg: >- - %0 + msg: "%0" - id: pound_error - msg: >- - %0 + msg: "%0" - id: operator_not_func - msg: >- - operators must be declared with 'func' + msg: "operators must be declared with 'func'" - id: redefining_builtin_operator - msg: >- - cannot declare a custom %0 '%1' operator + msg: "cannot declare a custom %0 '%1' operator" - id: attribute_requires_operator_identifier - msg: >- - '%0' requires a function with an operator identifier + msg: "'%0' requires a function with an operator identifier" - id: attribute_requires_single_argument - msg: >- - '%0' requires a function with one argument + msg: "'%0' requires a function with one argument" - id: nominal_type_not_attribute - msg: >- - %0 %1 cannot be used as an attribute + msg: "%0 %1 cannot be used as an attribute" - id: mutating_invalid_global_scope - msg: >- - %0 is only valid on methods + msg: "%0 is only valid on methods" - id: mutating_invalid_classes - msg: >- - %0 isn't valid on methods in classes or class-bound protocols + msg: "%0 is not valid on %1s in %select{classes|class-bound protocols}2" - id: functions_mutating_and_not - msg: >- - method must not be declared both %0 and %1 + msg: "method must not be declared both %0 and %1" - id: static_functions_not_mutating - msg: >- - static functions must not be declared mutating + msg: "static functions must not be declared mutating" - id: modify_mutatingness_differs_from_setter - msg: >- - 'modify' accessor cannot be %0 when the setter is %1 + msg: "'modify' accessor cannot be %0 when the setter is %1" - id: transparent_in_protocols_not_supported - msg: >- - '@_transparent' attribute is not supported on declarations within - protocols + msg: "'@_transparent' attribute is not supported on declarations within protocols" - id: transparent_in_classes_not_supported - msg: >- - '@_transparent' attribute is not supported on declarations within classes + msg: "'@_transparent' attribute is not supported on declarations within classes" - id: invalid_iboutlet - msg: >- - only instance properties can be declared @IBOutlet + msg: "only instance properties can be declared @IBOutlet" - id: iboutlet_nonobjc_class - msg: >- - @IBOutlet property cannot %select{have|be an array of}0 non-'@objc' class - type %1 + msg: "@IBOutlet property cannot %select{have|be an array of}0 non-'@objc' class type %1" - id: iboutlet_nonobjc_protocol - msg: >- - @IBOutlet property cannot %select{have|be an array of}0 non-'@objc' - protocol type %1 + msg: "@IBOutlet property cannot %select{have|be an array of}0 non-'@objc' protocol type %1" - id: iboutlet_nonobject_type - msg: >- - @IBOutlet property cannot %select{have|be an array of}0 non-object type %1 + msg: "@IBOutlet property cannot %select{have|be an array of}0 non-object type %1" - id: iboutlet_only_mutable - msg: >- - @IBOutlet attribute requires property to be mutable + msg: "@IBOutlet attribute requires property to be mutable" - id: iboutlet_non_optional - msg: >- - @IBOutlet property has non-optional type %0 + msg: "@IBOutlet property has non-optional type %0" - id: note_make_optional - msg: >- - add '?' to form the optional type %0 + msg: "add '?' to form the optional type %0" - id: note_make_implicitly_unwrapped_optional - msg: >- - add '!' to form an implicitly unwrapped optional + msg: "add '!' to form an implicitly unwrapped optional" - id: invalid_ibdesignable_extension - msg: >- - @IBDesignable can only be applied to classes and extensions of classes + msg: "@IBDesignable can only be applied to classes and extensions of classes" - id: invalid_ibinspectable - msg: >- - only instance properties can be declared @%0 + msg: "only instance properties can be declared @%0" - id: invalid_ibaction_decl - msg: >- - only instance methods can be declared @%0 + msg: "only instance methods can be declared @%0" - id: invalid_ibaction_result - msg: >- - methods declared @%0 must %select{|not }1return a value + msg: "methods declared @%0 must %select{|not }1return a value" - id: invalid_ibaction_argument_count - msg: >- - @%0 methods must have %1 to %2 arguments + msg: "@%0 methods must have %1 to %2 arguments" - id: invalid_ibaction_argument_count_exact - msg: >- - @%0 methods must have %2 argument%s2 + msg: "@%0 methods must have %2 argument%s2" - id: invalid_ibaction_argument_count_max - msg: >- - @%0 methods must have at most %2 argument%s2 + msg: "@%0 methods must have at most %2 argument%s2" - id: ibsegueaction_objc_method_family - msg: >- - @%0 method cannot have selector %1 because it has special memory - management behavior + msg: "@%0 method cannot have selector %1 because it has special memory management behavior" - id: fixit_rename_in_swift - msg: >- - change Swift name to %0 + msg: "change Swift name to %0" - id: fixit_rename_in_objc - msg: >- - change Objective-C selector to %0 + msg: "change Objective-C selector to %0" - id: no_objc_tagged_pointer_not_class_protocol - msg: >- - @unsafe_no_objc_tagged_pointer can only be applied to class protocols + msg: "@unsafe_no_objc_tagged_pointer can only be applied to class protocols" - id: swift_native_objc_runtime_base_not_on_root_class - msg: >- - @_swift_native_objc_runtime_base_not_on_root_class can only be applied to - root classes + msg: "@_swift_native_objc_runtime_base_not_on_root_class can only be applied to root classes" - id: cdecl_not_at_top_level - msg: >- - @_cdecl can only be applied to global functions + msg: "@_cdecl can only be applied to global functions" - id: cdecl_empty_name - msg: >- - @_cdecl symbol name cannot be empty + msg: "@_cdecl symbol name cannot be empty" - id: cdecl_throws - msg: >- - raising errors from @_cdecl functions is not supported + msg: "raising errors from @_cdecl functions is not supported" - id: attr_methods_only - msg: >- - only methods can be declared %0 + msg: "only methods can be declared %0" - id: access_control_in_protocol - msg: >- - %0 modifier cannot be used in protocols + msg: "%0 modifier cannot be used in protocols" - id: access_control_in_protocol_detail - msg: >- - protocol requirements implicitly have the same access as the protocol - itself + msg: "protocol requirements implicitly have the same access as the protocol itself" - id: access_control_setter - msg: >- - '%select{private|fileprivate|internal|public|open}0(set)' modifier can - only be applied to variables and subscripts + msg: "'%select{private|fileprivate|internal|public|open}0(set)' modifier can only be applied to variables and subscripts" - id: access_control_setter_read_only - msg: >- - '%select{private|fileprivate|internal|public|%error}0(set)' modifier - cannot be applied to %select{constants|read-only variables|read-only - properties|read-only subscripts}1 + msg: "'%select{private|fileprivate|internal|public|%error}0(set)' modifier cannot be applied to %select{constants|read-only variables|read-only properties|read-only subscripts}1" - id: access_control_setter_more - msg: >- - %select{private|fileprivate|internal|public|%error}0 - %select{variable|property|subscript}1 cannot have %select{%error|a - fileprivate|an internal|a public|an open}2 setter + msg: "%select{private|fileprivate|internal|public|%error}0 %select{variable|property|subscript}1 cannot have %select{%error|a fileprivate|an internal|a public|an open}2 setter" - id: access_control_setter_redundant - msg: >- - '%select{private|fileprivate|internal|public|open}0(set)' modifier is - redundant for - %select{a private|a fileprivate|an internal|a public|an open}2 %1 + msg: "'%select{private|fileprivate|internal|public|open}0(set)' modifier is redundant for %select{a private|a fileprivate|an internal|a public|an open}2 %1" - id: access_control_ext_member_more - msg: >- - '%select{%error|fileprivate|internal|public|open}0' modifier conflicts - with extension's default access of - '%select{private|fileprivate|internal|public|%error}1' + msg: "'%select{%error|fileprivate|internal|public|open}0' modifier conflicts with extension's default access of '%select{private|fileprivate|internal|public|%error}1'" - id: access_control_ext_member_redundant - msg: >- - '%select{%error|fileprivate|internal|public|%error}0' modifier is - redundant for %1 declared in %select{a private (equivalent to fileprivate)|a - fileprivate|an internal|a public|%error}2 extension + msg: "'%select{%error|fileprivate|internal|public|%error}0' modifier is redundant for %1 declared in %select{a private (equivalent to fileprivate)|a fileprivate|an internal|a public|%error}2 extension" - id: access_control_ext_requirement_member_more - msg: >- - cannot declare %select{%error|a fileprivate|an internal|a public|an - open}0 %1 in an extension with - %select{private|fileprivate|internal|public|%error}2 requirements + msg: "cannot declare %select{%error|a fileprivate|an internal|a public|an open}0 %1 in an extension with %select{private|fileprivate|internal|public|%error}2 requirements" - id: access_control_extension_more - msg: >- - extension of %select{private|fileprivate|internal|%error|%error}0 %1 - cannot be declared %select{%error|fileprivate|internal|public|%error}2 + msg: "extension of %select{private|fileprivate|internal|%error|%error}0 %1 cannot be declared %select{%error|fileprivate|internal|public|%error}2" - id: access_control_extension_open - msg: >- - extensions cannot use 'open' as their default access; use 'public' + msg: "extensions cannot use 'open' as their default access; use 'public'" - id: access_control_open_bad_decl - msg: >- - only classes and overridable class members can be declared 'open'; use - 'public' + msg: "only classes and overridable class members can be declared 'open'; use 'public'" - id: invalid_decl_attribute - msg: >- - '%0' attribute cannot be applied to this declaration + msg: "'%0' attribute cannot be applied to this declaration" - id: invalid_decl_modifier - msg: >- - %0 modifier cannot be applied to this declaration + msg: "%0 modifier cannot be applied to this declaration" - id: attribute_does_not_apply_to_type - msg: >- - attribute does not apply to type + msg: "attribute does not apply to type" - id: optional_attribute_non_protocol - msg: >- - 'optional' can only be applied to protocol members + msg: "'optional' can only be applied to protocol members" - id: optional_attribute_non_objc_protocol - msg: >- - 'optional' can only be applied to members of an @objc protocol + msg: "'optional' can only be applied to members of an @objc protocol" - id: optional_attribute_missing_explicit_objc - msg: >- - 'optional' requirements are an Objective-C compatibility feature; add - '@objc' + msg: "'optional' requirements are an Objective-C compatibility feature; add '@objc'" - id: objcmembers_attribute_nonclass - msg: >- - '@objcMembers' attribute can only be applied to a class + msg: "'@objcMembers' attribute can only be applied to a class" - id: optional_attribute_initializer - msg: >- - 'optional' cannot be applied to an initializer + msg: "'optional' cannot be applied to an initializer" - id: unavailable_method_non_objc_protocol - msg: >- - protocol members can only be marked unavailable in an @objc protocol + msg: "protocol members can only be marked unavailable in an @objc protocol" - id: missing_in_class_init_1 - msg: >- - stored property %0 requires an initial value%select{| or should be - @NSManaged}1 + msg: "stored property %0 requires an initial value%select{| or should be @NSManaged}1" - id: missing_in_class_init_2 - msg: >- - stored properties %0 and %1 require initial values%select{| or should be - @NSManaged}2 + msg: "stored properties %0 and %1 require initial values%select{| or should be @NSManaged}2" - id: missing_in_class_init_3plus - msg: >- - stored properties %0, %1, %select{and %2|%2, and others}3 require initial - values%select{| or should be @NSManaged}4 + msg: "stored properties %0, %1, %select{and %2|%2, and others}3 require initial values%select{| or should be @NSManaged}4" - id: requires_stored_property_inits_here - msg: >- - %select{superclass|class}1 %0 requires all stored properties to have - initial values%select{| or use @NSManaged}2 + msg: "%select{superclass|class}1 %0 requires all stored properties to have initial values%select{| or use @NSManaged}2" - id: class_without_init - msg: >- - class %0 has no initializers + msg: "class %0 has no initializers" - id: note_no_in_class_init_1 - msg: >- - stored property %0 without initial value prevents synthesized - initializers + msg: "stored property %0 without initial value prevents synthesized initializers" - id: note_no_in_class_init_2 - msg: >- - stored properties %0 and %1 without initial values prevent synthesized - initializers + msg: "stored properties %0 and %1 without initial values prevent synthesized initializers" - id: note_no_in_class_init_3plus - msg: >- - stored properties %0, %1, %select{and %2|%2, and others}3 without initial - values prevent synthesized initializers + msg: "stored properties %0, %1, %select{and %2|%2, and others}3 without initial values prevent synthesized initializers" - id: missing_unimplemented_init_runtime - msg: >- - standard library error: missing _unimplementedInitializer + msg: "standard library error: missing _unimplementedInitializer" - id: missing_undefined_runtime - msg: >- - standard library error: missing _undefined + msg: "standard library error: missing _undefined" - id: expr_dynamic_lookup_swift3_objc_inference - msg: >- - reference to %0 %1 of %2 depends on '@objc' inference deprecated in Swift 4 + msg: "reference to %0 %1 of %2 depends on '@objc' inference deprecated in Swift 4" - id: inherited_default_value_not_in_designated_constructor - msg: >- - default value inheritance via 'super' is only valid on the parameters of - designated initializers + msg: "default value inheritance via 'super' is only valid on the parameters of designated initializers" - id: inherited_default_value_used_in_non_overriding_constructor - msg: >- - default value inheritance via 'super' can only be used when overriding a - designated initializer + msg: "default value inheritance via 'super' can only be used when overriding a designated initializer" - id: corresponding_param_not_defaulted - msg: >- - default value inheritance via 'super' requires that the corresponding - parameter of the overridden designated initializer has a default value + msg: "default value inheritance via 'super' requires that the corresponding parameter of the overridden designated initializer has a default value" - id: inherited_default_param_here - msg: >- - corresponding parameter declared here + msg: "corresponding parameter declared here" - id: option_set_zero_constant - msg: >- - static property %0 produces an empty option set + msg: "static property %0 produces an empty option set" - id: option_set_empty_set_init - msg: >- - use [] to silence this warning + msg: "use [] to silence this warning" - id: originally_defined_in_dupe_platform - msg: >- - duplicate version number for platform %0 + msg: "duplicate version number for platform %0" - id: originally_definedin_topleve_decl - msg: >- - @%0 is only applicable to top-level decl + msg: "@%0 is only applicable to top-level decl" - id: originally_definedin_need_available - msg: >- - need @available attribute for @%0 + msg: "need @available attribute for @%0" - id: originally_definedin_must_after_available_version - msg: >- - moved version from @%0 must after introduced OS version + msg: "moved version from @%0 must after introduced OS version" - id: alignment_not_power_of_two - msg: >- - alignment value must be a power of two + msg: "alignment value must be a power of two" - id: indirect_case_without_payload - msg: >- - enum case %0 without associated value cannot be 'indirect' + msg: "enum case %0 without associated value cannot be 'indirect'" - id: indirect_case_in_indirect_enum - msg: >- - enum case in 'indirect' enum cannot also be 'indirect' + msg: "enum case in 'indirect' enum cannot also be 'indirect'" - id: enum_frozen_nonpublic - msg: >- - %0 has no effect on non-public enums + msg: "%0 has no effect on non-public enums" - id: getset_init - msg: >- - variable with getter/setter cannot have an initial value + msg: "variable with getter/setter cannot have an initial value" - id: unimplemented_static_var - msg: >- - %select{ERROR|static|class}1 stored properties not supported%select{ in - this context| in generic types| in classes| - in protocol extensions}0%select{|; did you mean 'static'?}2 + msg: "%select{ERROR|static|class}1 stored properties not supported%select{ in this context| in generic types| in classes| in protocol extensions}0%select{|; did you mean 'static'?}2" - id: observingprop_requires_initializer - msg: >- - non-member observing properties require an initializer + msg: "non-member observing properties require an initializer" - id: global_requires_initializer - msg: >- - global '%select{var|let}0' declaration requires an initializer - expression%select{ or getter/setter specifier|}0 + msg: "global '%select{var|let}0' declaration requires an initializer expression%select{ or getter/setter specifier|}0" - id: static_requires_initializer - msg: >- - %select{ERROR|'static var'|'class var'|}0 declaration requires an - initializer expression or getter/setter specifier + msg: "%select{ERROR|'static var'|'class var'|}0 declaration requires an initializer expression or getter/setter specifier" - id: pattern_type_access - msg: >- - %select{%select{variable|constant}0|property}1 %select{must be declared - %select{%select{private|fileprivate|internal|%error|%error}3|private or - fileprivate}4|cannot be declared %select{in this - context|fileprivate|internal|public|open}3}2 because its type uses %select{a - private|a fileprivate|an internal|%error|%error}5 type + msg: "%select{%select{variable|constant}0|property}1 %select{must be declared %select{%select{private|fileprivate|internal|%error|%error}3|private or fileprivate}4|cannot be declared %select{in this context|fileprivate|internal|public|open}3}2 because its type uses %select{a private|a fileprivate|an internal|%error|%error}5 type" - id: pattern_type_access_warn - msg: >- - %select{%select{variable|constant}0|property}1 %select{should be declared - %select{private|fileprivate|internal|%error|%error}5|should not be declared - %select{in this context|fileprivate|internal|public|open}3}2 because its - type uses %select{a private|a fileprivate|an internal|%error|%error}5 type + msg: "%select{%select{variable|constant}0|property}1 %select{should be declared %select{private|fileprivate|internal|%error|%error}5|should not be declared %select{in this context|fileprivate|internal|public|open}3}2 because its type uses %select{a private|a fileprivate|an internal|%error|%error}5 type" - id: pattern_type_access_inferred - msg: >- - %select{%select{variable|constant}0|property}1 %select{must be declared - %select{%select{private|fileprivate|internal|%error|%error}3|private or - fileprivate}4|cannot be declared %select{in this - context|fileprivate|internal|public|open}3}2 because its type %6 - uses %select{a private|a fileprivate|an internal|%error|%error}5 type + msg: "%select{%select{variable|constant}0|property}1 %select{must be declared %select{%select{private|fileprivate|internal|%error|%error}3|private or fileprivate}4|cannot be declared %select{in this context|fileprivate|internal|public|open}3}2 because its type %6 uses %select{a private|a fileprivate|an internal|%error|%error}5 type" - id: pattern_type_access_inferred_warn - msg: >- - %select{%select{variable|constant}0|property}1 %select{should be declared - %select{private|fileprivate|internal|%error|%error}5|should not be declared - %select{in this context|fileprivate|internal|public|open}3}2 because its - type %6 uses - %select{a private|a fileprivate|an internal|%error|%error}5 type + msg: "%select{%select{variable|constant}0|property}1 %select{should be declared %select{private|fileprivate|internal|%error|%error}5|should not be declared %select{in this context|fileprivate|internal|public|open}3}2 because its type %6 uses %select{a private|a fileprivate|an internal|%error|%error}5 type" - id: pattern_type_not_usable_from_inline - msg: >- - type referenced from a '@usableFromInline' - %select{%select{variable|constant}0|property}1 must be '@usableFromInline' - or public + msg: "type referenced from a '@usableFromInline' %select{%select{variable|constant}0|property}1 must be '@usableFromInline' or public" - id: pattern_type_not_usable_from_inline_warn - msg: >- - type referenced from a '@usableFromInline' - %select{%select{variable|constant}0|property}1 should be '@usableFromInline' - or public + msg: "type referenced from a '@usableFromInline' %select{%select{variable|constant}0|property}1 should be '@usableFromInline' or public" - id: pattern_type_not_usable_from_inline_frozen - msg: >- - type referenced from a stored property in a '@frozen' struct must be - '@usableFromInline' or public + msg: "type referenced from a stored property in a '@frozen' struct must be '@usableFromInline' or public" - id: pattern_type_not_usable_from_inline_inferred - msg: >- - type referenced from a '@usableFromInline' - %select{%select{variable|constant}0|property}1 with inferred type %2 must be - '@usableFromInline' or public + msg: "type referenced from a '@usableFromInline' %select{%select{variable|constant}0|property}1 with inferred type %2 must be '@usableFromInline' or public" - id: pattern_type_not_usable_from_inline_inferred_warn - msg: >- - type referenced from a '@usableFromInline' - %select{%select{variable|constant}0|property}1 with inferred type %2 should - be '@usableFromInline' or public + msg: "type referenced from a '@usableFromInline' %select{%select{variable|constant}0|property}1 with inferred type %2 should be '@usableFromInline' or public" - id: pattern_type_not_usable_from_inline_inferred_frozen - msg: >- - type referenced from a stored property with inferred type %2 in a - '@frozen' struct must be '@usableFromInline' or public + msg: "type referenced from a stored property with inferred type %2 in a '@frozen' struct must be '@usableFromInline' or public" - id: pattern_binds_no_variables - msg: >- - %select{property|global variable}0 declaration does not bind any - variables + msg: "%select{property|global variable}0 declaration does not bind any variables" - id: variable_bound_by_no_pattern - msg: >- - variable %0 is not bound by any pattern + msg: "variable %0 is not bound by any pattern" - id: optional_ambiguous_case_ref - msg: >- - assuming you mean '%0.%2'; did you mean '%1.%2' instead? + msg: "assuming you mean '%0.%2'; did you mean '%1.%2' instead?" - id: optional_fixit_ambiguous_case_ref - msg: >- - explicitly specify 'Optional' to silence this warning + msg: "explicitly specify 'Optional' to silence this warning" - id: optional_fixit_ambiguous_case_ref_switch - msg: >- - use 'nil' to silence this warning + msg: "use 'nil' to silence this warning" - id: type_fixit_optional_ambiguous_case_ref - msg: >- - use '%0.%1' instead + msg: "use '%0.%1' instead" - id: type_fixit_optional_ambiguous_case_ref_switch - msg: >- - use '%0' instead + msg: "use '%0' instead" - id: nscoding_unstable_mangled_name - msg: >- - %select{private|fileprivate|nested|local}0 class %1 has an unstable name - when archiving via 'NSCoding' + msg: "%select{private|fileprivate|nested|local}0 class %1 has an unstable name when archiving via 'NSCoding'" - id: unstable_mangled_name_add_objc_new - msg: >- - for new classes, use '@objc' to specify a unique, prefixed Objective-C - runtime name + msg: "for new classes, use '@objc' to specify a unique, prefixed Objective-C runtime name" - id: unstable_mangled_name_add_objc - msg: >- - for compatibility with existing archives, use '@objc' to record the Swift - 3 runtime name + msg: "for compatibility with existing archives, use '@objc' to record the Swift 3 runtime name" - id: unsupported_type_nested_in_generic_function - msg: >- - type %0 cannot be nested in generic function %1 + msg: "type %0 cannot be nested in generic function %1" - id: unsupported_type_nested_in_generic_closure - msg: >- - type %0 cannot be nested in closure in generic context + msg: "type %0 cannot be nested in closure in generic context" - id: unsupported_type_nested_in_protocol - msg: >- - type %0 cannot be nested in protocol %1 + msg: "type %0 cannot be nested in protocol %1" - id: unsupported_type_nested_in_protocol_extension - msg: >- - type %0 cannot be nested in protocol extension of %1 + msg: "type %0 cannot be nested in protocol extension of %1" - id: unsupported_nested_protocol - msg: >- - protocol %0 cannot be nested inside another declaration + msg: "protocol %0 cannot be nested inside another declaration" - id: where_nongeneric_ctx - msg: >- - 'where' clause on non-generic member declaration requires a generic - context + msg: "'where' clause on non-generic member declaration requires a generic context" - id: where_nongeneric_toplevel - msg: >- - 'where' clause cannot be applied to a non-generic top-level declaration + msg: "'where' clause cannot be applied to a non-generic top-level declaration" - id: type_alias_underlying_type_access - msg: >- - type alias %select{must be declared - %select{%select{private|fileprivate|internal|%error|%error}1|private or - fileprivate}3|cannot be declared %select{in this - context|fileprivate|internal|public|open}1}0 because its underlying type - uses %select{a private|a fileprivate|an internal|%error|%error}2 type + msg: "type alias %select{must be declared %select{%select{private|fileprivate|internal|%error|%error}1|private or fileprivate}3|cannot be declared %select{in this context|fileprivate|internal|public|open}1}0 because its underlying type uses %select{a private|a fileprivate|an internal|%error|%error}2 type" - id: type_alias_underlying_type_access_warn - msg: >- - type alias %select{should be declared - %select{private|fileprivate|internal|%error|%error}1|should not be declared - %select{in this context|fileprivate|internal|public|open}1}0 because its - underlying type uses - %select{a private|a fileprivate|an internal|%error|%error}2 type + msg: "type alias %select{should be declared %select{private|fileprivate|internal|%error|%error}1|should not be declared %select{in this context|fileprivate|internal|public|open}1}0 because its underlying type uses %select{a private|a fileprivate|an internal|%error|%error}2 type" - id: type_alias_underlying_type_not_usable_from_inline - msg: >- - type referenced from the underlying type of a '@usableFromInline' type - alias must be '@usableFromInline' or public + msg: "type referenced from the underlying type of a '@usableFromInline' type alias must be '@usableFromInline' or public" - id: type_alias_underlying_type_not_usable_from_inline_warn - msg: >- - type referenced from the underlying type of a '@usableFromInline' type - alias should be '@usableFromInline' or public + msg: "type referenced from the underlying type of a '@usableFromInline' type alias should be '@usableFromInline' or public" - id: subscript_type_access - msg: >- - subscript %select{must be declared - %select{private|fileprivate|internal|%error|%error}1|cannot be declared - %select{in this context|fileprivate|internal|public|open}1}0 because its - %select{index|element type}3 uses %select{a private|a fileprivate|an - internal|%error|%error}2 type + msg: "subscript %select{must be declared %select{private|fileprivate|internal|%error|%error}1|cannot be declared %select{in this context|fileprivate|internal|public|open}1}0 because its %select{index|element type}3 uses %select{a private|a fileprivate|an internal|%error|%error}2 type" - id: subscript_type_access_warn - msg: >- - subscript %select{should be declared - %select{private|fileprivate|internal|%error|%error}1|should not be declared - %select{in this context|fileprivate|internal|public|open}1}0 because its - %select{index|element type}3 uses %select{a private|a fileprivate|an - internal|%error|%error}2 type + msg: "subscript %select{should be declared %select{private|fileprivate|internal|%error|%error}1|should not be declared %select{in this context|fileprivate|internal|public|open}1}0 because its %select{index|element type}3 uses %select{a private|a fileprivate|an internal|%error|%error}2 type" - id: subscript_type_usable_from_inline - msg: >- - %select{index type|element type}0 of a '@usableFromInline' subscript must - be '@usableFromInline' or public + msg: "%select{index type|element type}0 of a '@usableFromInline' subscript must be '@usableFromInline' or public" - id: subscript_type_usable_from_inline_warn - msg: >- - %select{index type|element type}0 of a '@usableFromInline' subscript - should be '@usableFromInline' or public + msg: "%select{index type|element type}0 of a '@usableFromInline' subscript should be '@usableFromInline' or public" - id: function_type_access - msg: >- - %select{function|method|initializer}4 %select{must be declared - %select{%select{private|fileprivate|internal|%error|%error}1|private or - fileprivate}2|cannot be declared %select{in this - context|fileprivate|internal|public|open}1}0 because its - %select{parameter|result}5 uses %select{a private|a fileprivate|an internal|an - '@_spi'|an '@_spi'}3 type + msg: "%select{function|method|initializer}4 %select{must be declared %select{%select{private|fileprivate|internal|%error|%error}1|private or fileprivate}2|cannot be declared %select{in this context|fileprivate|internal|public|open}1}0 because its %select{parameter|result}5 uses %select{a private|a fileprivate|an internal|an '@_spi'|an '@_spi'}3 type" - id: function_type_spi - msg: >- - %select{function|method|initializer}0 cannot be declared '@_spi' because - its %select{parameter|result}1 uses %select{a private|a fileprivate|an - internal|a public|an open}2 type%select{| that is not '@_spi'}3 + msg: "%select{function|method|initializer}0 cannot be declared '@_spi' because its %select{parameter|result}1 uses %select{a private|a fileprivate|an internal|a public|an open}2 type%select{| that is not '@_spi'}3" - id: function_type_access_warn - msg: >- - %select{function|method|initializer}4 %select{should be declared - %select{private|fileprivate|internal|%error|%error}1|should not be declared - %select{in this context|fileprivate|internal|public|open}1}0 because its - %select{parameter|result}5 uses %select{a private|a fileprivate|an - internal|%error|%error}3 type + msg: "%select{function|method|initializer}4 %select{should be declared %select{private|fileprivate|internal|%error|%error}1|should not be declared %select{in this context|fileprivate|internal|public|open}1}0 because its %select{parameter|result}5 uses %select{a private|a fileprivate|an internal|%error|%error}3 type" - id: function_type_usable_from_inline - msg: >- - the %select{parameter|result}1 of a '@usableFromInline' - %select{function|method|initializer}0 must be '@usableFromInline' or public + msg: "the %select{parameter|result}1 of a '@usableFromInline' %select{function|method|initializer}0 must be '@usableFromInline' or public" - id: function_type_usable_from_inline_warn - msg: >- - the %select{parameter|result}1 of a '@usableFromInline' - %select{function|method|initializer}0 should be '@usableFromInline' - or public + msg: "the %select{parameter|result}1 of a '@usableFromInline' %select{function|method|initializer}0 should be '@usableFromInline' or public" - id: spi_attribute_on_non_public - msg: >- - %select{private|fileprivate|internal|%error|%error}0 %1 cannot be - declared '@_spi' because only public and open declarations can be '@_spi' + msg: "%select{private|fileprivate|internal|%error|%error}0 %1 cannot be declared '@_spi' because only public and open declarations can be '@_spi'" - id: spi_attribute_on_protocol_requirement - msg: >- - protocol requirement %0 cannot be declared '@_spi' without a default - implementation in a protocol extension + msg: "protocol requirement %0 cannot be declared '@_spi' without a default implementation in a protocol extension" - id: spi_attribute_on_frozen_stored_properties - msg: >- - stored property %0 cannot be declared '@_spi' in a '@frozen' struct + msg: "stored property %0 cannot be declared '@_spi' in a '@frozen' struct" - id: opaque_type_invalid_constraint - msg: >- - an 'opaque' type must specify only 'Any', 'AnyObject', protocols, and/or - a base class + msg: "an 'opaque' type must specify only 'Any', 'AnyObject', protocols, and/or a base class" - id: inferred_opaque_type - msg: >- - property definition has inferred type %0, involving the 'some' return - type of another declaration + msg: "property definition has inferred type %0, involving the 'some' return type of another declaration" - id: non_nominal_extension - msg: >- - non-nominal type %0 cannot be extended + msg: "non-nominal type %0 cannot be extended" - id: composition_in_extended_type - msg: >- - extending a protocol composition is not supported; extending %0 instead + msg: "extending a protocol composition is not supported; extending %0 instead" - id: composition_in_extended_type_alternative - msg: >- - did you mean to extend the most specific type %0 instead? + msg: "did you mean to extend the most specific type %0 instead?" - id: extension_access_with_conformances - msg: >- - %0 modifier cannot be used with extensions that declare protocol - conformances + msg: "%0 modifier cannot be used with extensions that declare protocol conformances" - id: extension_metatype - msg: >- - cannot extend a metatype %0 + msg: "cannot extend a metatype %0" - id: extension_specialization - msg: >- - constrained extension must be declared on the unspecialized generic type - %0 with constraints specified by a 'where' clause + msg: "constrained extension must be declared on the unspecialized generic type %0 with constraints specified by a 'where' clause" - id: extension_stored_property - msg: >- - extensions must not contain stored properties + msg: "extensions must not contain stored properties" - id: extension_stored_property_fixit - msg: >- - Remove '=' to make %0 a computed property + msg: "Remove '=' to make %0 a computed property" - id: extension_nongeneric_trailing_where - msg: >- - trailing 'where' clause for extension of non-generic type %0 + msg: "trailing 'where' clause for extension of non-generic type %0" - id: extension_protocol_inheritance - msg: >- - extension of protocol %0 cannot have an inheritance clause + msg: "extension of protocol %0 cannot have an inheritance clause" - id: objc_generic_extension_using_type_parameter - msg: >- - extension of a generic Objective-C class cannot access the class's - generic parameters at runtime + msg: "extension of a generic Objective-C class cannot access the class's generic parameters at runtime" - id: objc_generic_extension_using_type_parameter_here - msg: >- - generic parameter used here + msg: "generic parameter used here" - id: objc_generic_extension_using_type_parameter_try_objc - msg: >- - add '@objc' to allow uses of 'self' within the function body + msg: "add '@objc' to allow uses of 'self' within the function body" - id: invalid_nominal_extension - msg: >- - extension of type %0 must be declared as an extension of %1 + msg: "extension of type %0 must be declared as an extension of %1" - id: invalid_nominal_extension_rewrite - msg: >- - did you mean to extend %0 instead? + msg: "did you mean to extend %0 instead?" - id: type_does_not_conform - msg: >- - type %0 does not conform to protocol %1 + msg: "type %0 does not conform to protocol %1" - id: cannot_use_nil_with_this_type - msg: >- - 'nil' cannot be used in context expecting type %0 + msg: "'nil' cannot be used in context expecting type %0" - id: type_cannot_conform_to_nsobject - msg: >- - cannot declare conformance to 'NSObjectProtocol' in Swift; %0 should - inherit 'NSObject' instead + msg: "cannot declare conformance to 'NSObjectProtocol' in Swift; %0 should inherit 'NSObject' instead" - id: use_of_equal_instead_of_equality - msg: >- - use of '=' in a boolean context, did you mean '=='? + msg: "use of '=' in a boolean context, did you mean '=='?" - id: type_cannot_conform - msg: >- - %select{type %1|protocol %1 as a type}0 cannot conform to - %select{%3|the protocol itself}2; - only concrete types such as structs, enums and classes - can conform to protocols + msg: "%select{type %1|protocol %1 as a type}0 cannot conform to %select{%3|the protocol itself}2; only concrete types such as structs, enums and classes can conform to protocols" - id: required_by_opaque_return - msg: >- - required by opaque return type of %0 %1 + msg: "required by opaque return type of %0 %1" - id: required_by_decl - msg: >- - required by %0 %1 where %2 = %3 + msg: "required by %0 %1 where %2 = %3" - id: required_by_decl_ref - msg: >- - required by referencing %0 %1 on %2 where %3 = %4 + msg: "required by referencing %0 %1 on %2 where %3 = %4" - id: protocol_does_not_conform_static - msg: >- - %0 cannot be used as a type conforming to protocol %1 because %1 has - static requirements + msg: "%0 cannot be used as a type conforming to protocol %1 because %1 has static requirements" - id: protocol_derivation_is_broken - msg: >- - protocol %0 is broken; cannot derive conformance for type %1 + msg: "protocol %0 is broken; cannot derive conformance for type %1" - id: type_does_not_inherit - msg: >- - %0 requires that %1 inherit from %2 + msg: "%0 requires that %1 inherit from %2" - id: type_does_not_inherit_or_conform_requirement - msg: >- - requirement specified as %0 : %1%2 + msg: "requirement specified as %0 : %1%2" - id: types_not_equal - msg: >- - %0 requires the types %1 and %2 be equivalent + msg: "%0 requires the types %1 and %2 be equivalent" - id: type_does_not_conform_owner - msg: >- - %0 requires that %1 conform to %2 + msg: "%0 requires that %1 conform to %2" - id: type_does_not_conform_in_decl_ref - msg: >- - referencing %0 %1 on %2 requires that %3 conform to %4 + msg: "referencing %0 %1 on %2 requires that %3 conform to %4" - id: type_does_not_conform_anyobject_in_decl_ref - msg: >- - referencing %0 %1 on %2 requires that %3 be a class type + msg: "referencing %0 %1 on %2 requires that %3 be a class type" - id: type_does_not_conform_decl_owner - msg: >- - %0 %1 requires that %2 conform to %3 + msg: "%0 %1 requires that %2 conform to %3" - id: type_does_not_conform_anyobject_decl_owner - msg: >- - %0 %1 requires that %2 be a class type + msg: "%0 %1 requires that %2 be a class type" - id: type_does_not_conform_in_opaque_return - msg: >- - return type of %0 %1 requires that %2 - %select{conform to %3|be a class type}4 + msg: "return type of %0 %1 requires that %2 %select{conform to %3|be a class type}4" - id: types_not_equal_decl - msg: >- - %0 %1 requires the types %2 and %3 be equivalent + msg: "%0 %1 requires the types %2 and %3 be equivalent" - id: types_not_equal_in_decl_ref - msg: >- - referencing %0 %1 on %2 requires the types %3 and %4 be equivalent + msg: "referencing %0 %1 on %2 requires the types %3 and %4 be equivalent" - id: types_not_inherited_decl - msg: >- - %0 %1 requires that %2 inherit from %3 + msg: "%0 %1 requires that %2 inherit from %3" - id: types_not_inherited_in_decl_ref - msg: >- - referencing %0 %1 on %2 requires that %3 inherit from %4 + msg: "referencing %0 %1 on %2 requires that %3 inherit from %4" - id: where_requirement_failure_one_subst - msg: >- - where %0 = %1 + msg: "where %0 = %1" - id: where_requirement_failure_both_subst - msg: >- - where %0 = %1, %2 = %3 + msg: "where %0 = %1, %2 = %3" - id: requirement_implied_by_conditional_conformance - msg: >- - requirement from conditional conformance of %0 to %1 + msg: "requirement from conditional conformance of %0 to %1" - id: wrapped_type_satisfies_requirement - msg: >- - wrapped type %0 satisfies this requirement; did you mean to unwrap? + msg: "wrapped type %0 satisfies this requirement; did you mean to unwrap?" - id: candidate_types_conformance_requirement - msg: >- - candidate requires that %0 conform to %1 - (requirement specified as %2 == %3%4) + msg: "candidate requires that %0 conform to %1 (requirement specified as %2 == %3%4)" - id: candidate_types_equal_requirement - msg: >- - candidate requires that the types %0 and %1 be equivalent (requirement - specified as %2 == %3%4) + msg: "candidate requires that the types %0 and %1 be equivalent (requirement specified as %2 == %3%4)" - id: candidate_types_inheritance_requirement - msg: >- - candidate requires that %1 inherit from %2 - (requirement specified as %2 : %3%4) + msg: "candidate requires that %1 inherit from %2 (requirement specified as %2 : %3%4)" - id: types_not_equal_requirement - msg: >- - requirement specified as %0 == %1%2 + msg: "requirement specified as %0 == %1%2" - id: type_is_not_a_class - msg: >- - %0 requires that %1 be a class type + msg: "%0 requires that %1 be a class type" - id: anyobject_requirement - msg: >- - requirement specified as %0 : 'AnyObject'%2 + msg: "requirement specified as %0 : 'AnyObject'%2" - id: non_class_cannot_conform_to_class_protocol - msg: >- - non-class type %0 cannot conform to class protocol %1 + msg: "non-class type %0 cannot conform to class protocol %1" - id: cf_class_cannot_conform_to_objc_protocol - msg: >- - Core Foundation class %0 cannot conform to @objc protocol %1 because Core - Foundation types are not classes in Objective-C + msg: "Core Foundation class %0 cannot conform to @objc protocol %1 because Core Foundation types are not classes in Objective-C" - id: objc_runtime_visible_cannot_conform_to_objc_protocol - msg: >- - class %0 cannot conform to @objc protocol %1 because the class is only - visible via the Objective-C runtime + msg: "class %0 cannot conform to @objc protocol %1 because the class is only visible via the Objective-C runtime" - id: objc_generics_cannot_conditionally_conform - msg: >- - type %0 cannot conditionally conform to protocol %1 because the type uses - the Objective-C generics model + msg: "type %0 cannot conditionally conform to protocol %1 because the type uses the Objective-C generics model" - id: objc_protocol_cannot_have_conditional_conformance - msg: >- - type %0 cannot conditionally conform to @objc protocol %1 because - Objective-C does not support conditional conformances + msg: "type %0 cannot conditionally conform to @objc protocol %1 because Objective-C does not support conditional conformances" - id: objc_protocol_in_generic_extension - msg: >- - conformance of %select{class from generic context|generic class}0 %1 to - @objc protocol %2 cannot be in an extension + msg: "conformance of %select{class from generic context|generic class}0 %1 to @objc protocol %2 cannot be in an extension" - id: conditional_conformances_cannot_imply_conformances - msg: >- - conditional conformance of type %0 to protocol %1 does not imply - conformance to inherited protocol %2 + msg: "conditional conformance of type %0 to protocol %1 does not imply conformance to inherited protocol %2" - id: note_explicitly_state_conditional_conformance_different - msg: >- - did you mean to explicitly state the conformance with different bounds? + msg: "did you mean to explicitly state the conformance with different bounds?" - id: note_explicitly_state_conditional_conformance_relaxed - msg: >- - did you mean to explicitly state the conformance with relaxed bounds? + msg: "did you mean to explicitly state the conformance with relaxed bounds?" - id: note_explicitly_state_conditional_conformance_same - msg: >- - did you mean to explicitly state the conformance with the same bounds? + msg: "did you mean to explicitly state the conformance with the same bounds?" - id: note_explicitly_state_conditional_conformance_noneditor - msg: >- - did you mean to explicitly state the conformance like '%0where ...'? + msg: "did you mean to explicitly state the conformance like '%0where ...'?" - id: protocol_has_missing_requirements - msg: >- - type %0 cannot conform to protocol %1 because it has requirements that - cannot be satisfied + msg: "type %0 cannot conform to protocol %1 because it has requirements that cannot be satisfied" - id: protocol_has_missing_requirements_versioned - msg: >- - type %0 cannot conform to protocol %1 (compiled with Swift %2) because it - has requirements that could not be loaded in Swift %3 + msg: "type %0 cannot conform to protocol %1 (compiled with Swift %2) because it has requirements that could not be loaded in Swift %3" - id: requirement_restricts_self - msg: >- - %0 requirement %1 cannot add constraint '%2%select{:|:| ==|:}3 %4' on 'Self' + msg: "%0 requirement %1 cannot add constraint '%2%select{:|:| ==|:}3 %4' on 'Self'" - id: witness_argument_name_mismatch - msg: >- - %0 %1 has different argument labels from those required by protocol %2 (%3) + msg: "%0 %1 has different argument labels from those required by protocol %2 (%3)" - id: witness_initializer_not_required - msg: >- - initializer requirement %0 can only be satisfied by a 'required' - initializer in%select{| the definition of}1 non-final class %2 + msg: "initializer requirement %0 can only be satisfied by a 'required' initializer in%select{| the definition of}1 non-final class %2" - id: witness_initializer_failability - msg: >- - non-failable initializer requirement %0%select{| in Objective-C - protocol}1 cannot be satisfied by a - failable initializer ('init%select{?|!}1') + msg: "non-failable initializer requirement %0%select{| in Objective-C protocol}1 cannot be satisfied by a failable initializer ('init%select{?|!}1')" - id: witness_self_non_subtype - msg: >- - protocol %0 requirement %1 cannot be satisfied by a non-final class (%2) - because it uses 'Self' in a non-parameter, non-result type position + msg: "protocol %0 requirement %1 cannot be satisfied by a non-final class (%2) because it uses 'Self' in a non-parameter, non-result type position" - id: witness_self_same_type - msg: >- - %0 %1 in non-final class %2 cannot be used to satisfy requirement %3 %4 - (in protocol %5) due to same-type requirement involving 'Self' + msg: "%0 %1 in non-final class %2 cannot be used to satisfy requirement %3 %4 (in protocol %5) due to same-type requirement involving 'Self'" - id: witness_self_weaken_same_type - msg: >- - consider weakening the same-type requirement %0 == %1 to a superclass - requirement + msg: "consider weakening the same-type requirement %0 == %1 to a superclass requirement" - id: witness_requires_dynamic_self - msg: >- - method %0 in non-final class %1 must return 'Self' to conform to protocol %2 + msg: "method %0 in non-final class %1 must return 'Self' to conform to protocol %2" - id: witness_requires_class_implementation - msg: >- - method %0 in non-final class %1 cannot be implemented in a protocol - extension because it returns 'Self' and has associated type requirements + msg: "method %0 in non-final class %1 cannot be implemented in a protocol extension because it returns 'Self' and has associated type requirements" - id: witness_not_accessible_proto - msg: >- - %select{initializer %1|method %1|%select{|setter for }2property - %1|subscript%select{| setter}2}0 must be declared - %select{%error|fileprivate|internal|public|%error}3 because it matches a - requirement in %select{private|fileprivate|internal|public|%error}4 - protocol %5 + msg: "%select{initializer %1|method %1|%select{|setter for }2property %1|subscript%select{| setter}2}0 must be declared %select{%error|fileprivate|internal|public|%error}3 because it matches a requirement in %select{private|fileprivate|internal|public|%error}4 protocol %5" - id: witness_not_accessible_type - msg: >- - %select{initializer %1|method %1|%select{|setter for }2property - %1|subscript%select{| setter}2}0 must be as accessible as its enclosing type - because it matches a requirement in protocol %5 + msg: "%select{initializer %1|method %1|%select{|setter for }2property %1|subscript%select{| setter}2}0 must be as accessible as its enclosing type because it matches a requirement in protocol %5" - id: type_witness_not_accessible_proto - msg: >- - %0 %1 must be declared - %select{%error|fileprivate|internal|public|%error}2 because it matches a - requirement in %select{%error|fileprivate|internal|public|%error}2 - protocol %3 + msg: "%0 %1 must be declared %select{%error|fileprivate|internal|public|%error}2 because it matches a requirement in %select{%error|fileprivate|internal|public|%error}2 protocol %3" - id: type_witness_not_accessible_type - msg: >- - %0 %1 must be as accessible as its enclosing type because it matches a - requirement in protocol %3 + msg: "%0 %1 must be as accessible as its enclosing type because it matches a requirement in protocol %3" - id: witness_not_usable_from_inline - msg: >- - %0 %1 must be declared '@usableFromInline' because it matches a - requirement in protocol %2 + msg: "%0 %1 must be declared '@usableFromInline' because it matches a requirement in protocol %2" - id: witness_not_usable_from_inline_warn - msg: >- - %0 %1 should be declared '@usableFromInline' because it matches a - requirement in protocol %2 + msg: "%0 %1 should be declared '@usableFromInline' because it matches a requirement in protocol %2" - id: type_witness_objc_generic_parameter - msg: >- - type %0 involving Objective-C type parameter%select{| %1}2 cannot be used - for associated type %3 of protocol %4 + msg: "type %0 involving Objective-C type parameter%select{| %1}2 cannot be used for associated type %3 of protocol %4" - id: witness_fix_access - msg: >- - mark the %0 as '%select{%error|fileprivate|internal|public|%error}1' to - satisfy the requirement + msg: "mark the %0 as '%select{%error|fileprivate|internal|public|%error}1' to satisfy the requirement" - id: witness_move_to_another_extension - msg: >- - move the %0 to another extension where it can be declared - '%select{%error|%error|internal|public|%error}1' to satisfy the requirement + msg: "move the %0 to another extension where it can be declared '%select{%error|%error|internal|public|%error}1' to satisfy the requirement" - id: assoc_type_default_conformance_failed - msg: >- - default type %0 for associated type %1 does not satisfy constraint %2: %3 + msg: "default type %0 for associated type %1 does not satisfy constraint %2: %3" - id: assoc_type_default_here - msg: >- - associated type %0 has default type %1 written here + msg: "associated type %0 has default type %1 written here" - id: protocol_access - msg: >- - %select{protocol must be declared - %select{%select{private|fileprivate|internal|%error|%error}1|private or - fileprivate}4 because - %select{it refines|its 'where' clause uses}2|%select{in - this context|fileprivate|internal|public|%error}1 %select{protocol cannot - refine|protocol's 'where' clause cannot use}2}0 %select{a private|a - fileprivate|an internal|%error|%error}3 %5 + msg: "%select{protocol must be declared %select{%select{private|fileprivate|internal|%error|%error}1|private or fileprivate}4 because %select{it refines|its 'where' clause uses}2|%select{in this context|fileprivate|internal|public|%error}1 %select{protocol cannot refine|protocol's 'where' clause cannot use}2}0 %select{a private|a fileprivate|an internal|%error|%error}3 %5" - id: protocol_access_warn - msg: >- - %select{protocol should be declared - %select{private|fileprivate|internal|%error|%error}1 because %select{it - refines|its 'where' clause uses}2|%select{in this - context|fileprivate|internal|public|%error}1 %select{protocol should not - refine|protocol's 'where' clause should not use}2}0 %select{a private|a - fileprivate|an internal|%error|%error}3 %5 + msg: "%select{protocol should be declared %select{private|fileprivate|internal|%error|%error}1 because %select{it refines|its 'where' clause uses}2|%select{in this context|fileprivate|internal|public|%error}1 %select{protocol should not refine|protocol's 'where' clause should not use}2}0 %select{a private|a fileprivate|an internal|%error|%error}3 %5" - id: protocol_usable_from_inline - msg: >- - protocol %select{refined|used}0 by '@usableFromInline' protocol must be - '@usableForInline' or public + msg: "protocol %select{refined|used}0 by '@usableFromInline' protocol must be '@usableForInline' or public" - id: protocol_usable_from_inline_warn - msg: >- - protocol %select{refined|used}0 by '@usableFromInline' protocol should be - '@usableForInline' or public + msg: "protocol %select{refined|used}0 by '@usableFromInline' protocol should be '@usableForInline' or public" - id: protocol_property_must_be_computed_var - msg: >- - protocols cannot require properties to be immutable; declare read-only - properties by using 'var' with a '{ get }' specifier + msg: "protocols cannot require properties to be immutable; declare read-only properties by using 'var' with a '{ get }' specifier" - id: protocol_property_must_be_computed - msg: >- - property in protocol must have explicit { get } or { get set } specifier + msg: "property in protocol must have explicit { get } or { get set } specifier" - id: inherited_protocol_does_not_conform - msg: >- - type %0 does not conform to inherited protocol %1 + msg: "type %0 does not conform to inherited protocol %1" - id: no_witnesses - msg: >- - protocol requires %select{initializer %1|function %1|property - %1|subscript}0 with type %2%select{|; do you want to add a stub?}3 + msg: "protocol requires %select{initializer %1|function %1|property %1|subscript}0 with type %2%select{|; do you want to add a stub?}3" - id: missing_witnesses_general - msg: >- - do you want to add protocol stubs? + msg: "do you want to add protocol stubs?" - id: ambiguous_witnesses - msg: >- - multiple matching %select{initializers named %1|functions named - %1|properties named %1|subscript operators}0 with type %2 + msg: "multiple matching %select{initializers named %1|functions named %1|properties named %1|subscript operators}0 with type %2" - id: ambiguous_witnesses_wrong_name - msg: >- - multiple matching %select{initializers named %1|functions named - %1|properties named %1|subscript operators}0 with type %2 + msg: "multiple matching %select{initializers named %1|functions named %1|properties named %1|subscript operators}0 with type %2" - id: no_witnesses_type - msg: >- - protocol requires nested type %0; do you want to add it? + msg: "protocol requires nested type %0; do you want to add it?" - id: default_associated_type_req_fail - msg: >- - default type %0 for associated type %1 (from protocol %2) does not - %select{inherit from|conform to}4 %3 + msg: "default type %0 for associated type %1 (from protocol %2) does not %select{inherit from|conform to}4 %3" - id: associated_type_access - msg: >- - associated type in %select{a private|a fileprivate|an internal|a - public|%error}0 protocol uses %select{a private|a fileprivate|an - internal|%error|%error}1 type in its - %select{default definition|requirement}2 + msg: "associated type in %select{a private|a fileprivate|an internal|a public|%error}0 protocol uses %select{a private|a fileprivate|an internal|%error|%error}1 type in its %select{default definition|requirement}2 " - id: associated_type_access_warn - msg: >- - associated type in %select{a private|a fileprivate|an internal|a - public|%error}0 protocol uses %select{a private|a fileprivate|an - internal|%error|%error}1 type in its - %select{default definition|requirement}2 + msg: "associated type in %select{a private|a fileprivate|an internal|a public|%error}0 protocol uses %select{a private|a fileprivate|an internal|%error|%error}1 type in its %select{default definition|requirement}2 " - id: associated_type_not_usable_from_inline - msg: >- - type referenced from a %select{default definition|requirement}0 of an - associated type in a '@usableFromInline' - protocol must be '@usableFromInline' or public + msg: "type referenced from a %select{default definition|requirement}0 of an associated type in a '@usableFromInline' protocol must be '@usableFromInline' or public" - id: associated_type_not_usable_from_inline_warn - msg: >- - type referenced from a %select{default definition|requirement}0 of an - associated type in a '@usableFromInline' - protocol should be '@usableFromInline' or public + msg: "type referenced from a %select{default definition|requirement}0 of an associated type in a '@usableFromInline' protocol should be '@usableFromInline' or public" - id: bad_associated_type_deduction - msg: >- - unable to infer associated type %0 for protocol %1 + msg: "unable to infer associated type %0 for protocol %1" - id: associated_type_deduction_witness_failed - msg: >- - candidate would match and infer %0 = %1 if %1 %select{inherited - from|conformed to}3 %2 + msg: "candidate would match and infer %0 = %1 if %1 %select{inherited from|conformed to}3 %2" - id: associated_type_witness_conform_impossible - msg: >- - candidate can not infer %0 = %1 because %1 is not a nominal type and so - can't conform to %2 + msg: "candidate can not infer %0 = %1 because %1 is not a nominal type and so can't conform to %2" - id: associated_type_witness_inherit_impossible - msg: >- - candidate can not infer %0 = %1 because %1 is not a class type and so - can't inherit from %2 + msg: "candidate can not infer %0 = %1 because %1 is not a class type and so can't inherit from %2" - id: ambiguous_associated_type_deduction - msg: >- - ambiguous inference of associated type %0: %1 vs. %2 + msg: "ambiguous inference of associated type %0: %1 vs. %2" - id: associated_type_deduction_witness - msg: >- - matching requirement %0 to this declaration inferred associated type to %1 + msg: "matching requirement %0 to this declaration inferred associated type to %1" - id: associated_type_deduction_default - msg: >- - using associated type default %0 + msg: "using associated type default %0" - id: ambiguous_witnesses_type - msg: >- - multiple matching types named %0 + msg: "multiple matching types named %0" - id: protocol_witness_exact_match - msg: >- - candidate exactly matches%0 + msg: "candidate exactly matches%0" - id: protocol_witness_renamed - msg: >- - rename to %0 to satisfy this requirement%1 + msg: "rename to %0 to satisfy this requirement%1" - id: protocol_witness_kind_conflict - msg: >- - candidate is not %select{an initializer|a function|a variable|a subscript}0 + msg: "candidate is not %select{an initializer|a function|a variable|a subscript}0" - id: protocol_witness_type_conflict - msg: >- - candidate has non-matching type %0%1 + msg: "candidate has non-matching type %0%1" - id: protocol_witness_missing_requirement - msg: >- - candidate would match if %0 %select{conformed to|subclassed|was the same - type as}2 %1 + msg: "candidate would match if %0 %select{conformed to|subclassed|was the same type as}2 %1" - id: protocol_witness_optionality_conflict - msg: >- - candidate %select{type has|result type has|parameter type has|parameter - types have|result and parameter types have}0 incorrect optionality%1 + msg: "candidate %select{type has|result type has|parameter type has|parameter types have|result and parameter types have}0 incorrect optionality%1" - id: err_protocol_witness_optionality - msg: >- - %select{type|result|parameter|parameters|result and parameters}0 of %1 - %select{has|has|has|have|have|}0 - different optionality than required by protocol %2 + msg: "%select{type|result|parameter|parameters|result and parameters}0 of %1 %select{has|has|has|have|have|}0 different optionality than required by protocol %2" - id: warn_protocol_witness_optionality - msg: >- - %select{type|result|parameter|parameters|result and parameters}0 of %1 - %select{has|has|has|have|have|}0 different optionality than expected by - protocol %2 + msg: "%select{type|result|parameter|parameters|result and parameters}0 of %1 %select{has|has|has|have|have|}0 different optionality than expected by protocol %2" - id: protocol_witness_static_conflict - msg: >- - candidate operates on %select{a type|an instance}0, not %select{an - instance|a type}0 as required + msg: "candidate operates on %select{a type|an instance}0, not %select{an instance|a type}0 as required" - id: protocol_witness_prefix_postfix_conflict - msg: >- - candidate is %select{|prefix, |postfix, }1not %select{prefix|postfix}0 as - required + msg: "candidate is %select{|prefix, |postfix, }1not %select{prefix|postfix}0 as required" - id: protocol_witness_mutation_modifier_conflict - msg: >- - candidate is marked %0 but protocol does not allow it + msg: "candidate is marked %0 but protocol does not allow it" - id: protocol_witness_settable_conflict - msg: >- - candidate is not settable, but protocol requires it + msg: "candidate is not settable, but protocol requires it" - id: protocol_witness_rethrows_conflict - msg: >- - candidate is not 'rethrows', but protocol requires it + msg: "candidate is not 'rethrows', but protocol requires it" - id: protocol_witness_throws_conflict - msg: >- - candidate throws, but protocol does not allow it + msg: "candidate throws, but protocol does not allow it" - id: protocol_witness_not_objc - msg: >- - candidate is explicitly '@nonobjc' + msg: "candidate is explicitly '@nonobjc'" - id: protocol_witness_enum_case_payload - msg: >- - candidate is an enum case with associated values, but protocol does not - allow it + msg: "candidate is an enum case with associated values, but protocol does not allow it" - id: protocol_witness_type - msg: >- - possibly intended match + msg: "possibly intended match" - id: protocol_witness_nonconform_type - msg: >- - possibly intended match %0 does not %select{inherit from|conform to}2 %1 + msg: "possibly intended match %0 does not %select{inherit from|conform to}2 %1" - id: protocol_witness_circularity - msg: >- - candidate references itself + msg: "candidate references itself" - id: protocol_conformance_here - msg: >- - %select{|class }0%1 declares conformance to protocol %2 here + msg: "%select{|class }0%1 declares conformance to protocol %2 here" - id: declared_protocol_conformance_here - msg: >- - %select{%0 inherits conformance to protocol %2 from superclass|%0 - declares conformance to protocol %2|%0 implicitly conforms to protocol %2 - (via conformance to %3)|%0 implicitly conforms to protocol %2}1 here + msg: "%select{%0 inherits conformance to protocol %2 from superclass|%0 declares conformance to protocol %2|%0 implicitly conforms to protocol %2 (via conformance to %3)|%0 implicitly conforms to protocol %2}1 here" - id: witness_unavailable - msg: >- - unavailable %0 %1 was used to satisfy a requirement of protocol %2 + msg: "unavailable %0 %1 was used to satisfy a requirement of protocol %2" - id: redundant_conformance - msg: >- - redundant conformance of %0 to protocol %1 + msg: "redundant conformance of %0 to protocol %1" - id: redundant_conformance_conditional - msg: >- - conflicting conformance of %0 to protocol %1; there cannot be more than - one conformance, even with different conditional bounds + msg: "conflicting conformance of %0 to protocol %1; there cannot be more than one conformance, even with different conditional bounds" - id: redundant_conformance_adhoc - msg: >- - conformance of %0 to protocol %1 was already stated in - %select{the protocol's|the type's}2 module %3 + msg: "conformance of %0 to protocol %1 was already stated in %select{the protocol's|the type's}2 module %3" - id: redundant_conformance_adhoc_conditional - msg: >- - conformance of %0 to protocol %1 conflicts with that stated in - %select{the protocol's|the type's}2 module %3 and will be ignored; - there cannot be more than one conformance, - even with different conditional bounds + msg: "conformance of %0 to protocol %1 conflicts with that stated in %select{the protocol's|the type's}2 module %3 and will be ignored; there cannot be more than one conformance, even with different conditional bounds" - id: redundant_conformance_witness_ignored - msg: >- - %0 %1 will not be used to satisfy the conformance to %2 + msg: "%0 %1 will not be used to satisfy the conformance to %2" - id: req_near_match - msg: >- - %0 %1 nearly matches %select{defaulted|optional}2 requirement %3 of - protocol %4 + msg: "%0 %1 nearly matches %select{defaulted|optional}2 requirement %3 of protocol %4" - id: optional_req_nonobjc_near_match_add_objc - msg: >- - add '@objc' to provide an Objective-C entrypoint + msg: "add '@objc' to provide an Objective-C entrypoint" - id: req_near_match_move - msg: >- - move %0 to %select{an|another}1 extension to silence this warning + msg: "move %0 to %select{an|another}1 extension to silence this warning" - id: req_near_match_nonobjc - msg: >- - add '@nonobjc' to silence this %select{warning|error}0 + msg: "add '@nonobjc' to silence this %select{warning|error}0" - id: req_near_match_access - msg: >- - make %0 %select{ERROR|private|private|non-public|non-public}1 to silence - this warning + msg: "make %0 %select{ERROR|private|private|non-public|non-public}1 to silence this warning" - id: missing_append_interpolation - msg: >- - type conforming to 'StringInterpolationProtocol' does not implement a - valid 'appendInterpolation' method + msg: "type conforming to 'StringInterpolationProtocol' does not implement a valid 'appendInterpolation' method" - id: append_interpolation_static - msg: >- - 'appendInterpolation' method will never be used because it is static + msg: "'appendInterpolation' method will never be used because it is static" - id: append_interpolation_void_or_discardable - msg: >- - 'appendInterpolation' method does not return 'Void' or have a discardable - result + msg: "'appendInterpolation' method does not return 'Void' or have a discardable result" - id: append_interpolation_access_control - msg: >- - 'appendInterpolation' method is - %select{private|fileprivate|internal|public|open}0, but %1 is - %select{private|fileprivate|internal|public|open}2 + msg: "'appendInterpolation' method is %select{private|fileprivate|internal|public|open}0, but %1 is %select{private|fileprivate|internal|public|open}2" - id: assoc_type_outside_of_protocol - msg: >- - associated type %0 can only be used with a concrete type or generic - parameter base + msg: "associated type %0 can only be used with a concrete type or generic parameter base" - id: typealias_outside_of_protocol - msg: >- - type alias %0 can only be used with a concrete type or generic parameter - base + msg: "type alias %0 can only be used with a concrete type or generic parameter base" - id: objc_protocol_inherits_non_objc_protocol - msg: >- - @objc protocol %0 cannot refine non-@objc protocol %1 + msg: "@objc protocol %0 cannot refine non-@objc protocol %1" - id: protocol_where_clause_self_requirement - msg: >- - constraint with subject type of 'Self' is not supported; consider adding - requirement to protocol inheritance clause instead + msg: "constraint with subject type of 'Self' is not supported; consider adding requirement to protocol inheritance clause instead" - id: invalid_protocol_composition_member - msg: >- - non-protocol, non-class type %0 cannot be used within a - protocol-constrained type + msg: "non-protocol, non-class type %0 cannot be used within a protocol-constrained type" - id: protocol_composition_one_class - msg: >- - protocol-constrained type cannot contain class %0 because it already - contains class %1 + msg: "protocol-constrained type cannot contain class %0 because it already contains class %1" - id: requires_conformance_nonprotocol - msg: >- - type %0 constrained to non-protocol, non-class type %1 + msg: "type %0 constrained to non-protocol, non-class type %1" - id: requires_conformance_nonprotocol_fixit - msg: >- - use '%0 == %1' to require '%0' to be '%1' + msg: "use '%0 == %1' to require '%0' to be '%1'" - id: requires_not_suitable_archetype - msg: >- - type %0 in conformance requirement does not refer to a generic parameter - or associated type + msg: "type %0 in conformance requirement does not refer to a generic parameter or associated type" - id: requires_no_same_type_archetype - msg: >- - neither type in same-type constraint (%0 or %1) refers to a generic - parameter or associated type + msg: "neither type in same-type constraint (%0 or %1) refers to a generic parameter or associated type" - id: requires_generic_params_made_equal - msg: >- - same-type requirement makes generic parameters %0 and %1 equivalent + msg: "same-type requirement makes generic parameters %0 and %1 equivalent" - id: requires_generic_param_made_equal_to_concrete - msg: >- - same-type requirement makes generic parameter %0 non-generic + msg: "same-type requirement makes generic parameter %0 non-generic" - id: recursive_decl_reference - msg: >- - %0 %1 references itself + msg: "%0 %1 references itself" - id: recursive_same_type_constraint - msg: >- - same-type constraint %0 == %1 is recursive + msg: "same-type constraint %0 == %1 is recursive" - id: recursive_superclass_constraint - msg: >- - superclass constraint %0 : %1 is recursive + msg: "superclass constraint %0 : %1 is recursive" - id: requires_generic_param_same_type_does_not_conform - msg: >- - same-type constraint type %0 does not conform to required protocol %1 + msg: "same-type constraint type %0 does not conform to required protocol %1" - id: requires_same_concrete_type - msg: >- - generic signature requires types %0 and %1 to be the same + msg: "generic signature requires types %0 and %1 to be the same" - id: redundant_conformance_constraint - msg: >- - redundant conformance constraint %0: %1 + msg: "redundant conformance constraint %0: %1" - id: redundant_conformance_here - msg: >- - conformance constraint %1: %2 %select{written here|implied here|inferred - from type here}0 + msg: "conformance constraint %1: %2 %select{written here|implied here|inferred from type here}0" - id: unsupported_recursive_requirements - msg: >- - requirement involves recursion that is not currently supported + msg: "requirement involves recursion that is not currently supported" - id: same_type_conflict - msg: >- - %select{generic parameter |protocol |}0%1 cannot be equal to both %2 and %3 + msg: "%select{generic parameter |protocol |}0%1 cannot be equal to both %2 and %3" - id: redundant_same_type_to_concrete - msg: >- - redundant same-type constraint %0 == %1 + msg: "redundant same-type constraint %0 == %1" - id: same_type_redundancy_here - msg: >- - same-type constraint %1 == %2 %select{written here|implied here|inferred - from type here}0 + msg: "same-type constraint %1 == %2 %select{written here|implied here|inferred from type here}0" - id: requires_superclass_conflict - msg: >- - %select{generic parameter %1 cannot|protocol %1 cannot require 'Self' - to|%1 cannot}0 be a subclass of both %2 and %3 + msg: "%select{generic parameter %1 cannot|protocol %1 cannot require 'Self' to|%1 cannot}0 be a subclass of both %2 and %3" - id: redundant_superclass_constraint - msg: >- - redundant superclass constraint %0 : %1 + msg: "redundant superclass constraint %0 : %1" - id: superclass_redundancy_here - msg: >- - superclass constraint %1 : %2 %select{written here|implied here|inferred - from type here}0 + msg: "superclass constraint %1 : %2 %select{written here|implied here|inferred from type here}0" - id: conflicting_layout_constraints - msg: >- - %select{generic parameter |protocol |}0%1 has conflicting constraints %2 - and %3 + msg: "%select{generic parameter |protocol |}0%1 has conflicting constraints %2 and %3" - id: redundant_layout_constraint - msg: >- - redundant constraint %0 : %1 + msg: "redundant constraint %0 : %1" - id: previous_layout_constraint - msg: >- - constraint %1 : %2 %select{written here|implied here|inferred from type - here}0 + msg: "constraint %1 : %2 %select{written here|implied here|inferred from type here}0" - id: redundant_same_type_constraint - msg: >- - redundant same-type constraint %0 == %1 + msg: "redundant same-type constraint %0 == %1" - id: previous_same_type_constraint - msg: >- - previous same-type constraint %1 == %2 %select{written here|implied - here|inferred from type here}0 + msg: "previous same-type constraint %1 == %2 %select{written here|implied here|inferred from type here}0" - id: inherited_associated_type_redecl - msg: >- - redeclaration of associated type %0 from protocol %1 is better expressed - as a 'where' clause on the protocol + msg: "redeclaration of associated type %0 from protocol %1 is better expressed as a 'where' clause on the protocol" - id: typealias_override_associated_type - msg: >- - typealias overriding associated type %0 from protocol %1 is better - expressed as same-type constraint on the protocol + msg: "typealias overriding associated type %0 from protocol %1 is better expressed as same-type constraint on the protocol" - id: associated_type_override_typealias - msg: >- - associated type %0 is redundant with type %0 declared in inherited %1 %2 + msg: "associated type %0 is redundant with type %0 declared in inherited %1 %2" - id: associated_type_objc - msg: >- - associated type %0 cannot be declared inside '@objc' protocol %1 + msg: "associated type %0 cannot be declared inside '@objc' protocol %1" - id: generic_param_access - msg: >- - %0 %select{must be declared - %select{%select{private|fileprivate|internal|%error|%error}3|private or - fileprivate}4|cannot be declared %select{in this - context|fileprivate|internal|public|open}2}1 because its generic - %select{parameter|requirement}5 uses %select{a private|a fileprivate|an - internal|an '@_spi'|an '@_spi'}3 type + msg: "%0 %select{must be declared %select{%select{private|fileprivate|internal|%error|%error}3|private or fileprivate}4|cannot be declared %select{in this context|fileprivate|internal|public|open}2}1 because its generic %select{parameter|requirement}5 uses %select{a private|a fileprivate|an internal|an '@_spi'|an '@_spi'}3 type" - id: generic_param_access_warn - msg: >- - %0 %select{should be declared - %select{private|fileprivate|internal|%error|%error}3|should not be declared - %select{in this context|fileprivate|internal|public|open}2}1 because its generic - %select{parameter|requirement}5 uses %select{a private|a fileprivate|an - internal|an '@_spi'|an '@_spi'}3 type + msg: "%0 %select{should be declared %select{private|fileprivate|internal|%error|%error}3|should not be declared %select{in this context|fileprivate|internal|public|open}2}1 because its generic %select{parameter|requirement}5 uses %select{a private|a fileprivate|an internal|an '@_spi'|an '@_spi'}3 type" - id: generic_param_usable_from_inline - msg: >- - type referenced from a generic %select{parameter|requirement}1 of a - '@usableFromInline' %0 must be '@usableFromInline' or public + msg: "type referenced from a generic %select{parameter|requirement}1 of a '@usableFromInline' %0 must be '@usableFromInline' or public" - id: generic_param_usable_from_inline_warn - msg: >- - type referenced from a generic %select{parameter|requirement}1 of a - '@usableFromInline' %0 should be '@usableFromInline' or public + msg: "type referenced from a generic %select{parameter|requirement}1 of a '@usableFromInline' %0 should be '@usableFromInline' or public" - id: override_multiple_decls_base - msg: >- - declaration %0 cannot override more than one superclass declaration + msg: "declaration %0 cannot override more than one superclass declaration" - id: override_multiple_decls_arg_mismatch - msg: >- - declaration %0 has different argument labels from any potential overrides + msg: "declaration %0 has different argument labels from any potential overrides" - id: overridden_near_match_here - msg: >- - potential overridden %0 %1 here + msg: "potential overridden %0 %1 here" - id: override_decl_extension - msg: >- - overriding %select{|non-@objc }0declarations %select{in extensions|from - extensions}0 is not supported + msg: "overriding %select{|non-@objc }0declarations %select{in extensions|from extensions}0 is not supported" - id: overridden_here - msg: >- - overridden declaration is here + msg: "overridden declaration is here" - id: overridden_here_can_be_objc - msg: >- - add '@objc' to make this declaration overridable + msg: "add '@objc' to make this declaration overridable" - id: missing_override - msg: >- - overriding declaration requires an 'override' keyword + msg: "overriding declaration requires an 'override' keyword" - id: missing_override_warn - msg: >- - implicit override should be marked with 'override' or suppressed with - '@_nonoverride' + msg: "implicit override should be marked with 'override' or suppressed with '@_nonoverride'" - id: multiple_override - msg: >- - %0 has already been overridden + msg: "%0 has already been overridden" - id: multiple_override_prev - msg: >- - %0 previously overridden here + msg: "%0 previously overridden here" - id: override_unavailable - msg: >- - cannot override %0 which has been marked unavailable%select{|: %1}1 + msg: "cannot override %0 which has been marked unavailable%select{|: %1}1" - id: suggest_removing_override - msg: >- - remove 'override' modifier to declare a new %0 + msg: "remove 'override' modifier to declare a new %0" - id: override_less_available - msg: >- - overriding %0 must be as available as declaration it overrides + msg: "overriding %0 must be as available as declaration it overrides" - id: override_accessor_less_available - msg: >- - overriding %0 for %1 must be as available as declaration it overrides + msg: "overriding %0 for %1 must be as available as declaration it overrides" - id: override_let_property - msg: >- - cannot override immutable 'let' property %0 with the getter of a 'var' + msg: "cannot override immutable 'let' property %0 with the getter of a 'var'" - id: override_not_accessible - msg: >- - %select{|setter of }0overriding %1 must be as accessible as %select{its - enclosing type|the declaration it overrides}2 + msg: "%select{|setter of }0overriding %1 must be as accessible as %select{its enclosing type|the declaration it overrides}2" - id: override_of_non_open - msg: >- - overriding non-open %0 outside of its defining module + msg: "overriding non-open %0 outside of its defining module" - id: method_does_not_override - msg: >- - method does not override any method from its %select{parent protocol|superclass}0 + msg: "method does not override any method from its %select{parent protocol|superclass}0" - id: property_does_not_override - msg: >- - property does not override any property from its %select{parent protocol|superclass}0 + msg: "property does not override any property from its %select{parent protocol|superclass}0" - id: subscript_does_not_override - msg: >- - subscript does not override any subscript from its %select{parent protocol|superclass}0 + msg: "subscript does not override any subscript from its %select{parent protocol|superclass}0" - id: initializer_does_not_override - msg: >- - initializer does not override a designated initializer from its - %select{parent protocol|superclass}0 + msg: "initializer does not override a designated initializer from its %select{parent protocol|superclass}0" - id: failable_initializer_override - msg: >- - failable initializer %0 cannot override a non-failable initializer + msg: "failable initializer %0 cannot override a non-failable initializer" - id: nonfailable_initializer_override_here - msg: >- - non-failable initializer %0 overridden here + msg: "non-failable initializer %0 overridden here" - id: property_override_here - msg: >- - attempt to override property here + msg: "attempt to override property here" - id: subscript_override_here - msg: >- - attempt to override subscript here + msg: "attempt to override subscript here" - id: convenience_init_override_here - msg: >- - attempt to override convenience initializer here + msg: "attempt to override convenience initializer here" - id: override_type_mismatch_with_fixits - msg: >- - type does not match superclass %0 with type %1 + msg: "type does not match superclass %0 with type %1" - id: override_type_mismatch_with_fixits_init - msg: >- - type does not match superclass initializer with %select{no - arguments|argument %1|arguments %1}0 + msg: "type does not match superclass initializer with %select{no arguments|argument %1|arguments %1}0" - id: override_nonclass_decl - msg: >- - 'override' can only be specified on class members + msg: "'override' can only be specified on class members" - id: nonoverride_wrong_decl_context - msg: >- - '@_nonoverride' can only be specified on class or protocol members + msg: "'@_nonoverride' can only be specified on class or protocol members" - id: nonoverride_and_override_attr - msg: >- - 'override' cannot be combined with '@_nonoverride' + msg: "'override' cannot be combined with '@_nonoverride'" - id: override_property_type_mismatch - msg: >- - property %0 with type %1 cannot override a property with type %2 + msg: "property %0 with type %1 cannot override a property with type %2" - id: override_with_stored_property - msg: >- - cannot override with a stored property %0 + msg: "cannot override with a stored property %0" - id: override_with_stored_property_warn - msg: >- - cannot override with a stored property %0 + msg: "cannot override with a stored property %0" - id: observing_readonly_property - msg: >- - cannot observe read-only property %0; it can't change + msg: "cannot observe read-only property %0; it can't change" - id: override_mutable_with_readonly_property - msg: >- - cannot override mutable property with read-only property %0 + msg: "cannot override mutable property with read-only property %0" - id: override_argument_name_mismatch - msg: >- - argument labels for %select{method|initializer}0 %1 do not match those of - overridden %select{method|initializer}0 %2 + msg: "argument labels for %select{method|initializer}0 %1 do not match those of overridden %select{method|initializer}0 %2" - id: override_ownership_mismatch - msg: >- - cannot override %0 property with %1 property + msg: "cannot override %0 property with %1 property" - id: override_dynamic_self_mismatch - msg: >- - cannot override a Self return type with a non-Self return type + msg: "cannot override a Self return type with a non-Self return type" - id: override_class_declaration_in_extension - msg: >- - cannot override a non-dynamic class declaration from an extension + msg: "cannot override a non-dynamic class declaration from an extension" - id: override_throws - msg: >- - cannot override non-throwing %select{method|initializer}0 with throwing - %select{method|initializer}0 + msg: "cannot override non-throwing %select{method|initializer}0 with throwing %select{method|initializer}0" - id: override_throws_objc - msg: >- - overriding a throwing @objc %select{method|initializer}0 with a - non-throwing %select{method|initializer}0 is not supported + msg: "overriding a throwing @objc %select{method|initializer}0 with a non-throwing %select{method|initializer}0 is not supported" - id: satisfy_throws_objc - msg: >- - satisfying a throwing @objc %select{method|initializer}0 with a - non-throwing %select{method|initializer}0 is not supported + msg: "satisfying a throwing @objc %select{method|initializer}0 with a non-throwing %select{method|initializer}0 is not supported" - id: override_optional_mismatch - msg: >- - cannot override %0 %select{parameter|index}1 of type %2 with non-optional - type %3 + msg: "cannot override %0 %select{parameter|index}1 of type %2 with non-optional type %3" - id: override_optional_result_mismatch - msg: >- - cannot override %0 %select{result|element}1 type %2 with optional type %3 + msg: "cannot override %0 %select{result|element}1 type %2 with optional type %3" - id: override_unnecessary_IUO - msg: >- - overriding %0 parameter of type %1 with implicitly unwrapped optional - type %2 + msg: "overriding %0 parameter of type %1 with implicitly unwrapped optional type %2" - id: override_unnecessary_result_IUO - msg: >- - overriding %0 optional result type %1 with implicitly unwrapped optional - type %2 + msg: "overriding %0 optional result type %1 with implicitly unwrapped optional type %2" - id: override_unnecessary_IUO_remove - msg: >- - remove '!' to make the parameter required + msg: "remove '!' to make the parameter required" - id: override_unnecessary_IUO_use_strict - msg: >- - use '?' to make the result optional + msg: "use '?' to make the result optional" - id: override_unnecessary_IUO_silence - msg: >- - add parentheses to silence this warning + msg: "add parentheses to silence this warning" - id: override_mutable_covariant_property - msg: >- - cannot override mutable property %0 of type %1 with covariant type %2 + msg: "cannot override mutable property %0 of type %1 with covariant type %2" - id: override_mutable_covariant_subscript - msg: >- - cannot override mutable subscript of type %0 with covariant type %1 + msg: "cannot override mutable subscript of type %0 with covariant type %1" - id: static_decl_already_final - msg: >- - static declarations are already final + msg: "static declarations are already final" - id: open_decl_cannot_be_final - msg: >- - %0 cannot be declared both 'final' and 'open' + msg: "%0 cannot be declared both 'final' and 'open'" - id: implicitly_final_cannot_be_open - msg: >- - %select{'let' properties|members of 'final' classes|static declarations}0 - are implicitly 'final'; use 'public' instead of 'open' + msg: "%select{'let' properties|members of 'final' classes|static declarations}0 are implicitly 'final'; use 'public' instead of 'open'" - id: implicitly_final_cannot_be_open_swift4 - msg: >- - %select{'let' properties|members of 'final' classes|static declarations}0 - are implicitly 'final'; use 'public' instead of 'open' + msg: "%select{'let' properties|members of 'final' classes|static declarations}0 are implicitly 'final'; use 'public' instead of 'open'" - id: override_swift3_objc_inference - msg: >- - override of %0 %1 from extension of %2 depends on deprecated inference of - '@objc' + msg: "override of %0 %1 from extension of %2 depends on deprecated inference of '@objc'" - id: override_method_different_generic_sig - msg: >- - overridden method %0 has generic signature %1 which is incompatible with - base method's generic signature %2; expected generic signature to be %3 + msg: "overridden method %0 has generic signature %1 which is incompatible with base method's generic signature %2; expected generic signature to be %3" - id: duplicate_inheritance - msg: >- - duplicate inheritance from %0 + msg: "duplicate inheritance from %0" - id: duplicate_anyobject_class_inheritance - msg: >- - redundant inheritance from 'AnyObject' and Swift 3 'class' keyword + msg: "redundant inheritance from 'AnyObject' and Swift 3 'class' keyword" - id: inheritance_from_protocol_with_superclass - msg: >- - inheritance from class-constrained protocol composition type %0 + msg: "inheritance from class-constrained protocol composition type %0" - id: multiple_inheritance - msg: >- - multiple inheritance from classes %0 and %1 + msg: "multiple inheritance from classes %0 and %1" - id: inheritance_from_non_protocol_or_class - msg: >- - inheritance from non-protocol, non-class type %0 + msg: "inheritance from non-protocol, non-class type %0" - id: inheritance_from_non_protocol - msg: >- - inheritance from non-protocol type %0 + msg: "inheritance from non-protocol type %0" - id: superclass_not_first - msg: >- - superclass %0 must appear first in the inheritance clause + msg: "superclass %0 must appear first in the inheritance clause" - id: superclass_not_open - msg: >- - cannot inherit from non-open class %0 outside of its defining module + msg: "cannot inherit from non-open class %0 outside of its defining module" - id: superclass_here - msg: >- - superclass is declared here + msg: "superclass is declared here" - id: superclass_of_open_not_open - msg: >- - superclass %0 of open class must be open + msg: "superclass %0 of open class must be open" - id: inheritance_from_final_class - msg: >- - inheritance from a final class %0 + msg: "inheritance from a final class %0" - id: inheritance_from_unspecialized_objc_generic_class - msg: >- - inheritance from a generic Objective-C class %0 must bind type parameters - of %0 to specific concrete types + msg: "inheritance from a generic Objective-C class %0 must bind type parameters of %0 to specific concrete types" - id: inheritance_from_class_with_missing_vtable_entries - msg: >- - cannot inherit from class %0 because it has overridable members that - could not be loaded + msg: "cannot inherit from class %0 because it has overridable members that could not be loaded" - id: inheritance_from_class_with_missing_vtable_entries_versioned - msg: >- - cannot inherit from class %0 (compiled with Swift %1) because it has - overridable members that could not be loaded in Swift %2 + msg: "cannot inherit from class %0 (compiled with Swift %1) because it has overridable members that could not be loaded in Swift %2" - id: inheritance_from_cf_class - msg: >- - cannot inherit from Core Foundation type %0 + msg: "cannot inherit from Core Foundation type %0" - id: inheritance_from_objc_runtime_visible_class - msg: >- - cannot inherit from class %0 because it is only visible via the - Objective-C runtime + msg: "cannot inherit from class %0 because it is only visible via the Objective-C runtime" - id: enum_case_access - msg: >- - enum case in %select{a private|a fileprivate|an internal|a - public|%error}0 enum uses %select{a private|a fileprivate|an - internal|%error|%error}1 type + msg: "enum case in %select{a private|a fileprivate|an internal|a public|%error}0 enum uses %select{a private|a fileprivate|an internal|%error|%error}1 type" - id: enum_case_access_warn - msg: >- - enum case in %select{a private|a fileprivate|an internal|a - public|%error}0 enum uses %select{a private|a fileprivate|an - internal|%error|%error}1 type + msg: "enum case in %select{a private|a fileprivate|an internal|a public|%error}0 enum uses %select{a private|a fileprivate|an internal|%error|%error}1 type" - id: enum_case_usable_from_inline - msg: >- - type of enum case in '@usableFromInline' enum must be '@usableFromInline' - or public + msg: "type of enum case in '@usableFromInline' enum must be '@usableFromInline' or public" - id: enum_case_usable_from_inline_warn - msg: >- - type of enum case in '@usableFromInline' enum should be - '@usableFromInline' or public + msg: "type of enum case in '@usableFromInline' enum should be '@usableFromInline' or public" - id: enum_stored_property - msg: >- - enums must not contain stored properties + msg: "enums must not contain stored properties" - id: multiple_enum_raw_types - msg: >- - multiple enum raw types %0 and %1 + msg: "multiple enum raw types %0 and %1" - id: raw_type_not_first - msg: >- - raw type %0 must appear first in the enum inheritance clause + msg: "raw type %0 must appear first in the enum inheritance clause" - id: raw_type_not_literal_convertible - msg: >- - raw type %0 is not expressible by a string, integer, or floating-point - literal + msg: "raw type %0 is not expressible by a string, integer, or floating-point literal" - id: enum_raw_type_not_equatable - msg: >- - RawRepresentable conformance cannot be synthesized because raw type %0 is - not Equatable + msg: "RawRepresentable conformance cannot be synthesized because raw type %0 is not Equatable" - id: enum_raw_type_nonconforming_and_nonsynthable - msg: >- - %0 declares raw type %1, but does not conform to RawRepresentable and - conformance could not be synthesized + msg: "%0 declares raw type %1, but does not conform to RawRepresentable and conformance could not be synthesized" - id: enum_declares_rawrep_with_raw_type - msg: >- - %0 declares raw type %1, which implies RawRepresentable + msg: "%0 declares raw type %1, which implies RawRepresentable" - id: enum_raw_type_access - msg: >- - enum %select{must be declared - %select{%select{private|fileprivate|internal|%error|%error}1|private or - fileprivate}3|cannot be declared %select{in this - context|fileprivate|internal|public|open}1}0 because its raw type uses - %select{a private|a fileprivate|an internal|%error|%error}2 type + msg: "enum %select{must be declared %select{%select{private|fileprivate|internal|%error|%error}1|private or fileprivate}3|cannot be declared %select{in this context|fileprivate|internal|public|open}1}0 because its raw type uses %select{a private|a fileprivate|an internal|%error|%error}2 type" - id: enum_raw_type_access_warn - msg: >- - enum %select{should be declared - %select{private|fileprivate|internal|%error|%error}1|should not be declared - %select{in this context|fileprivate|internal|public|open}1}0 because its raw - type uses %select{a private|a fileprivate|an internal|%error|%error}2 type + msg: "enum %select{should be declared %select{private|fileprivate|internal|%error|%error}1|should not be declared %select{in this context|fileprivate|internal|public|open}1}0 because its raw type uses %select{a private|a fileprivate|an internal|%error|%error}2 type" - id: enum_raw_type_not_usable_from_inline - msg: >- - type referenced from the raw type of a '@usableFromInline' enum must be - '@usableFromInline' or public + msg: "type referenced from the raw type of a '@usableFromInline' enum must be '@usableFromInline' or public" - id: enum_raw_type_not_usable_from_inline_warn - msg: >- - type referenced from the raw type of a '@usableFromInline' enum should be - '@usableFromInline' or public + msg: "type referenced from the raw type of a '@usableFromInline' enum should be '@usableFromInline' or public" - id: empty_enum_raw_type - msg: >- - an enum with no cases cannot declare a raw type + msg: "an enum with no cases cannot declare a raw type" - id: enum_raw_value_without_raw_type - msg: >- - enum case cannot have a raw value if the enum does not have a raw type + msg: "enum case cannot have a raw value if the enum does not have a raw type" - id: enum_with_raw_type_case_with_argument - msg: >- - enum with raw type cannot have cases with arguments + msg: "enum with raw type cannot have cases with arguments" - id: enum_raw_type_here - msg: >- - declared raw type %0 here + msg: "declared raw type %0 here" - id: objc_enum_no_raw_type - msg: >- - '@objc' enum must declare an integer raw type + msg: "'@objc' enum must declare an integer raw type" - id: objc_enum_raw_type_not_integer - msg: >- - '@objc' enum raw type %0 is not an integer type + msg: "'@objc' enum raw type %0 is not an integer type" - id: enum_non_integer_raw_value_auto_increment - msg: >- - enum case must declare a raw value when the preceding raw value is not an - integer + msg: "enum case must declare a raw value when the preceding raw value is not an integer" - id: enum_non_integer_convertible_raw_type_no_value - msg: >- - enum cases require explicit raw values when the raw type is not - expressible by integer or string literal + msg: "enum cases require explicit raw values when the raw type is not expressible by integer or string literal" - id: enum_raw_value_not_unique - msg: >- - raw value for enum case is not unique + msg: "raw value for enum case is not unique" - id: enum_raw_value_magic_literal - msg: >- - use of '%0' literal as raw value for enum case is not supported + msg: "use of '%0' literal as raw value for enum case is not supported" - id: enum_raw_value_used_here - msg: >- - raw value previously used here + msg: "raw value previously used here" - id: enum_raw_value_incrementing_from_here - msg: >- - raw value auto-incremented from here + msg: "raw value auto-incremented from here" - id: enum_raw_value_incrementing_from_zero - msg: >- - raw value implicitly auto-incremented from zero + msg: "raw value implicitly auto-incremented from zero" - id: construct_raw_representable_from_unwrapped_value - msg: >- - construct %0 from unwrapped %1 value + msg: "construct %0 from unwrapped %1 value" - id: decl_from_hidden_module - msg: >- - cannot use %0 %1 %select{here|as property wrapper here|in an extension - with public or '@usableFromInline' members|in an extension with conditional - conformances}2; %select{%3 has been imported as implementation-only|it - is an SPI imported from %3|it is SPI}4 + msg: "cannot use %0 %1 %select{here|as property wrapper here|in an extension with public or '@usableFromInline' members|in an extension with conditional conformances}2; %select{%3 has been imported as implementation-only|it is an SPI imported from %3|it is SPI}4" + +- id: decl_from_hidden_module_warn + msg: "cannot use %0 %1 %select{in SPI|as property wrapper in SPI|in an extension with public or '@usableFromInline' members|in an extension with conditional conformances}2; %select{%3 has been imported as implementation-only}4" - id: conformance_from_implementation_only_module - msg: >- - cannot use conformance of %0 to %1 %select{here|as property wrapper - here|in an extension with public or '@usableFromInline' members|in - an extension with conditional conformances}2; - %3 has been imported as implementation-only + msg: "cannot use conformance of %0 to %1 %select{here|as property wrapper here|in an extension with public or '@usableFromInline' members|in an extension with conditional conformances}2; %3 has been imported as implementation-only" - id: assoc_conformance_from_implementation_only_module - msg: >- - cannot use conformance of %0 to %1 in associated type %3 (inferred as - %4); %2 has been imported as implementation-only + msg: "cannot use conformance of %0 to %1 in associated type %3 (inferred as %4); %2 has been imported as implementation-only" - id: unexportable_clang_function_type - msg: >- - cannot export the underlying C type of the function type %0; it may use - anonymous types or types defined outside of a module + msg: "cannot export the underlying C type of the function type %0; it may use anonymous types or types defined outside of a module" - id: warn_implementation_only_conflict - msg: >- - %0 inconsistently imported as implementation-only + msg: "%0 inconsistently imported as implementation-only" - id: implementation_only_conflict_here - msg: >- - imported as implementation-only here + msg: "imported as implementation-only here" - id: implementation_only_decl_non_override - msg: >- - '@_implementationOnly' can only be used on overrides + msg: "'@_implementationOnly' can only be used on overrides" - id: implementation_only_override_changed_type - msg: >- - '@_implementationOnly' override must have the same type as the - declaration it overrides (%0) + msg: "'@_implementationOnly' override must have the same type as the declaration it overrides (%0)" - id: implementation_only_override_without_attr - msg: >- - override of '@_implementationOnly' %0 should also be declared - '@_implementationOnly' + msg: "override of '@_implementationOnly' %0 should also be declared '@_implementationOnly'" - id: implementation_only_override_import_without_attr - msg: >- - override of %0 imported as implementation-only must be declared - '@_implementationOnly' + msg: "override of %0 imported as implementation-only must be declared '@_implementationOnly'" - id: cannot_synthesize_init_in_extension_of_nonfinal - msg: >- - implementation of %0 for non-final class cannot be automatically - synthesized in extension because initializer requirement %1 can only be - satisfied by a 'required' initializer in the class definition + msg: "implementation of %0 for non-final class cannot be automatically synthesized in extension because initializer requirement %1 can only be satisfied by a 'required' initializer in the class definition" - id: cannot_synthesize_in_crossfile_extension - msg: >- - implementation of %0 cannot be automatically synthesized in an extension - in a different file to the type + msg: "extension outside of file declaring %0 %1 prevents automatic synthesis of %2 for protocol %3" - id: broken_additive_arithmetic_requirement - msg: >- - AdditiveArithmetic protocol is broken: unexpected requirement + msg: "AdditiveArithmetic protocol is broken: unexpected requirement" - id: broken_case_iterable_requirement - msg: >- - CaseIterable protocol is broken: unexpected requirement + msg: "CaseIterable protocol is broken: unexpected requirement" - id: broken_raw_representable_requirement - msg: >- - RawRepresentable protocol is broken: unexpected requirement + msg: "RawRepresentable protocol is broken: unexpected requirement" - id: broken_comparable_requirement - msg: >- - Comparable protocol is broken: unexpected requirement + msg: "Comparable protocol is broken: unexpected requirement" - id: broken_equatable_requirement - msg: >- - Equatable protocol is broken: unexpected requirement + msg: "Equatable protocol is broken: unexpected requirement" - id: broken_hashable_requirement - msg: >- - Hashable protocol is broken: unexpected requirement + msg: "Hashable protocol is broken: unexpected requirement" - id: broken_hashable_no_hasher - msg: >- - Hashable protocol is broken: Hasher type not found + msg: "Hashable protocol is broken: Hasher type not found" - id: broken_errortype_requirement - msg: >- - Error protocol is broken: unexpected requirement + msg: "Error protocol is broken: unexpected requirement" - id: broken_int_hashable_conformance - msg: >- - Int type is broken: does not conform to Hashable + msg: "Int type is broken: does not conform to Hashable" - id: broken_int_integer_literal_convertible_conformance - msg: >- - Int type is broken: does not conform to ExpressibleByIntegerLiteral + msg: "Int type is broken: does not conform to ExpressibleByIntegerLiteral" - id: no_less_than_overload_for_int - msg: >- - no overload of '<' for Int + msg: "no overload of '<' for Int" - id: no_equal_overload_for_int - msg: >- - no overload of '==' for Int + msg: "no overload of '==' for Int" - id: broken_coding_key_requirement - msg: >- - CodingKey protocol is broken: unexpected requirement + msg: "CodingKey protocol is broken: unexpected requirement" - id: broken_encodable_requirement - msg: >- - Encodable protocol is broken: unexpected requirement + msg: "Encodable protocol is broken: unexpected requirement" - id: broken_decodable_requirement - msg: >- - Decodable protocol is broken: unexpected requirement + msg: "Decodable protocol is broken: unexpected requirement" - id: broken_differentiable_requirement - msg: >- - Differentiable protocol is broken: unexpected requirement + msg: "Differentiable protocol is broken: unexpected requirement" - id: differentiable_nondiff_type_implicit_noderivative_fixit - msg: >- - stored property %0 has no derivative because %1 does not conform to - 'Differentiable'; add an explicit '@noDerivative' attribute%select{|, - or conform %2 to 'AdditiveArithmetic'}3 + msg: "stored property %0 has no derivative because %1 does not conform to 'Differentiable'; add an explicit '@noDerivative' attribute%select{|, or conform %2 to 'AdditiveArithmetic'}3" - id: differentiable_immutable_wrapper_implicit_noderivative_fixit - msg: >- - synthesis of the 'Differentiable.move(along:)' requirement for %1 - requires 'wrappedValue' in property wrapper %0 to be mutable; - add an explicit '@noDerivative' attribute%select{|, - or conform %1 to 'AdditiveArithmetic'}2 + msg: "synthesis of the 'Differentiable.move(along:)' requirement for %1 requires 'wrappedValue' in property wrapper %0 to be mutable; add an explicit '@noDerivative' attribute%select{|, or conform %1 to 'AdditiveArithmetic'}2" - id: differentiable_let_property_implicit_noderivative_fixit - msg: >- - synthesis of the 'Differentiable.move(along:)' requirement for %0 - requires all stored properties not marked with `@noDerivative` - to be mutable; use 'var' instead, or add an explicit - '@noDerivative' attribute%select{|, or conform %0 to 'AdditiveArithmetic'}1 + msg: "synthesis of the 'Differentiable.move(along:)' requirement for %0 requires all stored properties not marked with `@noDerivative` to be mutable; use 'var' instead, or add an explicit '@noDerivative' attribute%select{|, or conform %0 to 'AdditiveArithmetic'}1" - id: codable_extraneous_codingkey_case_here - msg: >- - CodingKey case %0 does not match any stored properties + msg: "CodingKey case %0 does not match any stored properties" - id: codable_non_conforming_property_here - msg: >- - cannot automatically synthesize %0 because %1 does not conform to %0 + msg: "cannot automatically synthesize %0 because %1 does not conform to %0" - id: codable_non_decoded_property_here - msg: >- - cannot automatically synthesize %0 because %1 does not have a matching - CodingKey and does not have a default value + msg: "cannot automatically synthesize %0 because %1 does not have a matching CodingKey and does not have a default value" - id: codable_codingkeys_type_is_not_an_enum_here - msg: >- - cannot automatically synthesize %0 because 'CodingKeys' is not an enum + msg: "cannot automatically synthesize %0 because 'CodingKeys' is not an enum" - id: codable_codingkeys_type_does_not_conform_here - msg: >- - cannot automatically synthesize %0 because 'CodingKeys' does not conform - to CodingKey + msg: "cannot automatically synthesize %0 because 'CodingKeys' does not conform to CodingKey" - id: decodable_no_super_init_here - msg: >- - cannot automatically synthesize %0 because superclass does not have a - callable %1 + msg: "cannot automatically synthesize %0 because superclass does not have a callable %1" - id: decodable_super_init_not_designated_here - msg: >- - cannot automatically synthesize %0 because implementation would need to - call %1, which is not designated + msg: "cannot automatically synthesize %0 because implementation would need to call %1, which is not designated" - id: decodable_inaccessible_super_init_here - msg: >- - cannot automatically synthesize %0 because implementation would need to - call %1, which is inaccessible due to - '%select{private|fileprivate|internal|%error|%error}2' protection level + msg: "cannot automatically synthesize %0 because implementation would need to call %1, which is inaccessible due to '%select{private|fileprivate|internal|%error|%error}2' protection level" - id: decodable_super_init_is_failable_here - msg: >- - cannot automatically synthesize %0 because implementation would need to - call %1, which is failable + msg: "cannot automatically synthesize %0 because implementation would need to call %1, which is failable" - id: decodable_suggest_overriding_init_here - msg: >- - did you mean to override 'init(from:)'? + msg: "did you mean to override 'init(from:)'?" - id: codable_suggest_overriding_init_here - msg: >- - did you mean to override 'init(from:)' and 'encode(to:)'? + msg: "did you mean to override 'init(from:)' and 'encode(to:)'?" - id: decodable_property_will_not_be_decoded - msg: >- - immutable property will not be decoded because it is declared with an - initial value which cannot be overwritten + msg: "immutable property will not be decoded because it is declared with an initial value which cannot be overwritten" - id: decodable_property_init_or_codingkeys_implicit - msg: >- - set the initial value via the initializer or explicitly define a - CodingKeys enum %select{including|without}0 a %1 - case to silence this warning + msg: "set the initial value via the initializer or explicitly define a CodingKeys enum %select{including|without}0 a %1 case to silence this warning" - id: decodable_property_init_or_codingkeys_explicit - msg: >- - set the initial value via the initializer or remove the %0 case from the - CodingKeys enum to silence this warning + msg: "set the initial value via the initializer or remove the %0 case from the CodingKeys enum to silence this warning" - id: decodable_make_property_mutable - msg: >- - make the property mutable instead + msg: "make the property mutable instead" - id: missing_member_type_conformance_prevents_synthesis - msg: >- - %select{associated value|stored property}0 type %1 does not conform to - protocol %2, preventing synthesized conformance of %3 to %2 + msg: "%select{associated value|stored property}0 type %1 does not conform to protocol %2, preventing synthesized conformance of %3 to %2" - id: automatic_protocol_synthesis_unsupported - msg: >- - automatic synthesis of '%0' is not supported for %select{classes|structs}1 + msg: "automatic synthesis of '%0' is not supported for %select{classes|structs}1" - id: comparable_synthesis_raw_value_not_allowed - msg: >- - enum declares raw type %0, preventing synthesized conformance of %1 to %2 + msg: "enum declares raw type %0, preventing synthesized conformance of %1 to %2" - id: dynamic_self_non_method - msg: >- - %select{global|local}0 function cannot return 'Self' + msg: "%select{global|local}0 function cannot return 'Self'" - id: dynamic_self_invalid - msg: >- - covariant 'Self' can only appear as the type of a property, subscript or - method result; did you mean '%0'? + msg: "covariant 'Self' can only appear as the type of a property, subscript or method result; did you mean '%0'?" - id: dynamic_self_in_mutable_property - msg: >- - mutable property cannot have covariant 'Self' type + msg: "mutable property cannot have covariant 'Self' type" - id: dynamic_self_in_stored_property - msg: >- - stored property cannot have covariant 'Self' type + msg: "stored property cannot have covariant 'Self' type" - id: dynamic_self_in_mutable_subscript - msg: >- - mutable subscript cannot have covariant 'Self' type + msg: "mutable subscript cannot have covariant 'Self' type" - id: dynamic_self_invalid_property - msg: >- - covariant 'Self' can only appear at the top level of property type + msg: "covariant 'Self' can only appear at the top level of property type" - id: dynamic_self_invalid_subscript - msg: >- - covariant 'Self' can only appear at the top level of subscript element - type + msg: "covariant 'Self' can only appear at the top level of subscript element type" - id: dynamic_self_invalid_method - msg: >- - covariant 'Self' can only appear at the top level of method result type + msg: "covariant 'Self' can only appear at the top level of method result type" - id: dynamic_self_stored_property_init - msg: >- - covariant 'Self' type cannot be referenced from a stored property - initializer + msg: "covariant 'Self' type cannot be referenced from a stored property initializer" - id: dynamic_self_default_arg - msg: >- - covariant 'Self' type cannot be referenced from a default argument - expression + msg: "covariant 'Self' type cannot be referenced from a default argument expression" - id: attr_only_one_decl_kind - msg: >- - %0 may only be used on '%1' declarations + msg: "%0 may only be used on '%1' declarations" - id: attr_not_on_variadic_parameters - msg: >- - '%0' must not be used on variadic parameters + msg: "'%0' must not be used on variadic parameters" - id: attr_not_on_subscript_parameters - msg: >- - '%0' must not be used on subscript parameters + msg: "'%0' must not be used on subscript parameters" - id: attr_ambiguous_reference_to_decl - msg: >- - ambiguous reference to %0 in '@%1' attribute + msg: "ambiguous reference to %0 in '@%1' attribute" - id: override_final - msg: >- - %0 overrides a 'final' %1 + msg: "%0 overrides a 'final' %1" - id: override_static - msg: >- - cannot override %0 + msg: "cannot override %0" - id: member_cannot_be_final - msg: >- - only classes and class members may be marked with 'final' + msg: "only classes and class members may be marked with 'final'" - id: final_not_allowed_here - msg: >- - 'final' may only be applied to classes, properties, methods, and subscripts + msg: "'final' may only be applied to classes, properties, methods, and subscripts" - id: final_not_on_accessors - msg: >- - 'final' cannot be applied to accessors, it must be put on the - %select{var|let|subscript}0 + msg: "'final' cannot be applied to accessors, it must be put on the %select{var|let|subscript}0" - id: override_rethrows_with_non_rethrows - msg: >- - override of 'rethrows' %select{method|initializer}0 should also be - 'rethrows' + msg: "override of 'rethrows' %select{method|initializer}0 should also be 'rethrows'" - id: rethrows_without_throwing_parameter - msg: >- - 'rethrows' function must take a throwing function argument + msg: "'rethrows' function must take a throwing function argument" - id: autoclosure_function_type - msg: >- - @autoclosure attribute only applies to function types + msg: "@autoclosure attribute only applies to function types" - id: invalid_autoclosure_and_convention_attributes - msg: >- - '@convention(%0)' attribute is not allowed on '@autoclosure' types + msg: "'@convention(%0)' attribute is not allowed on '@autoclosure' types" - id: autoclosure_function_input_nonunit - msg: >- - argument type of @autoclosure parameter must be '()' + msg: "argument type of @autoclosure parameter must be '()'" - id: escaping_non_function_parameter - msg: >- - @escaping attribute may only be used in function parameter position + msg: "@escaping attribute may only be used in function parameter position" - id: escaping_optional_type_argument - msg: >- - closure is already escaping in optional type argument + msg: "closure is already escaping in optional type argument" - id: non_ephemeral_non_pointer_type - msg: >- - @_nonEphemeral attribute only applies to pointer types + msg: "@_nonEphemeral attribute only applies to pointer types" - id: attr_NSManaged_not_instance_member - msg: >- - @NSManaged only allowed on an instance property or method + msg: "@NSManaged only allowed on an instance property or method" - id: attr_NSManaged_not_stored - msg: >- - @NSManaged not allowed on %select{computed|observing|addressed}0 properties + msg: "@NSManaged not allowed on %select{computed|observing|addressed}0 properties" - id: attr_NSManaged_let_property - msg: >- - @NSManaged not allowed on a 'let' property + msg: "@NSManaged not allowed on a 'let' property" - id: attr_NSManaged_initial_value - msg: >- - @NSManaged property cannot have an initial value + msg: "@NSManaged property cannot have an initial value" - id: attr_NSManaged_NSCopying - msg: >- - @NSManaged property cannot also be marked @NSCopying + msg: "@NSManaged property cannot also be marked @NSCopying" - id: attr_NSManaged_method_body - msg: >- - @NSManaged method cannot have a body; it must be provided at runtime + msg: "@NSManaged method cannot have a body; it must be provided at runtime" - id: nscopying_only_on_class_properties - msg: >- - @NSCopying may only be used on properties in classes + msg: "@NSCopying may only be used on properties in classes" - id: nscopying_only_mutable - msg: >- - @NSCopying requires property to be mutable + msg: "@NSCopying requires property to be mutable" - id: nscopying_only_stored_property - msg: >- - @NSCopying is only valid on stored properties + msg: "@NSCopying is only valid on stored properties" - id: nscopying_doesnt_conform - msg: >- - @NSCopying is only valid with types that conform to the NSCopying protocol + msg: "@NSCopying is only valid with types that conform to the NSCopying protocol" - id: attr_ApplicationMain_not_ApplicationDelegate - msg: >- - %select{'UIApplicationMain'|'NSApplicationMain'|'main'}0 class must - conform to the %select{'UIApplicationDelegate'|'NSApplicationDelegate'}0 - protocol + msg: "%select{'UIApplicationMain'|'NSApplicationMain'|'main'}0 class must conform to the %select{'UIApplicationDelegate'|'NSApplicationDelegate'}0 protocol" - id: attr_generic_ApplicationMain_not_supported - msg: >- - generic %select{'UIApplicationMain'|'NSApplicationMain'|'main'}0 - %select{classes|classes|types}0 are not supported + msg: "generic %select{'UIApplicationMain'|'NSApplicationMain'|'main'}0 %select{classes|classes|types}0 are not supported" - id: attr_ApplicationMain_multiple - msg: >- - %select{'UIApplicationMain'|'NSApplicationMain'|'main'}0 attribute can - only apply to one %select{class|class|type}0 in a module + msg: "%select{'UIApplicationMain'|'NSApplicationMain'|'main'}0 attribute can only apply to one %select{class|class|type}0 in a module" - id: attr_ApplicationMain_with_script - msg: >- - %select{'UIApplicationMain'|'NSApplicationMain'|'main'}0 attribute cannot - be used in a module that contains top-level code + msg: "%select{'UIApplicationMain'|'NSApplicationMain'|'main'}0 attribute cannot be used in a module that contains top-level code" - id: attr_ApplicationMain_script_here - msg: >- - top-level code defined in this source file + msg: "top-level code defined in this source file" - id: attr_MainType_without_main - msg: >- - %0 is annotated with @main and must provide a main static function of - type () -> Void or () throws -> Void. + msg: "%0 is annotated with @main and must provide a main static function of type () -> Void or () throws -> Void." - id: lazy_not_on_let - msg: >- - 'lazy' cannot be used on a let + msg: "'lazy' cannot be used on a let" - id: lazy_not_on_computed - msg: >- - 'lazy' must not be used on a computed property + msg: "'lazy' must not be used on a computed property" - id: lazy_on_already_lazy_global - msg: >- - 'lazy' must not be used on an already-lazy global + msg: "'lazy' must not be used on an already-lazy global" - id: lazy_not_in_protocol - msg: >- - 'lazy' isn't allowed on a protocol requirement + msg: "'lazy' isn't allowed on a protocol requirement" - id: lazy_requires_initializer - msg: >- - lazy properties must have an initializer + msg: "lazy properties must have an initializer" - id: lazy_requires_single_var - msg: >- - 'lazy' cannot destructure an initializer + msg: "'lazy' cannot destructure an initializer" - id: lazy_must_be_property - msg: >- - lazy is only valid for members of a struct or class + msg: "lazy is only valid for members of a struct or class" - id: lazy_not_strong - msg: >- - lazy properties cannot be %0 + msg: "lazy properties cannot be %0" + +- id: lazy_var_storage_access + msg: "access to the underlying storage of a lazy property is not allowed" - id: attr_for_debugger_support_only - msg: >- - @LLDBDebuggerSupport may only be used when debugger support is on + msg: "@LLDBDebuggerSupport may only be used when debugger support is on" - id: implements_attr_protocol_lacks_member - msg: >- - protocol %0 has no member %1 + msg: "protocol %0 has no member %1" - id: implements_attr_non_protocol_type - msg: >- - non-protocol type in @_implements attribute + msg: "non-protocol type in @_implements attribute" - id: implements_attr_protocol_not_conformed_to - msg: >- - containing type %0 does not conform to protocol %1 + msg: "containing type %0 does not conform to protocol %1" - id: differentiable_attr_no_vjp_or_jvp_when_linear - msg: >- - cannot specify 'vjp:' or 'jvp:' for linear functions; use '@transpose' - attribute for transpose registration instead + msg: "cannot specify 'vjp:' or 'jvp:' for linear functions; use '@transpose' attribute for transpose registration instead" - id: differentiable_attr_overload_not_found - msg: >- - %0 does not have expected type %1 + msg: "%0 does not have expected type %1" - id: differentiable_attr_duplicate - msg: >- - duplicate '@differentiable' attribute with same parameters + msg: "duplicate '@differentiable' attribute with same parameters" - id: differentiable_attr_duplicate_note - msg: >- - other attribute declared here + msg: "other attribute declared here" - id: differentiable_attr_function_not_same_type_context - msg: >- - %0 is not defined in the current type context + msg: "%0 is not defined in the current type context" - id: differentiable_attr_derivative_not_function - msg: >- - registered derivative %0 must be a 'func' declaration + msg: "registered derivative %0 must be a 'func' declaration" - id: differentiable_attr_class_derivative_not_final - msg: >- - class member derivative must be final + msg: "class member derivative must be final" - id: differentiable_attr_invalid_access - msg: >- - derivative function %0 is required to either be public or - '@usableFromInline' because the original function %1 is public or - '@usableFromInline' + msg: "derivative function %0 is required to either be public or '@usableFromInline' because the original function %1 is public or '@usableFromInline'" - id: differentiable_attr_protocol_req_where_clause - msg: >- - '@differentiable' attribute on protocol requirement cannot specify - 'where' clause + msg: "'@differentiable' attribute on protocol requirement cannot specify 'where' clause" - id: differentiable_attr_class_member_dynamic_self_result_unsupported - msg: >- - '@differentiable' attribute cannot be declared on class members returning - 'Self' + msg: "'@differentiable' attribute cannot be declared on class members returning 'Self'" - id: differentiable_attr_nonfinal_class_init_unsupported - msg: >- - '@differentiable' attribute cannot be declared on 'init' in a non-final - class; consider making %0 final + msg: "'@differentiable' attribute cannot be declared on 'init' in a non-final class; consider making %0 final" - id: differentiable_attr_empty_where_clause - msg: >- - empty 'where' clause in '@differentiable' attribute + msg: "empty 'where' clause in '@differentiable' attribute" - id: differentiable_attr_where_clause_for_nongeneric_original - msg: >- - 'where' clause is valid only when original function is generic %0 + msg: "'where' clause is valid only when original function is generic %0" - id: differentiable_attr_layout_req_unsupported - msg: >- - '@differentiable' attribute does not yet support layout requirements + msg: "'@differentiable' attribute does not yet support layout requirements" - id: overriding_decl_missing_differentiable_attr - msg: >- - overriding declaration is missing attribute '%0' + msg: "overriding declaration is missing attribute '%0'" - id: protocol_witness_missing_differentiable_attr - msg: >- - candidate is missing attribute '%0' + msg: "candidate is missing attribute '%0'" - id: protocol_witness_missing_differentiable_attr_nonpublic_other_file - msg: >- - non-public %1 %2 must have explicit '%0' attribute to satisfy requirement - %3 %4 (in protocol %6) because it is declared in a different file than the - conformance of %5 to %6 + msg: "non-public %1 %2 must have explicit '%0' attribute to satisfy requirement %3 %4 (in protocol %6) because it is declared in a different file than the conformance of %5 to %6" - id: derivative_attr_expected_result_tuple - msg: >- - '@derivative(of:)' attribute requires function to return a two-element - tuple; first element must have label 'value:' and second element - must have label 'pullback:' or 'differential:' + msg: "'@derivative(of:)' attribute requires function to return a two-element tuple; first element must have label 'value:' and second element must have label 'pullback:' or 'differential:'" - id: derivative_attr_invalid_result_tuple_value_label - msg: >- - '@derivative(of:)' attribute requires function to return a two-element - tuple; first element must have label 'value:' + msg: "'@derivative(of:)' attribute requires function to return a two-element tuple; first element must have label 'value:'" - id: derivative_attr_invalid_result_tuple_func_label - msg: >- - '@derivative(of:)' attribute requires function to return a two-element - tuple; second element must have label 'pullback:' or 'differential:' + msg: "'@derivative(of:)' attribute requires function to return a two-element tuple; second element must have label 'pullback:' or 'differential:'" - id: derivative_attr_result_value_not_differentiable - msg: >- - '@derivative(of:)' attribute requires function to return a two-element - tuple; first element type %0 must conform to 'Differentiable' + msg: "'@derivative(of:)' attribute requires function to return a two-element tuple; first element type %0 must conform to 'Differentiable'" - id: derivative_attr_result_func_type_mismatch - msg: >- - function result's %0 type does not match %1 + msg: "function result's %0 type does not match %1" - id: derivative_attr_result_func_type_mismatch_note - msg: >- - %0 does not have expected type %1 + msg: "%0 does not have expected type %1" - id: derivative_attr_result_func_original_note - msg: >- - %0 defined here + msg: "%0 defined here" - id: derivative_attr_not_in_same_file_as_original - msg: >- - derivative not in the same file as the original function + msg: "derivative not in the same file as the original function" - id: derivative_attr_original_stored_property_unsupported - msg: >- - cannot register derivative for stored property %0 + msg: "cannot register derivative for stored property %0" - id: derivative_attr_class_member_dynamic_self_result_unsupported - msg: >- - cannot register derivative for class member %0 returning 'Self' + msg: "cannot register derivative for class member %0 returning 'Self'" - id: derivative_attr_nonfinal_class_init_unsupported - msg: >- - cannot register derivative for 'init' in a non-final class; consider - making %0 final - + msg: "cannot register derivative for 'init' in a non-final class; consider making %0 final" + +- id: derivative_attr_unsupported_accessor_kind + msg: "cannot register derivative for %0" + - id: derivative_attr_class_setter_unsupported - msg: >- - cannot yet register derivative for class property or subscript setters + msg: "cannot yet register derivative for class property or subscript setters" + +- id: derivative_attr_protocol_requirement_unsupported + msg: "cannot yet register derivative default implementation for protocol requirements" - id: derivative_attr_original_already_has_derivative - msg: >- - a derivative already exists for %0 + msg: "a derivative already exists for %0" - id: derivative_attr_duplicate_note - msg: >- - other attribute declared here + msg: "other attribute declared here" - id: derivative_attr_access_level_mismatch - msg: >- - derivative function must have same access level as original function; - derivative function %2 is %select{private|fileprivate|internal|public|open}3, - but original function %0 is %select{private|fileprivate|internal|public|open}1 + msg: "derivative function must have same access level as original function; derivative function %2 is %select{private|fileprivate|internal|public|open}3, but original function %0 is %select{private|fileprivate|internal|public|open}1" - id: derivative_attr_fix_access - msg: >- - mark the derivative function as - '%select{private|fileprivate|internal|@usableFromInline|@usableFromInline}0' - to match the original function + msg: "mark the derivative function as '%select{private|fileprivate|internal|@usableFromInline|@usableFromInline}0' to match the original function" - id: transpose_attr_invalid_linearity_parameter_or_result - msg: >- - cannot transpose with respect to original %select{result|parameter}1 '%0' - that does not conform to 'Differentiable' and satisfy '%0 == %0.TangentVector' + msg: "cannot transpose with respect to original %select{result|parameter}1 '%0' that does not conform to 'Differentiable' and satisfy '%0 == %0.TangentVector'" - id: transpose_attr_overload_not_found - msg: >- - could not find function %0 with expected type %1 + msg: "could not find function %0 with expected type %1" - id: transpose_attr_cannot_use_named_wrt_params - msg: >- - cannot use named 'wrt' parameters in '@transpose(of:)' attribute, found %0 + msg: "cannot use named 'wrt' parameters in '@transpose(of:)' attribute, found %0" - id: transpose_attr_wrt_self_must_be_static - msg: >- - the transpose of an instance method must be a 'static' method in the same - type when 'self' is a linearity parameter + msg: "the transpose of an instance method must be a 'static' method in the same type when 'self' is a linearity parameter" - id: transpose_attr_wrt_self_self_type_mismatch_note - msg: >- - the transpose is declared in %0 but the original function is declared in %1 + msg: "the transpose is declared in %0 but the original function is declared in %1" + +- id: autodiff_attr_original_decl_ambiguous + msg: "referenced declaration %0 is ambiguous" + +- id: autodiff_attr_original_decl_ambiguous_candidate + msg: "candidate %0 found here" + +- id: autodiff_attr_original_decl_none_valid + msg: "referenced declaration %0 could not be resolved" - id: autodiff_attr_original_decl_invalid_kind - msg: >- - %0 is not a 'func', 'init', 'subscript', or 'var' computed property - declaration + msg: "candidate %0 is not a 'func', 'init', 'subscript', or 'var' computed property declaration" + +- id: autodiff_attr_original_decl_missing_accessor + msg: "candidate %0 does not have a %1" + +- id: autodiff_attr_original_decl_type_mismatch + msg: "candidate %0 does not have %select{expected type|type equal to or less constrained than}2 %1" - id: autodiff_attr_original_decl_not_same_type_context - msg: >- - %0 is not defined in the current type context + msg: "candidate %0 is not defined in the current type context" - id: autodiff_attr_original_void_result - msg: >- - cannot differentiate void function %0 + msg: "cannot differentiate void function %0" - id: autodiff_attr_original_multiple_semantic_results - msg: >- - cannot differentiate functions with both an 'inout' parameter and a result + msg: "cannot differentiate functions with both an 'inout' parameter and a result" - id: autodiff_attr_result_not_differentiable - msg: >- - can only differentiate functions with results that conform to - 'Differentiable', but %0 does not conform to 'Differentiable' + msg: "can only differentiate functions with results that conform to 'Differentiable', but %0 does not conform to 'Differentiable'" + +- id: autodiff_attr_opaque_result_type_unsupported + msg: "cannot differentiate functions returning opaque result types" - id: diff_function_no_parameters - msg: >- - %0 has no parameters to differentiate with respect to + msg: "%0 has no parameters to differentiate with respect to" - id: diff_params_clause_param_name_unknown - msg: >- - unknown parameter name %0 + msg: "unknown parameter name %0" - id: diff_params_clause_self_instance_method_only - msg: >- - 'self' parameter is only applicable to instance methods + msg: "'self' parameter is only applicable to instance methods" - id: diff_params_clause_self_must_be_first - msg: >- - 'self' parameter must come first in the parameter list + msg: "'self' parameter must come first in the parameter list" - id: diff_params_clause_params_not_original_order - msg: >- - parameters must be specified in original order + msg: "parameters must be specified in original order" - id: diff_params_clause_param_index_out_of_range - msg: >- - parameter index is larger than total number of parameters + msg: "parameter index is larger than total number of parameters" - id: diff_params_clause_no_inferred_parameters - msg: >- - no differentiation parameters could be inferred; must differentiate with - respect to at least one parameter conforming to 'Differentiable' + msg: "no differentiation parameters could be inferred; must differentiate with respect to at least one parameter conforming to 'Differentiable'" - id: diff_params_clause_cannot_diff_wrt_inout_parameter - msg: >- - cannot differentiate with respect to 'inout' parameter (%0) + msg: "cannot differentiate with respect to 'inout' parameter (%0)" - id: diff_params_clause_param_not_differentiable - msg: >- - can only differentiate with respect to parameters that conform to - 'Differentiable', but %0 does not conform to 'Differentiable' + msg: "can only differentiate with respect to parameters that conform to 'Differentiable', but %0 does not conform to 'Differentiable'" - id: found_candidate - msg: >- - found this candidate + msg: "found this candidate" - id: found_candidate_type - msg: >- - found candidate with type %0 + msg: "found candidate with type %0" - id: no_MaxBuiltinFloatType_found - msg: >- - standard library error: _MaxBuiltinFloatType is not properly defined + msg: "standard library error: _MaxBuiltinFloatType is not properly defined" - id: no_member_of_module - msg: >- - module %0 has no member named %1 + msg: "module %0 has no member named %1" - id: super_with_no_base_class - msg: >- - 'super' members cannot be referenced in a root class + msg: "'super' members cannot be referenced in a root class" - id: bad_init_ref_base - msg: >- - 'init' can only refer to the initializers of 'self'%select{| or 'super'}0 + msg: "'init' can only refer to the initializers of 'self'%select{| or 'super'}0" - id: init_delegation_outside_initializer - msg: >- - initializer delegation can only occur within an initializer + msg: "initializer delegation can only occur within an initializer" - id: init_delegates_and_chains - msg: >- - initializer cannot both delegate ('self.init') and chain to a superclass - initializer ('super.init') + msg: "initializer cannot both delegate ('self.init') and chain to a superclass initializer ('super.init')" - id: init_delegation_or_chain - msg: >- - previous %select{delegation|chaining}0 call is here + msg: "previous %select{delegation|chaining}0 call is here" - id: delegating_convenience_super_init - msg: >- - convenience initializer for %0 must delegate (with 'self.init') rather - than chaining to a superclass initializer (with 'super.init') + msg: "convenience initializer for %0 must delegate (with 'self.init') rather than chaining to a superclass initializer (with 'super.init')" - id: delegating_designated_init - msg: >- - designated initializer for %0 cannot delegate (with 'self.init'); did you - mean this to be a convenience initializer? + msg: "designated initializer for %0 cannot delegate (with 'self.init'); did you mean this to be a convenience initializer?" - id: delegating_designated_init_in_extension - msg: >- - designated initializer for %0 cannot delegate (with 'self.init') + msg: "designated initializer for %0 cannot delegate (with 'self.init')" - id: delegation_here - msg: >- - delegation occurs here + msg: "delegation occurs here" - id: chain_convenience_init - msg: >- - must call a designated initializer of the superclass %0 + msg: "must call a designated initializer of the superclass %0" - id: delegate_chain_nonoptional_to_optional - msg: >- - a non-failable initializer cannot %select{delegate|chain}0 to failable - initializer %1 written with 'init?' + msg: "a non-failable initializer cannot %select{delegate|chain}0 to failable initializer %1 written with 'init?'" - id: init_force_unwrap - msg: >- - force potentially-failing result with '!' + msg: "force potentially-failing result with '!'" - id: init_propagate_failure - msg: >- - propagate the failure with 'init?' + msg: "propagate the failure with 'init?'" - id: delegate_chain_nonoptional_to_optional_try - msg: >- - a non-failable initializer cannot use 'try?' to %select{delegate|chain}0 - to another initializer + msg: "a non-failable initializer cannot use 'try?' to %select{delegate|chain}0 to another initializer" - id: init_delegate_force_try - msg: >- - force potentially-failing result with 'try!' + msg: "force potentially-failing result with 'try!'" - id: init_delegation_nested - msg: >- - %select{initializer delegation ('self.init')|initializer chaining - ('super.init')}0 cannot be nested in another %select{expression|statement}1 + msg: "%select{initializer delegation ('self.init')|initializer chaining ('super.init')}0 cannot be nested in another %select{expression|statement}1" - id: convenience_init_here - msg: >- - convenience initializer is declared here + msg: "convenience initializer is declared here" - id: designated_init_in_extension - msg: >- - designated initializer cannot be declared in an extension of %0; did you - mean this to be a convenience initializer? + msg: "designated initializer cannot be declared in an extension of %0; did you mean this to be a convenience initializer?" - id: cfclass_designated_init_in_extension - msg: >- - designated initializer cannot be declared in an extension of %0 + msg: "designated initializer cannot be declared in an extension of %0" - id: enumstruct_convenience_init - msg: >- - delegating initializers in %0 are not marked with 'convenience' + msg: "delegating initializers in %0 are not marked with 'convenience'" - id: nonclass_convenience_init - msg: >- - convenience initializer not allowed in non-class type %0 + msg: "convenience initializer not allowed in non-class type %0" - id: cfclass_convenience_init - msg: >- - convenience initializers are not supported in extensions of CF types + msg: "convenience initializers are not supported in extensions of CF types" - id: dynamic_construct_class - msg: >- - constructing an object of class type %0 with a metatype value must use a - 'required' initializer + msg: "constructing an object of class type %0 with a metatype value must use a 'required' initializer" - id: note_nonrequired_initializer - msg: >- - selected %select{non-required|implicit}0 initializer %1 + msg: "selected %select{non-required|implicit}0 initializer %1" - id: construct_protocol_value - msg: >- - value of type %0 is a protocol; it cannot be instantiated + msg: "value of type %0 is a protocol; it cannot be instantiated" - id: construct_protocol_by_name - msg: >- - protocol type %0 cannot be instantiated + msg: "protocol type %0 cannot be instantiated" - id: unknown_binop - msg: >- - operator is not a known binary operator + msg: "operator is not a known binary operator" - id: non_associative_adjacent_operators - msg: >- - adjacent operators are in non-associative precedence group %0 + msg: "adjacent operators are in non-associative precedence group %0" - id: unordered_adjacent_operators - msg: >- - adjacent operators are in unordered precedence groups %0 and %1 + msg: "adjacent operators are in unordered precedence groups %0 and %1" - id: missing_builtin_precedence_group - msg: >- - broken standard library: missing builtin precedence group %0 + msg: "broken standard library: missing builtin precedence group %0" - id: try_rhs - msg: >- - '%select{try|try!|try?}0' cannot appear to the right of a non-assignment - operator + msg: "'%select{try|try!|try?|await}0' cannot appear to the right of a non-assignment operator" - id: try_if_rhs_noncovering - msg: >- - '%select{try|try!|try?}0' following conditional operator does not cover - everything to its right + msg: "'%select{try|try!|try?|await}0' following conditional operator does not cover everything to its right" - id: try_assign_rhs_noncovering - msg: >- - '%select{try|try!|try?}0' following assignment operator does not cover - everything to its right + msg: "'%select{try|try!|try?|await}0' following assignment operator does not cover everything to its right" - id: broken_bool - msg: >- - type 'Bool' is broken + msg: "type 'Bool' is broken" - id: inject_forced_downcast - msg: >- - treating a forced downcast to %0 as optional will never produce 'nil' + msg: "treating a forced downcast to %0 as optional will never produce 'nil'" - id: forced_to_conditional_downcast - msg: >- - use 'as?' to perform a conditional downcast to %0 + msg: "use 'as?' to perform a conditional downcast to %0" - id: silence_inject_forced_downcast - msg: >- - add parentheses around the cast to silence this warning + msg: "add parentheses around the cast to silence this warning" - id: conditional_downcast_foreign - msg: >- - conditional downcast to CoreFoundation type %0 will always succeed + msg: "conditional downcast to CoreFoundation type %0 will always succeed" - id: note_explicitly_compare_cftypeid - msg: >- - did you mean to explicitly compare the CFTypeIDs of %0 and %1? + msg: "did you mean to explicitly compare the CFTypeIDs of %0 and %1?" - id: optional_used_as_boolean - msg: >- - optional type %0 cannot be used as a boolean; test for '%select{!|=}1= - nil' instead + msg: "optional type %0 cannot be used as a boolean; test for '%select{!|=}1= nil' instead" - id: integer_used_as_boolean - msg: >- - type %0 cannot be used as a boolean; test for '%select{!|=}1= 0' instead + msg: "type %0 cannot be used as a boolean; test for '%select{!|=}1= 0' instead" - id: interpolation_missing_proto - msg: >- - string interpolation requires the protocol - 'ExpressibleByStringInterpolation' to be defined + msg: "string interpolation requires the protocol 'ExpressibleByStringInterpolation' to be defined" - id: interpolation_broken_proto - msg: >- - protocol 'ExpressibleByStringInterpolation' is broken + msg: "protocol 'ExpressibleByStringInterpolation' is broken" - id: object_literal_broken_proto - msg: >- - object literal protocol is broken + msg: "object literal protocol is broken" - id: discard_expr_outside_of_assignment - msg: >- - '_' can only appear in a pattern or on the left side of an assignment + msg: "'_' can only appear in a pattern or on the left side of an assignment" - id: discard_expr_void_result_redundant - msg: >- - using '_' to ignore the result of a Void-returning function is redundant + msg: "using '_' to ignore the result of a Void-returning function is redundant" - id: collection_literal_heterogeneous - msg: >- - heterogeneous collection literal could only be inferred to %0; add - explicit type annotation if this is intentional + msg: "heterogeneous collection literal could only be inferred to %0; add explicit type annotation if this is intentional" - id: collection_literal_empty - msg: >- - empty collection literal requires an explicit type + msg: "empty collection literal requires an explicit type" - id: unresolved_member_no_inference - msg: >- - reference to member %0 cannot be resolved without a contextual type + msg: "reference to member %0 cannot be resolved without a contextual type" - id: cannot_infer_base_of_unresolved_member - msg: >- - cannot infer contextual base in reference to member %0 + msg: "cannot infer contextual base in reference to member %0" - id: unresolved_nil_literal - msg: >- - 'nil' requires a contextual type + msg: "'nil' requires a contextual type" - id: cannot_force_unwrap_nil_literal - msg: >- - 'nil' literal cannot be force unwrapped + msg: "'nil' literal cannot be force unwrapped" - id: type_of_expression_is_ambiguous - msg: >- - type of expression is ambiguous without more context + msg: "type of expression is ambiguous without more context" - id: failed_to_produce_diagnostic - msg: >- - failed to produce diagnostic for expression; please file a bug report + msg: "failed to produce diagnostic for expression; please file a bug report" - id: missing_protocol - msg: >- - missing protocol %0 + msg: "missing protocol %0" - id: nil_literal_broken_proto - msg: >- - protocol 'ExpressibleByNilLiteral' is broken + msg: "protocol 'ExpressibleByNilLiteral' is broken" - id: builtin_integer_literal_broken_proto - msg: >- - protocol '_ExpressibleByBuiltinIntegerLiteral' is broken + msg: "protocol '_ExpressibleByBuiltinIntegerLiteral' is broken" - id: integer_literal_broken_proto - msg: >- - protocol 'ExpressibleByIntegerLiteral' is broken + msg: "protocol 'ExpressibleByIntegerLiteral' is broken" - id: builtin_float_literal_broken_proto - msg: >- - protocol '_ExpressibleByBuiltinFloatLiteral' is broken + msg: "protocol '_ExpressibleByBuiltinFloatLiteral' is broken" - id: float_literal_broken_proto - msg: >- - protocol 'ExpressibleByFloatLiteral' is broken + msg: "protocol 'ExpressibleByFloatLiteral' is broken" - id: builtin_boolean_literal_broken_proto - msg: >- - protocol '_ExpressibleByBuiltinBooleanLiteral' is broken + msg: "protocol '_ExpressibleByBuiltinBooleanLiteral' is broken" - id: boolean_literal_broken_proto - msg: >- - protocol 'ExpressibleByBooleanLiteral' is broken + msg: "protocol 'ExpressibleByBooleanLiteral' is broken" - id: builtin_unicode_scalar_literal_broken_proto - msg: >- - protocol '_ExpressibleByBuiltinUnicodeScalarLiteral' is broken + msg: "protocol '_ExpressibleByBuiltinUnicodeScalarLiteral' is broken" - id: unicode_scalar_literal_broken_proto - msg: >- - protocol 'ExpressibleByUnicodeScalarLiteral' is broken + msg: "protocol 'ExpressibleByUnicodeScalarLiteral' is broken" - id: builtin_extended_grapheme_cluster_literal_broken_proto - msg: >- - protocol '_ExpressibleByBuiltinExtendedGraphemeClusterLiteral' is broken + msg: "protocol '_ExpressibleByBuiltinExtendedGraphemeClusterLiteral' is broken" - id: extended_grapheme_cluster_literal_broken_proto - msg: >- - protocol 'ExpressibleByExtendedGraphemeClusterLiteral' is broken + msg: "protocol 'ExpressibleByExtendedGraphemeClusterLiteral' is broken" - id: builtin_string_literal_broken_proto - msg: >- - protocol '_ExpressibleByBuiltinStringLiteral' is broken + msg: "protocol '_ExpressibleByBuiltinStringLiteral' is broken" - id: string_literal_broken_proto - msg: >- - protocol 'ExpressibleByStringLiteral' is broken + msg: "protocol 'ExpressibleByStringLiteral' is broken" - id: should_use_dictionary_literal - msg: >- - dictionary of type %0 cannot be %select{used|initialized}1 with array - literal + msg: "dictionary of type %0 cannot be %select{used|initialized}1 with array literal" - id: meant_dictionary_lit - msg: >- - did you mean to use a dictionary literal instead? + msg: "did you mean to use a dictionary literal instead?" - id: should_use_empty_dictionary_literal - msg: >- - use [:] to get an empty dictionary literal + msg: "use [:] to get an empty dictionary literal" - id: type_is_not_dictionary - msg: >- - contextual type %0 cannot be used with dictionary literal + msg: "contextual type %0 cannot be used with dictionary literal" - id: cannot_explicitly_specialize_generic_function - msg: >- - cannot explicitly specialize a generic function + msg: "cannot explicitly specialize a generic function" - id: not_a_generic_definition - msg: >- - cannot specialize a non-generic definition + msg: "cannot specialize a non-generic definition" - id: not_a_generic_type - msg: >- - cannot specialize non-generic type %0 + msg: "cannot specialize non-generic type %0" - id: type_parameter_count_mismatch - msg: >- - generic type %0 specialized with %select{too many|too few}3 type - parameters (got %2, but expected %1) + msg: "generic type %0 specialized with %select{too many|too few}3 type parameters (got %2, but expected %1)" - id: generic_type_requires_arguments - msg: >- - reference to generic type %0 requires arguments in <...> + msg: "reference to generic type %0 requires arguments in <...>" - id: descriptive_generic_type_declared_here - msg: >- - %0 declared here + msg: "%0 declared here" - id: use_of_void_pointer - msg: >- - Unsafe%0Pointer has been replaced by Unsafe%0RawPointer + msg: "Unsafe%0Pointer has been replaced by Unsafe%0RawPointer" - id: ambiguous_decl_ref - msg: >- - ambiguous use of %0 + msg: "ambiguous use of %0" - id: ambiguous_operator_ref - msg: >- - ambiguous use of operator %0 + msg: "ambiguous use of operator %0" - id: ambiguous_because_of_trailing_closure - msg: >- - %select{use an explicit argument label instead of a trailing - closure|avoid using a trailing closure}0 to call %1 + msg: "%select{use an explicit argument label instead of a trailing closure|avoid using a trailing closure}0 to call %1" - id: partial_application_of_function_invalid - msg: >- - partial application of %select{'mutating' method|'super.init' initializer - chain|'self.init' initializer delegation|'super' instance method with - metatype base}0 is not allowed + msg: "partial application of %select{'mutating' method|'super.init' initializer chain|'self.init' initializer delegation|'super' instance method with metatype base}0 is not allowed" - id: partial_application_of_function_invalid_swift4 - msg: >- - partial application of %select{'mutating' method|'super.init' initializer - chain|'self.init' initializer delegation|'super' instance method with - metatype base}0 is not allowed; calling the function has undefined - behavior and will be an error in future Swift versions + msg: "partial application of %select{'mutating' method|'super.init' initializer chain|'self.init' initializer delegation|'super' instance method with metatype base}0 is not allowed; calling the function has undefined behavior and will be an error in future Swift versions" - id: self_assignment_var - msg: >- - assigning a variable to itself + msg: "assigning a variable to itself" - id: self_assignment_prop - msg: >- - assigning a property to itself + msg: "assigning a property to itself" - id: property_use_in_closure_without_explicit_self - msg: >- - reference to property %0 in closure requires explicit use of 'self' to - make capture semantics explicit + msg: "reference to property %0 in closure requires explicit use of 'self' to make capture semantics explicit" - id: method_call_in_closure_without_explicit_self - msg: >- - call to method %0 in closure requires explicit use of 'self' to make - capture semantics explicit + msg: "call to method %0 in closure requires explicit use of 'self' to make capture semantics explicit" - id: note_capture_self_explicitly - msg: >- - capture 'self' explicitly to enable implicit 'self' in this closure + msg: "capture 'self' explicitly to enable implicit 'self' in this closure" - id: note_reference_self_explicitly - msg: >- - reference 'self.' explicitly + msg: "reference 'self.' explicitly" - id: note_other_self_capture - msg: >- - variable other than 'self' captured here under the name 'self' does not - enable implicit 'self' + msg: "variable other than 'self' captured here under the name 'self' does not enable implicit 'self'" - id: note_self_captured_weakly - msg: >- - weak capture of 'self' here does not enable implicit 'self' + msg: "weak capture of 'self' here does not enable implicit 'self'" - id: implicit_use_of_self_in_closure - msg: >- - implicit use of 'self' in closure; use 'self.' to make capture semantics - explicit + msg: "implicit use of 'self' in closure; use 'self.' to make capture semantics explicit" - id: recursive_accessor_reference - msg: >- - attempting to %select{access|modify}1 %0 within its own - %select{getter|setter}1 + msg: "attempting to %select{access|modify}1 %0 within its own %select{getter|setter}1" - id: recursive_accessor_reference_silence - msg: >- - access 'self' explicitly to silence this warning + msg: "access 'self' explicitly to silence this warning" - id: store_in_willset - msg: >- - attempting to store to property %0 within its own willSet, which is about - to be overwritten by the new value + msg: "attempting to store to property %0 within its own willSet, which is about to be overwritten by the new value" - id: value_of_module_type - msg: >- - expected module member name after module name + msg: "expected module member name after module name" - id: value_of_metatype_type - msg: >- - expected member name or constructor call after type name + msg: "expected member name or constructor call after type name" - id: add_parens_to_type - msg: >- - add arguments after the type to construct a value of the type + msg: "add arguments after the type to construct a value of the type" - id: add_self_to_type - msg: >- - use '.self' to reference the type object + msg: "use '.self' to reference the type object" - id: warn_unqualified_access - msg: >- - use of %0 treated as a reference to %1 in %2 %3 + msg: "use of %0 treated as a reference to %1 in %2 %3" - id: fix_unqualified_access_member - msg: >- - use 'self.' to silence this warning + msg: "use 'self.' to silence this warning" - id: fix_unqualified_access_top_level - msg: >- - use '%0' to reference the %1 + msg: "use '%0' to reference the %1" - id: fix_unqualified_access_top_level_multi - msg: >- - use '%0' to reference the %1 in module %2 + msg: "use '%0' to reference the %1 in module %2" - id: warn_deprecated_conditional_conformance_outer_access - msg: >- - use of %0 as reference to %1 in %2 %3 will change in future versions of - Swift to reference %4 in %5 %6 which comes via a conditional conformance + msg: "use of %0 as reference to %1 in %2 %3 will change in future versions of Swift to reference %4 in %5 %6 which comes via a conditional conformance" - id: fix_deprecated_conditional_conformance_outer_access - msg: >- - use '%0' to continue to reference the %1 + msg: "use '%0' to continue to reference the %1" - id: unsupported_special_decl_ref - msg: >- - referencing %0 as a function value is not implemented + msg: "referencing %0 as a function value is not implemented" - id: bitcasting_away_noescape - msg: >- - 'unsafeBitCast' from non-escaping function type %0 to escaping function - type %1 is undefined; use 'withoutActuallyEscaping' to temporarily escape a - function + msg: "'unsafeBitCast' from non-escaping function type %0 to escaping function type %1 is undefined; use 'withoutActuallyEscaping' to temporarily escape a function" - id: bitcasting_to_change_function_rep - msg: >- - 'unsafeBitCast' from function type %0 to %1 changes @convention and is - undefined; use an implicit conversion to change conventions + msg: "'unsafeBitCast' from function type %0 to %1 changes @convention and is undefined; use an implicit conversion to change conventions" - id: bitcasting_to_downcast - msg: >- - 'unsafeBitCast' from %0 to %1 can be replaced with 'unsafeDowncast' + msg: "'unsafeBitCast' from %0 to %1 can be replaced with 'unsafeDowncast'" - id: bitcasting_is_no_op - msg: >- - 'unsafeBitCast' from %0 to %1 is unnecessary and can be removed + msg: "'unsafeBitCast' from %0 to %1 is unnecessary and can be removed" - id: bitcasting_to_change_pointer_kind - msg: >- - 'unsafeBitCast' from %0 to %1 can be replaced with %2 initializer + msg: "'unsafeBitCast' from %0 to %1 can be replaced with %2 initializer" - id: bitcasting_to_change_pointee_type - msg: >- - 'unsafeBitCast' from %0 to %1 changes pointee type and may lead to - undefined behavior; use the 'withMemoryRebound' method on %0 - to rebind the type of memory + msg: "'unsafeBitCast' from %0 to %1 changes pointee type and may lead to undefined behavior; use the 'withMemoryRebound' method on %0 to rebind the type of memory" - id: bitcasting_to_give_type_to_raw_pointer - msg: >- - 'unsafeBitCast' from %0 to %1 gives a type to a raw pointer and may lead - to undefined behavior + msg: "'unsafeBitCast' from %0 to %1 gives a type to a raw pointer and may lead to undefined behavior" - id: bitcast_assume_memory_rebound - msg: >- - use the 'assumingMemoryBound' method if the pointer is known to point to - an existing value or array of type %0 in memory + msg: "use the 'assumingMemoryBound' method if the pointer is known to point to an existing value or array of type %0 in memory" - id: bitcast_bind_memory - msg: >- - use the 'bindMemory' method to assign type %0 to uninitialized raw memory + msg: "use the 'bindMemory' method to assign type %0 to uninitialized raw memory" - id: bitcasting_for_number_bit_pattern_init - msg: >- - 'unsafeBitCast' from %0 to %1 can be replaced with 'bitPattern:' - initializer on %1 + msg: "'unsafeBitCast' from %0 to %1 can be replaced with 'bitPattern:' initializer on %1" - id: bitcasting_for_number_bit_pattern_property - msg: >- - 'unsafeBitCast' from %0 to %1 can be replaced with 'bitPattern' property - on %0 + msg: "'unsafeBitCast' from %0 to %1 can be replaced with 'bitPattern' property on %0" - id: bitcasting_to_change_from_unsized_to_sized_int - msg: >- - 'unsafeBitCast' from %0 to %1 can be replaced with %1 initializer + msg: "'unsafeBitCast' from %0 to %1 can be replaced with %1 initializer" - id: use_of_qq_on_non_optional_value - msg: >- - left side of nil coalescing operator '??' has non-optional type %0, so - the right side is never used + msg: "left side of nil coalescing operator '??' has non-optional type %0, so the right side is never used" - id: nonoptional_compare_to_nil - msg: >- - comparing non-optional value of type %0 to 'nil' always returns - %select{false|true}1 + msg: "comparing non-optional value of type %0 to 'nil' always returns %select{false|true}1" - id: optional_check_nonoptional - msg: >- - non-optional expression of type %0 used in a check for optionals + msg: "non-optional expression of type %0 used in a check for optionals" - id: optional_check_promotion - msg: >- - explicitly specified type %0 adds an additional level of optional to the - initializer, making the optional check always succeed + msg: "explicitly specified type %0 adds an additional level of optional to the initializer, making the optional check always succeed" - id: optional_pattern_match_promotion - msg: >- - pattern match introduces an implicit promotion from %0 to %1 + msg: "pattern match introduces an implicit promotion from %0 to %1" - id: optional_to_any_coercion - msg: >- - expression implicitly coerced from %0 to %1 + msg: "expression implicitly coerced from %0 to %1" - id: iuo_to_any_coercion - msg: >- - coercion of implicitly unwrappable value of type %0 to %1 does not unwrap - optional + msg: "coercion of implicitly unwrappable value of type %0 to %1 does not unwrap optional" - id: iuo_to_any_coercion_note - msg: >- - implicitly unwrapped %0 %1 declared here + msg: "implicitly unwrapped %0 %1 declared here" - id: iuo_to_any_coercion_note_func_result - msg: >- - %0 %1 with implicitly unwrapped result type is declared here + msg: "%0 %1 with implicitly unwrapped result type is declared here" - id: default_optional_to_any - msg: >- - provide a default value to avoid this warning + msg: "provide a default value to avoid this warning" - id: force_optional_to_any - msg: >- - force-unwrap the value to avoid this warning + msg: "force-unwrap the value to avoid this warning" - id: silence_optional_to_any - msg: >- - explicitly cast to %0 with '%1' to silence this warning + msg: "explicitly cast to %0 with '%1' to silence this warning" - id: debug_description_in_string_interpolation_segment - msg: >- - string interpolation produces a debug description for %select{an - optional|a function}0 value; did you mean to make this explicit? + msg: "string interpolation produces a debug description for %select{an optional|a function}0 value; did you mean to make this explicit?" - id: silence_debug_description_in_interpolation_segment_call - msg: >- - use 'String(describing:)' to silence this warning + msg: "use 'String(describing:)' to silence this warning" - id: noescape_parameter - msg: >- - parameter %0 is implicitly non-escaping + msg: "parameter %0 is implicitly non-escaping" - id: generic_parameters_always_escaping - msg: >- - generic parameters are always considered '@escaping' + msg: "generic parameters are always considered '@escaping'" - id: passing_noescape_to_escaping - msg: >- - passing non-escaping parameter %0 to function expecting an @escaping closure + msg: "passing non-escaping parameter %0 to function expecting an @escaping closure" - id: converting_noespace_param_to_generic_type - msg: >- - converting non-escaping parameter %0 to generic parameter %1 may allow it - to escape + msg: "converting non-escaping parameter %0 to generic parameter %1 may allow it to escape" - id: assigning_noescape_to_escaping - msg: >- - assigning non-escaping parameter %0 to an @escaping closure + msg: "assigning non-escaping parameter %0 to an @escaping closure" - id: general_noescape_to_escaping - msg: >- - using non-escaping parameter %0 in a context expecting an @escaping closure + msg: "using non-escaping parameter %0 in a context expecting an @escaping closure" - id: converting_noescape_to_type - msg: >- - converting non-escaping value to %0 may allow it to escape + msg: "converting non-escaping value to %0 may allow it to escape" - id: capture_across_type_decl - msg: >- - %0 declaration cannot close over value %1 defined in outer scope + msg: "%0 declaration cannot close over value %1 defined in outer scope" - id: jump_out_of_defer - msg: >- - '%0' cannot transfer control out of a defer statement + msg: "'%0' cannot transfer control out of a defer statement" - id: defer_stmt_at_block_end - msg: >- - 'defer' statement at end of scope always executes immediately; replace - with 'do' statement to silence this warning + msg: "'defer' statement at end of scope always executes immediately; replace with 'do' statement to silence this warning" - id: return_invalid_outside_func - msg: >- - return invalid outside of a func + msg: "return invalid outside of a func" - id: return_expr_missing - msg: >- - non-void function should return a value + msg: "non-void function should return a value" - id: return_non_failable_init - msg: >- - only a failable initializer can return 'nil' + msg: "only a failable initializer can return 'nil'" - id: make_init_failable - msg: >- - use 'init?' to make the initializer %0 failable + msg: "use 'init?' to make the initializer %0 failable" - id: return_init_non_nil - msg: >- - 'nil' is the only return value permitted in an initializer + msg: "'nil' is the only return value permitted in an initializer" - id: if_always_true - msg: >- - 'if' condition is always true + msg: "'if' condition is always true" - id: while_always_true - msg: >- - 'while' condition is always true + msg: "'while' condition is always true" - id: guard_always_succeeds - msg: >- - 'guard' condition is always true, body is unreachable + msg: "'guard' condition is always true, body is unreachable" - id: expression_unused_closure - msg: >- - closure expression is unused + msg: "closure expression is unused" - id: expression_unused_function - msg: >- - expression resolves to an unused function + msg: "expression resolves to an unused function" - id: expression_unused_lvalue - msg: >- - expression resolves to an unused %select{variable|property|subscript}0 + msg: "expression resolves to an unused %select{variable|property|subscript}0" - id: expression_unused_result_call - msg: >- - result of call to %0 is unused + msg: "result of call to %0 is unused" - id: expression_unused_result_operator - msg: >- - result of operator %0 is unused + msg: "result of operator %0 is unused" - id: expression_unused_result_unknown - msg: >- - result of call to %select{function|closure}0 returning %1 is unused + msg: "result of call to %select{function|closure}0 returning %1 is unused" - id: expression_unused_result - msg: >- - expression of type %0 is unused + msg: "expression of type %0 is unused" - id: expression_unused_init_result - msg: >- - result of %0 initializer is unused + msg: "result of %0 initializer is unused" - id: expression_unused_optional_try - msg: >- - result of 'try?' is unused + msg: "result of 'try?' is unused" - id: expression_unused_selector_result - msg: >- - result of '#selector' is unused + msg: "result of '#selector' is unused" - id: expression_unused_literal - msg: >- - %0 literal is unused + msg: "%0 literal is unused" - id: assignment_lhs_not_lvalue - msg: >- - cannot assign to immutable expression of type %0 + msg: "cannot assign to immutable expression of type %0" - id: assignment_lhs_is_apply_expression - msg: >- - expression is not assignable: %0 + msg: "expression is not assignable: %0" - id: assignment_lhs_is_immutable_variable - msg: >- - cannot assign to value: %0 + msg: "cannot assign to value: %0" - id: assignment_lhs_is_immutable_property - msg: >- - cannot assign to property: %0 + msg: "cannot assign to property: %0" - id: assignment_subscript_has_immutable_base - msg: >- - cannot assign through subscript: %0 + msg: "cannot assign through subscript: %0" - id: assignment_dynamic_property_has_immutable_base - msg: >- - cannot assign through dynamic lookup property: %0 + msg: "cannot assign through dynamic lookup property: %0" - id: assignment_bang_has_immutable_subcomponent - msg: >- - cannot assign through '!': %0 + msg: "cannot assign through '!': %0" - id: candidate_is_not_assignable - msg: >- - candidate is not assignable: %0 %1 + msg: "candidate is not assignable: %0 %1" - id: change_to_mutating - msg: >- - mark %select{method|accessor}0 'mutating' to make 'self' mutable + msg: "mark %select{method|accessor}0 'mutating' to make 'self' mutable" - id: masked_mutable_property - msg: >- - add explicit '%0' to refer to mutable %1 of %2 + msg: "add explicit '%0' to refer to mutable %1 of %2" - id: assignment_let_property_delegating_init - msg: >- - 'let' property %0 may not be initialized directly; use "self.init(...)" - or "self = ..." instead + msg: "'let' property %0 may not be initialized directly; use \"self.init(...)\" or \"self = ...\" instead" - id: label_shadowed - msg: >- - label %0 cannot be reused on an inner statement + msg: "label %0 cannot be reused on an inner statement" - id: break_outside_loop - msg: >- - 'break' is only allowed inside a loop, if, do, or switch + msg: "'break' is only allowed inside a loop, if, do, or switch" - id: unlabeled_break_outside_loop - msg: >- - unlabeled 'break' is only allowed inside a loop or switch, a labeled - break is required to exit an if or do + msg: "unlabeled 'break' is only allowed inside a loop or switch, a labeled break is required to exit an if or do" - id: continue_outside_loop - msg: >- - 'continue' is only allowed inside a loop + msg: "'continue' is only allowed inside a loop" - id: continue_not_in_this_stmt - msg: >- - 'continue' cannot be used with %0 statements + msg: "'continue' cannot be used with %0 statements" - id: unresolved_label - msg: >- - cannot find label %0 in scope + msg: "cannot find label %0 in scope" - id: unresolved_label_corrected - msg: >- - cannot find label %0 in scope; did you mean %1? + msg: "cannot find label %0 in scope; did you mean %1?" - id: foreach_sequence_does_not_conform_to_expected_protocol - msg: >- - for-in loop requires %0 to conform to %1%select{|; did you mean to unwrap - optional?}2 + msg: "for-in loop requires %0 to conform to %1%select{|; did you mean to unwrap optional?}2" - id: no_match_operator - msg: >- - no binary '~=' operator available for 'switch' statement + msg: "no binary '~=' operator available for 'switch' statement" - id: fallthrough_outside_switch - msg: >- - 'fallthrough' is only allowed inside a switch + msg: "'fallthrough' is only allowed inside a switch" - id: fallthrough_from_last_case - msg: >- - 'fallthrough' without a following 'case' or 'default' block + msg: "'fallthrough' without a following 'case' or 'default' block" - id: fallthrough_into_case_with_var_binding - msg: >- - 'fallthrough' from a case which doesn't bind variable %0 + msg: "'fallthrough' from a case which doesn't bind variable %0" - id: unnecessary_cast_over_optionset - msg: >- - unnecessary cast over raw value of %0 + msg: "unnecessary cast over raw value of %0" - id: mutability_mismatch_multiple_pattern_list - msg: >- - '%select{var|let}0' pattern binding must match previous - '%select{var|let}1' pattern binding + msg: "'%select{var|let}0' pattern binding must match previous '%select{var|let}1' pattern binding" - id: type_mismatch_multiple_pattern_list - msg: >- - pattern variable bound to type %0, expected type %1 + msg: "pattern variable bound to type %0, expected type %1" - id: type_mismatch_fallthrough_pattern_list - msg: >- - pattern variable bound to type %0, fallthrough case bound to type %1 + msg: "pattern variable bound to type %0, fallthrough case bound to type %1" - id: unknown_case_must_be_catchall - msg: >- - '@unknown' is only supported for catch-all cases ("case _") + msg: "'@unknown' is only supported for catch-all cases (\"case _\")" - id: unknown_case_where_clause - msg: >- - 'where' cannot be used with '@unknown' + msg: "'where' cannot be used with '@unknown'" - id: unknown_case_multiple_patterns - msg: >- - '@unknown' cannot be applied to multiple patterns + msg: "'@unknown' cannot be applied to multiple patterns" - id: unknown_case_must_be_last - msg: >- - '@unknown' can only be applied to the last case in a switch + msg: "'@unknown' can only be applied to the last case in a switch" - id: where_on_one_item - msg: >- - 'where' only applies to the second pattern match in this case + msg: "'where' only applies to the second pattern match in this case" - id: add_where_newline - msg: >- - disambiguate by adding a line break between them if this is desired + msg: "disambiguate by adding a line break between them if this is desired" - id: duplicate_where - msg: >- - duplicate the 'where' on both patterns to check both patterns + msg: "duplicate the 'where' on both patterns to check both patterns" - id: trailing_closure_requires_parens - msg: >- - trailing closure in this context is confusable with the body of the - statement; pass as a parenthesized argument to silence this warning + msg: "trailing closure in this context is confusable with the body of the statement; pass as a parenthesized argument to silence this warning" - id: opaque_type_var_no_init - msg: >- - property declares an opaque return type, but has no initializer - expression from which to infer an underlying type + msg: "property declares an opaque return type, but has no initializer expression from which to infer an underlying type" - id: opaque_type_no_underlying_type_candidates - msg: >- - function declares an opaque return type, but has no return statements in - its body from which to infer an underlying type + msg: "function declares an opaque return type, but has no return statements in its body from which to infer an underlying type" - id: opaque_type_mismatched_underlying_type_candidates - msg: >- - function declares an opaque return type, but the return statements in its - body do not have matching underlying types + msg: "function declares an opaque return type, but the return statements in its body do not have matching underlying types" - id: opaque_type_underlying_type_candidate_here - msg: >- - return statement has underlying type %0 + msg: "return statement has underlying type %0" - id: opaque_type_self_referential_underlying_type - msg: >- - function opaque return type was inferred as %0, which defines the opaque - type in terms of itself + msg: "function opaque return type was inferred as %0, which defines the opaque type in terms of itself" - id: opaque_type_var_no_underlying_type - msg: >- - property declares an opaque return type, but cannot infer the underlying - type from its initializer expression + msg: "property declares an opaque return type, but cannot infer the underlying type from its initializer expression" - id: cannot_infer_type_for_pattern - msg: >- - type annotation missing in pattern + msg: "type annotation missing in pattern" - id: refutable_pattern_requires_initializer - msg: >- - pattern matching requires an initializer value to match against + msg: "pattern matching requires an initializer value to match against" - id: var_pattern_didnt_bind_variables - msg: >- - '%0' pattern has no effect; sub-pattern didn't bind any variables + msg: "'%0' pattern has no effect; sub-pattern didn't bind any variables" - id: iflet_pattern_matching - msg: >- - pattern matching in a condition requires the 'case' keyword + msg: "pattern matching in a condition requires the 'case' keyword" - id: iflet_implicitly_unwraps - msg: >- - pattern matching in a condition implicitly unwraps optionals + msg: "pattern matching in a condition implicitly unwraps optionals" - id: type_pattern_missing_is - msg: >- - 'is' keyword required to pattern match against type name + msg: "'is' keyword required to pattern match against type name" - id: pattern_type_mismatch_context - msg: >- - type annotation does not match contextual type %0 + msg: "type annotation does not match contextual type %0" - id: tuple_pattern_in_non_tuple_context - msg: >- - tuple pattern cannot match values of the non-tuple type %0 + msg: "tuple pattern cannot match values of the non-tuple type %0" - id: found_one_pattern_for_several_associated_values - msg: >- - enum case '%0' has %1 associated values; matching them as a tuple is - deprecated + msg: "enum case '%0' has %1 associated values; matching them as a tuple is deprecated" - id: converting_tuple_into_several_associated_values - msg: >- - enum case '%0' has %1 associated values + msg: "enum case '%0' has %1 associated values" - id: converting_several_associated_values_into_tuple - msg: >- - enum case '%0' has one associated value that is a tuple of %1 elements + msg: "enum case '%0' has one associated value that is a tuple of %1 elements" - id: closure_argument_list_tuple - msg: >- - contextual closure type %0 expects %1 argument%s1, but %2 - %select{were|was}3 used in closure body + msg: "contextual closure type %0 expects %1 argument%s1, but %2 %select{were|was}3 used in closure body" - id: closure_argument_list_missing - msg: >- - contextual type for closure argument list expects %0 argument%s0, which - cannot be implicitly ignored + msg: "contextual type for closure argument list expects %0 argument%s0, which cannot be implicitly ignored" - id: closure_tuple_parameter_destructuring - msg: >- - closure tuple parameter %0 does not support destructuring + msg: "closure tuple parameter %0 does not support destructuring" - id: closure_tuple_parameter_destructuring_implicit - msg: >- - closure tuple parameter %0 does not support destructuring with implicit - parameters + msg: "closure tuple parameter %0 does not support destructuring with implicit parameters" - id: single_tuple_parameter_mismatch_special - msg: >- - %0 expects a single parameter of type %1%2 + msg: "%0 expects a single parameter of type %1%2" - id: single_tuple_parameter_mismatch_normal - msg: >- - %0 %1 expects a single parameter of type %2%3 + msg: "%0 %1 expects a single parameter of type %2%3" - id: cannot_convert_single_tuple_into_multiple_arguments - msg: >- - %0 %select{%1 |}2expects %3 separate arguments%select{|; remove extra - parentheses to change tuple into separate arguments}4 + msg: "%0 %select{%1 |}2expects %3 separate arguments%select{|; remove extra parentheses to change tuple into separate arguments}4" - id: enum_element_pattern_assoc_values_mismatch - msg: >- - pattern with associated values does not match enum case %0 + msg: "pattern with associated values does not match enum case %0" - id: enum_element_pattern_assoc_values_remove - msg: >- - remove associated values to make the pattern match + msg: "remove associated values to make the pattern match" - id: tuple_pattern_length_mismatch - msg: >- - tuple pattern has the wrong length for tuple type %0 + msg: "tuple pattern has the wrong length for tuple type %0" - id: tuple_pattern_label_mismatch - msg: >- - tuple pattern element label %0 must be %1 + msg: "tuple pattern element label %0 must be %1" - id: enum_element_pattern_member_not_found - msg: >- - enum case %0 not found in type %1 + msg: "enum case %0 not found in type %1" - id: optional_element_pattern_not_valid_type - msg: >- - '?' pattern cannot match values of type %0 + msg: "'?' pattern cannot match values of type %0" - id: condition_optional_element_pattern_not_valid_type - msg: >- - initializer for conditional binding must have Optional type, not %0 + msg: "initializer for conditional binding must have Optional type, not %0" - id: enum_element_pattern_not_member_of_enum - msg: >- - enum case %0 is not a member of type %1 + msg: "enum case %0 is not a member of type %1" - id: ambiguous_enum_pattern_type - msg: >- - generic enum type %0 is ambiguous without explicit generic parameters - when matching value of type %1 + msg: "generic enum type %0 is ambiguous without explicit generic parameters when matching value of type %1" - id: type_inferred_to_undesirable_type - msg: >- - %select{variable|constant}2 %0 inferred to have type %1, which may be - unexpected + msg: "%select{variable|constant}2 %0 inferred to have type %1, which may be unexpected" - id: type_inferred_to_uninhabited_type - msg: >- - %select{variable|constant}2 %0 inferred to have type %1, which is an enum - with no cases + msg: "%select{variable|constant}2 %0 inferred to have type %1, which is an enum with no cases" - id: type_inferred_to_uninhabited_tuple_type - msg: >- - %select{variable|constant}2 %0 inferred to have type %1, which contains - an enum with no cases + msg: "%select{variable|constant}2 %0 inferred to have type %1, which contains an enum with no cases" - id: add_explicit_type_annotation_to_silence - msg: >- - add an explicit type annotation to silence this warning + msg: "add an explicit type annotation to silence this warning" - id: unowned_assignment_immediate_deallocation - msg: >- - instance will be immediately deallocated because - %select{variable|property}2 %0 is %1 + msg: "instance will be immediately deallocated because %select{variable|property}2 %0 is %1" - id: unowned_assignment_requires_strong - msg: >- - a strong reference is required to prevent the instance from being - deallocated + msg: "a strong reference is required to prevent the instance from being deallocated" - id: isa_collection_downcast_pattern_value_unimplemented - msg: >- - collection downcast in cast pattern is not implemented; use an explicit - downcast to %0 instead + msg: "collection downcast in cast pattern is not implemented; use an explicit downcast to %0 instead" - id: try_unhandled - msg: >- - errors thrown from here are not handled + msg: "errors thrown from here are not handled" - id: throwing_call_unhandled - msg: >- - call can throw, but the error is not handled + msg: "call can throw, but the error is not handled" - id: tryless_throwing_call_unhandled - msg: >- - call can throw, but it is not marked with 'try' and the error is not handled + msg: "call can throw, but it is not marked with 'try' and the error is not handled" - id: throw_in_nonthrowing_function - msg: >- - error is not handled because the enclosing function is not declared 'throws' + msg: "error is not handled because the enclosing function is not declared 'throws'" - id: throwing_call_in_rethrows_function - msg: >- - call can throw, but the error is not handled; a function declared - 'rethrows' may only throw if its parameter does + msg: "call can throw, but the error is not handled; a function declared 'rethrows' may only throw if its parameter does" - id: tryless_throwing_call_in_rethrows_function - msg: >- - call can throw, but it is not marked with 'try' and the error is not - handled; a function declared 'rethrows' may only throw if its parameter does + msg: "call can throw, but it is not marked with 'try' and the error is not handled; a function declared 'rethrows' may only throw if its parameter does" - id: throw_in_rethrows_function - msg: >- - a function declared 'rethrows' may only throw if its parameter does + msg: "a function declared 'rethrows' may only throw if its parameter does" - id: because_rethrows_argument_throws - msg: >- - call is to 'rethrows' function, but argument function can throw + msg: "call is to 'rethrows' function, but argument function can throw" - id: because_rethrows_default_argument_throws - msg: >- - call is to 'rethrows' function, but a defaulted argument function can throw + msg: "call is to 'rethrows' function, but a defaulted argument function can throw" - id: throwing_call_in_nonthrowing_autoclosure - msg: >- - call can throw, but it is executed in a non-throwing autoclosure + msg: "call can throw, but it is executed in a non-throwing autoclosure" - id: tryless_throwing_call_in_nonthrowing_autoclosure - msg: >- - call can throw, but it is not marked with 'try' and it is executed in a - non-throwing autoclosure + msg: "call can throw, but it is not marked with 'try' and it is executed in a non-throwing autoclosure" - id: throw_in_nonthrowing_autoclosure - msg: >- - error is not handled because it is thrown in a non-throwing autoclosure + msg: "error is not handled because it is thrown in a non-throwing autoclosure" - id: try_unhandled_in_nonexhaustive_catch - msg: >- - errors thrown from here are not handled because the enclosing catch is - not exhaustive + msg: "errors thrown from here are not handled because the enclosing catch is not exhaustive" - id: throwing_call_in_nonexhaustive_catch - msg: >- - call can throw, but the enclosing catch is not exhaustive + msg: "call can throw, but the enclosing catch is not exhaustive" - id: tryless_throwing_call_in_nonexhaustive_catch - msg: >- - call can throw, but it is not marked with 'try' and the enclosing catch - is not exhaustive + msg: "call can throw, but it is not marked with 'try' and the enclosing catch is not exhaustive" - id: throw_in_nonexhaustive_catch - msg: >- - error is not handled because the enclosing catch is not exhaustive + msg: "error is not handled because the enclosing catch is not exhaustive" - id: throwing_call_in_illegal_context - msg: >- - call can throw, but errors cannot be thrown out of %0 + msg: "call can throw, but errors cannot be thrown out of %select{<>|a default argument|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0" - id: throw_in_illegal_context - msg: >- - errors cannot be thrown out of %0 + msg: "errors cannot be thrown out of %select{<>|a default argument|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0" - id: throwing_operator_without_try - msg: >- - operator can throw but expression is not marked with 'try' + msg: "operator can throw but expression is not marked with 'try'" - id: throwing_interpolation_without_try - msg: >- - interpolation can throw but is not marked with 'try' + msg: "interpolation can throw but is not marked with 'try'" - id: throwing_call_without_try - msg: >- - call can throw but is not marked with 'try' + msg: "call can throw but is not marked with 'try'" - id: note_forgot_try - msg: >- - did you mean to use 'try'? + msg: "did you mean to use 'try'?" - id: note_error_to_optional - msg: >- - did you mean to handle error as optional value? + msg: "did you mean to handle error as optional value?" - id: note_disable_error_propagation - msg: >- - did you mean to disable error propagation? + msg: "did you mean to disable error propagation?" - id: no_throw_in_try - msg: >- - no calls to throwing functions occur within 'try' expression + msg: "no calls to throwing functions occur within 'try' expression" - id: no_throw_in_do_with_catch - msg: >- - 'catch' block is unreachable because no errors are thrown in 'do' block + msg: "'catch' block is unreachable because no errors are thrown in 'do' block" + +- id: async_call_without_await + msg: "call is 'async' but is not marked with 'await'" + +- id: async_call_without_await_in_autoclosure + msg: "call is 'async' in an autoclosure argument that is not marked with 'await'" + +- id: no_async_in_await + msg: "no calls to 'async' functions occur within 'await' expression" + +- id: async_call_in_illegal_context + msg: "'async' call cannot occur in %select{<>|a default argument|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0" + +- id: await_in_illegal_context + msg: "'await' operation cannot occur in %select{<>|a default argument|a property initializer|a global variable initializer|an enum case raw value|a catch pattern|a catch guard expression|a defer body}0" + +- id: async_in_nonasync_function + msg: "%select{'async'|'await'}0 in %select{a function|an autoclosure}1 that does not support concurrency" + +- id: note_add_async_to_function + msg: "add 'async' to function %0 to make it asynchronous" + +- id: note_add_asynchandler_to_function + msg: "add '@asyncHandler' to function %0 to create an implicit asynchronous context" + +- id: not_objc_function_async + msg: "'async' function cannot be represented in Objective-C" + +- id: not_objc_function_type_async + msg: "'async' function types cannot be represented in Objective-C" + +- id: protocol_witness_async_conflict + msg: "candidate is %select{not |}0'async', but protocol requirement is%select{| not}0" + +- id: async_autoclosure_nonasync_function + msg: "'async' autoclosure parameter in a non-'async' function" + +- id: asynchandler_attr_requires_concurrency + msg: "'@asyncHandler' is only valid when experimental concurrency is enabled" + +- id: asynchandler_non_func + msg: "'@asyncHandler' can only be applied to functions" + +- id: asynchandler_returns_value + msg: "'@asyncHandler' function can only return 'Void'" + +- id: asynchandler_throws + msg: "'@asyncHandler' function cannot throw" + +- id: asynchandler_async + msg: "'@asyncHandler' function cannot be 'async' itself" + +- id: asynchandler_inout_parameter + msg: "'inout' parameter is not allowed in '@asyncHandler' function" + +- id: asynchandler_mutating + msg: "'@asyncHandler' function cannot be 'mutating'" - id: unsupported_recursive_struct - msg: >- - value type %0 cannot have a stored property that recursively contains it + msg: "value type %0 cannot have a stored property that recursively contains it" - id: enum_non_well_founded - msg: >- - enum containing only recursive cases is impossible to instantiate + msg: "enum containing only recursive cases is impossible to instantiate" - id: recursive_enum_not_indirect - msg: >- - recursive enum %0 is not marked 'indirect' + msg: "recursive enum %0 is not marked 'indirect'" - id: unsupported_infinitely_sized_type - msg: >- - value type %0 has infinite size + msg: "value type %0 has infinite size" - id: note_type_cycle_starts_here - msg: >- - cycle beginning here: %0 + msg: "cycle beginning here: %0" - id: note_recursive_enum_case_here - msg: >- - recursive case here + msg: "recursive case here" - id: sugar_type_not_found - msg: >- - broken standard library: cannot find - %select{Array|Optional|ImplicitlyUnwrappedOptional|Dictionary|Error}0 type + msg: "broken standard library: cannot find %select{Array|Optional|ImplicitlyUnwrappedOptional|Dictionary|Error}0 type" - id: optional_intrinsics_not_found - msg: >- - broken standard library: cannot find intrinsic operations on Optional + msg: "broken standard library: cannot find intrinsic operations on Optional" - id: pointer_argument_intrinsics_not_found - msg: >- - broken standard library: cannot find intrinsic operations on - UnsafeMutablePointer + msg: "broken standard library: cannot find intrinsic operations on UnsafeMutablePointer" - id: array_literal_intrinsics_not_found - msg: >- - broken standard library: cannot find intrinsic operations on Array + msg: "broken standard library: cannot find intrinsic operations on Array" - id: class_super_access - msg: >- - class %select{must be declared - %select{%select{private|fileprivate|internal|%error|%error}1|private or - fileprivate}3|cannot be declared %select{in this - context|fileprivate|internal|public|open}1}0 because its superclass - %select{is %select{private|fileprivate|internal|'@_spi'|'@_spi'}2|uses - %select{a private|a fileprivate|an internal|an '@_spi'|an '@_spi'}2 - type as a generic parameter}4 + msg: "class %select{must be declared %select{%select{private|fileprivate|internal|%error|%error}1|private or fileprivate}3|cannot be declared %select{in this context|fileprivate|internal|public|open}1}0 because its superclass %select{is %select{private|fileprivate|internal|'@_spi'|'@_spi'}2|uses %select{a private|a fileprivate|an internal|an '@_spi'|an '@_spi'}2 type as a generic parameter}4" - id: class_super_access_warn - msg: >- - class %select{should be declared - %select{private|fileprivate|internal|%error|%error}1|should not be declared - %select{in this context|fileprivate|internal|public|open}1}0 because its - superclass %select{is - %select{private|fileprivate|internal|'@_spi'|'@_spi'}2|uses - %select{a private|a - fileprivate|an internal|an '@_spi'|an '@_spi'}2 - type as a generic parameter}4 + msg: "class %select{should be declared %select{private|fileprivate|internal|%error|%error}1|should not be declared %select{in this context|fileprivate|internal|public|open}1}0 because its superclass %select{is %select{private|fileprivate|internal|'@_spi'|'@_spi'}2|uses %select{a private|a fileprivate|an internal|an '@_spi'|an '@_spi'}2 type as a generic parameter}4" - id: class_super_not_usable_from_inline - msg: >- - %select{type referenced from |}0the superclass of a '@usableFromInline' - class must be '@usableFromInline' or public + msg: "%select{type referenced from |}0the superclass of a '@usableFromInline' class must be '@usableFromInline' or public" - id: class_super_not_usable_from_inline_warn - msg: >- - %select{type referenced from |}0the superclass of a '@usableFromInline' - class should be '@usableFromInline' or public + msg: "%select{type referenced from |}0the superclass of a '@usableFromInline' class should be '@usableFromInline' or public" - id: dot_protocol_on_non_existential - msg: >- - cannot use 'Protocol' with non-protocol type %0 + msg: "cannot use 'Protocol' with non-protocol type %0" - id: tuple_single_element - msg: >- - cannot create a single-element tuple with an element label + msg: "cannot create a single-element tuple with an element label" - id: tuple_ellipsis - msg: >- - cannot create a variadic tuple + msg: "cannot create a variadic tuple" - id: tuple_duplicate_label - msg: >- - cannot create a tuple with a duplicate element label + msg: "cannot create a tuple with a duplicate element label" - id: enum_element_ellipsis - msg: >- - variadic enum cases are not supported + msg: "variadic enum cases are not supported" - id: implicitly_unwrapped_optional_in_illegal_position_interpreted_as_optional - msg: >- - using '!' is not allowed here; treating this as '?' instead + msg: "using '!' is not allowed here; treating this as '?' instead" - id: implicitly_unwrapped_optional_deprecated_in_this_position - msg: >- - using '!' here is deprecated and will be removed in a future release + msg: "using '!' here is deprecated and will be removed in a future release" - id: implicitly_unwrapped_optional_in_illegal_position - msg: >- - using '!' is not allowed here; perhaps '?' was intended? + msg: "using '!' is not allowed here; perhaps '?' was intended?" - id: invalid_ownership_type - msg: >- - %0 may only be applied to class and class-bound protocol types, not %1 + msg: "%0 may only be applied to class and class-bound protocol types, not %1" - id: invalid_ownership_protocol_type - msg: >- - %0 must not be applied to non-class-bound %1; consider adding a protocol - conformance that has a class bound + msg: "%0 must not be applied to non-class-bound %1; consider adding a protocol conformance that has a class bound" - id: invalid_ownership_incompatible_class - msg: >- - %0 is incompatible with %1 references + msg: "%0 is incompatible with %1 references" - id: invalid_ownership_with_optional - msg: >- - %0 variable cannot have optional type + msg: "%0 variable cannot have optional type" - id: invalid_ownership_not_optional - msg: >- - %0 variable should have optional type %1 + msg: "%0 variable should have optional type %1" - id: invalid_ownership_is_let - msg: >- - %0 must be a mutable variable, because it may change at runtime + msg: "%0 must be a mutable variable, because it may change at runtime" - id: ownership_invalid_in_protocols - msg: >- - %0 cannot be applied to a property declaration in a protocol + msg: "%0 cannot be applied to a property declaration in a protocol" - id: ownership_invalid_in_protocols_compat_warning - msg: >- - %0 should not be applied to a property declaration in a protocol and will - be disallowed in future versions + msg: "%0 should not be applied to a property declaration in a protocol and will be disallowed in future versions" - id: required_initializer_nonclass - msg: >- - 'required' initializer in non-class type %0 + msg: "'required' initializer in non-class type %0" - id: required_initializer_in_extension - msg: >- - 'required' initializer must be declared directly in class %0 (not in an - extension) + msg: "'required' initializer must be declared directly in class %0 (not in an extension)" - id: required_initializer_missing - msg: >- - 'required' initializer %0 must be provided by subclass of %1 + msg: "'required' initializer %0 must be provided by subclass of %1" - id: required_initializer_here - msg: >- - 'required' initializer is declared in superclass here + msg: "'required' initializer is declared in superclass here" - id: required_initializer_not_accessible - msg: >- - 'required' initializer must be accessible wherever class %0 can be - subclassed + msg: "'required' initializer must be accessible wherever class %0 can be subclassed" - id: required_initializer_missing_keyword - msg: >- - 'required' modifier must be present on all overrides of a required - initializer + msg: "'required' modifier must be present on all overrides of a required initializer" - id: required_initializer_override_wrong_keyword - msg: >- - use the 'required' modifier to override a required initializer + msg: "use the 'required' modifier to override a required initializer" - id: required_initializer_override_keyword - msg: >- - 'override' is implied when overriding a required initializer + msg: "'override' is implied when overriding a required initializer" - id: overridden_required_initializer_here - msg: >- - overridden required initializer is here + msg: "overridden required initializer is here" - id: attribute_requires_function_type - msg: >- - @%0 attribute only applies to function types + msg: "@%0 attribute only applies to function types" - id: unsupported_convention - msg: >- - convention '%0' not supported + msg: "convention '%0' not supported" - id: unreferenced_generic_parameter - msg: >- - generic parameter '%0' is not used in function signature + msg: "generic parameter '%0' is not used in function signature" - id: unexpected_ctype_for_non_c_convention - msg: >- - convention '%0' does not support the 'cType' argument label, did you mean - @convention(c, cType: "%1") or @convention(block, cType: "%1") instead? + msg: "convention '%0' does not support the 'cType' argument label, did you mean @convention(c, cType: \"%1\") or @convention(block, cType: \"%1\") instead?" - id: unable_to_parse_c_function_type - msg: >- - unable to parse '%0'; it should be a C function pointer type or a block - pointer type + msg: "unable to parse '%0'; it should be a C function pointer type or a block pointer type" - id: unsupported_opaque_type - msg: >- - 'some' types are only implemented for the declared type of properties and - subscripts and the return type of functions + msg: "'some' types are only implemented for the declared type of properties and subscripts and the return type of functions" - id: opaque_type_unsupported_pattern - msg: >- - 'some' type can only be declared on a single property declaration + msg: "'some' type can only be declared on a single property declaration" - id: opaque_type_in_protocol_requirement - msg: >- - 'some' type cannot be the return type of a protocol requirement; - did you mean to add an associated type? + msg: "'some' type cannot be the return type of a protocol requirement; did you mean to add an associated type?" - id: attr_only_on_parameters_of_differentiable - msg: >- - '%0' may only be used on parameters of '@differentiable' function types + msg: "'%0' may only be used on parameters of '@differentiable' function types" - id: differentiable_function_type_invalid_parameter - msg: >- - parameter type '%0' does not conform to 'Differentiable'%select{| and - satisfy '%0 == %0.TangentVector'}1, but the enclosing function type is - '@differentiable%select{|(linear)}1'%select{|; did you want to add - '@noDerivative' to this parameter?}2 + msg: "parameter type '%0' does not conform to 'Differentiable'%select{| and satisfy '%0 == %0.TangentVector'}1, but the enclosing function type is '@differentiable%select{|(linear)}1'%select{|; did you want to add '@noDerivative' to this parameter?}2" - id: differentiable_function_type_invalid_result - msg: >- - result type '%0' does not conform to 'Differentiable'%select{| and - satisfy '%0 == %0.TangentVector'}1, but the enclosing function type is - '@differentiable%select{|(linear)}1' + msg: "result type '%0' does not conform to 'Differentiable'%select{| and satisfy '%0 == %0.TangentVector'}1, but the enclosing function type is '@differentiable%select{|(linear)}1'" - id: opened_non_protocol - msg: >- - @opened cannot be applied to non-protocol type %0 + msg: "@opened cannot be applied to non-protocol type %0" - id: sil_function_ellipsis - msg: >- - SIL function types cannot be variadic + msg: "SIL function types cannot be variadic" - id: sil_function_input_label - msg: >- - SIL function types cannot have labeled inputs + msg: "SIL function types cannot have labeled inputs" - id: sil_function_output_label - msg: >- - SIL function types cannot have labeled results + msg: "SIL function types cannot have labeled results" - id: sil_non_coro_yields - msg: >- - non-coroutine SIL function types cannot have @yield results + msg: "non-coroutine SIL function types cannot have @yield results" - id: sil_function_repeat_convention - msg: >- - repeated %select{parameter|result|callee}0 convention attribute + msg: "repeated %select{parameter|result|callee}0 convention attribute" - id: ast_subst_function_type - msg: >- - substitutions cannot be provided on a formal function type + msg: "substitutions cannot be provided on a formal function type" - id: sil_function_multiple_error_results - msg: >- - SIL function types cannot have multiple @error results + msg: "SIL function types cannot have multiple @error results" - id: unsupported_sil_convention - msg: >- - convention '%0' not supported in SIL + msg: "convention '%0' not supported in SIL" - id: illegal_sil_type - msg: >- - type %0 is not a legal SIL value type + msg: "type %0 is not a legal SIL value type" - id: sil_box_arg_mismatch - msg: >- - SIL box type has wrong number of generic arguments for layout + msg: "SIL box type has wrong number of generic arguments for layout" - id: sil_metatype_without_repr - msg: >- - metatypes in SIL must have @thin, @thick, or @objc_metatype attribute + msg: "metatypes in SIL must have @thin, @thick, or @objc_metatype attribute" - id: sil_metatype_multiple_reprs - msg: >- - metatypes in SIL can only be one of @thin, @thick, or @objc_metatype + msg: "metatypes in SIL can only be one of @thin, @thick, or @objc_metatype" - id: objc_interop_disabled - msg: >- - Objective-C interoperability is disabled + msg: "Objective-C interoperability is disabled" - id: attr_used_without_required_module - msg: >- - %0 attribute used without importing module %1 + msg: "%0 attribute used without importing module %1" - id: invalid_objc_decl_context - msg: >- - @objc can only be used with members of classes, @objc protocols, and - concrete extensions of classes + msg: "@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes" - id: invalid_objc_decl - msg: >- - only classes (and their extensions), protocols, methods, initializers, - properties, and subscript declarations can be declared @objc + msg: "only classes (and their extensions), protocols, methods, initializers, properties, and subscript declarations can be declared @objc" - id: invalid_objc_swift_rooted_class - msg: >- - only classes that inherit from NSObject can be declared @objc + msg: "only classes that inherit from NSObject can be declared @objc" - id: invalid_nonobjc_decl - msg: >- - only class members and extensions of classes can be declared @nonobjc + msg: "only class members and extensions of classes can be declared @nonobjc" - id: invalid_nonobjc_extension - msg: >- - only extensions of classes can be declared @nonobjc + msg: "only extensions of classes can be declared @nonobjc" - id: objc_in_extension_context - msg: >- - members of constrained extensions cannot be declared @objc + msg: "members of constrained extensions cannot be declared @objc" - id: objc_in_generic_extension - msg: >- - extensions of %select{classes from generic context|generic classes}0 - cannot contain '@objc' members + msg: "extensions of %select{classes from generic context|generic classes}0 cannot contain '@objc' members" - id: objc_in_resilient_extension - msg: >- - '@objc' %0 in extension of subclass of %1 requires %2 %3 + msg: "'@objc' %0 in extension of subclass of %1 requires %2 %3" - id: objc_operator - msg: >- - operator methods cannot be declared @objc + msg: "operator methods cannot be declared @objc" - id: objc_operator_proto - msg: >- - @objc protocols must not have operator requirements + msg: "@objc protocols must not have operator requirements" - id: objc_inference_swift3_dynamic - msg: >- - inference of '@objc' for 'dynamic' members is deprecated + msg: "inference of '@objc' for 'dynamic' members is deprecated" - id: objc_inference_swift3_objc_derived - msg: >- - inference of '@objc' for members of Objective-C-derived classes is - deprecated + msg: "inference of '@objc' for members of Objective-C-derived classes is deprecated" - id: objc_inference_swift3_addobjc - msg: >- - add '@objc' to continue exposing an Objective-C entry point (Swift 3 - behavior) + msg: "add '@objc' to continue exposing an Objective-C entry point (Swift 3 behavior)" - id: objc_inference_swift3_addnonobjc - msg: >- - add '@nonobjc' to suppress the Objective-C entry point (Swift 4 behavior) + msg: "add '@nonobjc' to suppress the Objective-C entry point (Swift 4 behavior)" - id: objc_for_generic_class - msg: >- - generic subclasses of '@objc' classes cannot have an explicit '@objc' - because they are not directly visible from Objective-C + msg: "generic subclasses of '@objc' classes cannot have an explicit '@objc' because they are not directly visible from Objective-C" - id: objc_for_resilient_class - msg: >- - explicit '@objc' on subclass of %0 requires %1 %2 + msg: "explicit '@objc' on subclass of %0 requires %1 %2" - id: objc_getter_for_nonobjc_property - msg: >- - '@objc' getter for non-'@objc' property + msg: "'@objc' getter for non-'@objc' property" - id: objc_getter_for_nonobjc_subscript - msg: >- - '@objc' getter for non-'@objc' subscript + msg: "'@objc' getter for non-'@objc' subscript" - id: objc_setter_for_nonobjc_property - msg: >- - '@objc' setter for non-'@objc' property + msg: "'@objc' setter for non-'@objc' property" - id: objc_setter_for_nonobjc_subscript - msg: >- - '@objc' setter for non-'@objc' subscript + msg: "'@objc' setter for non-'@objc' subscript" - id: accessor_swift3_objc_inference - msg: >- - %select{%0 %1|%1}2 with '@objc' %select{getter|setter}3 depends on - deprecated inference of '@objc' + msg: "%select{%0 %1|%1}2 with '@objc' %select{getter|setter}3 depends on deprecated inference of '@objc'" - id: objc_enum_generic - msg: >- - '@objc' enum cannot be generic + msg: "'@objc' enum cannot be generic" - id: objc_name_req_nullary - msg: >- - '@objc' %0 must have a simple name + msg: "'@objc' %0 must have a simple name" - id: objc_name_subscript - msg: >- - '@objc' subscript cannot have a name; did you mean to put the name on the - getter or setter? + msg: "'@objc' subscript cannot have a name; did you mean to put the name on the getter or setter?" - id: objc_name_deinit - msg: >- - '@objc' deinitializer cannot have a name + msg: "'@objc' deinitializer cannot have a name" - id: objc_name_func_mismatch - msg: >- - '@objc' %select{initializer|method}0 name provides %select{one argument - name|names for %1 arguments}2, but %select{initializer|method}0 has - %select{one parameter|%3 parameters}4%select{| - (%select{|including }4the error parameter)}5 + msg: "'@objc' %select{initializer|method}0 name provides %select{one argument name|names for %1 arguments}2, but %select{initializer|method}0 has %select{one parameter|%3 parameters}4%select{| (%select{|including }4the error parameter)}5" - id: objc_enum_case_req_name - msg: >- - attribute has no effect; cases within an '@objc' enum are already exposed - to Objective-C + msg: "attribute has no effect; cases within an '@objc' enum are already exposed to Objective-C" - id: objc_enum_case_req_objc_enum - msg: >- - '@objc' enum case is not allowed outside of an '@objc' enum + msg: "'@objc' enum case is not allowed outside of an '@objc' enum" - id: objc_enum_case_multi - msg: >- - '@objc' enum case declaration defines multiple enum cases with the same - Objective-C name + msg: "'@objc' enum case declaration defines multiple enum cases with the same Objective-C name" - id: objc_extension_not_class - msg: >- - '@objc' can only be applied to an extension of a class + msg: "'@objc' can only be applied to an extension of a class" - id: attribute_meaningless_when_nonobjc - msg: >- - '@%0' attribute is meaningless on a property that cannot be represented - in Objective-C + msg: "'@%0' attribute is meaningless on a property that cannot be represented in Objective-C" - id: objc_invalid_on_var - msg: >- - property cannot be %select{marked @_cdecl|marked dynamic|marked - @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked - @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc - override|an implementation of an @objc requirement|marked - @IBInspectable|marked @GKInspectable|in an @objc extension of a class - (without @nonobjc)}0 because its type cannot be represented in Objective-C + msg: "property cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}0 because its type cannot be represented in Objective-C" - id: objc_invalid_on_subscript - msg: >- - subscript cannot be %select{marked @_cdecl|marked dynamic|marked - @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked - @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc - override|an implementation of an @objc requirement|marked - @IBInspectable|marked @GKInspectable|in an @objc extension of a class - (without @nonobjc)}0 because its type cannot be represented in Objective-C + msg: "subscript cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}0 because its type cannot be represented in Objective-C" - id: objc_invalid_on_static_subscript - msg: >- - %0 cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked - @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member - of an @objc protocol|implicitly @objc|an @objc override|an implementation of - an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc - extension of a class (without @nonobjc)}1 + msg: "%0 cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}1" - id: objc_invalid_with_generic_params - msg: >- - %0 cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked - @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member - of an @objc protocol|implicitly @objc|an @objc override|an implementation of - an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc - extension of a class (without @nonobjc)}1 because it has generic parameters + msg: "%0 cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}1 because it has generic parameters" - id: objc_convention_invalid - msg: >- - %0 is not representable in Objective-C, so it cannot be used with - '@convention(%1)' + msg: "%0 is not representable in Objective-C, so it cannot be used with '@convention(%1)'" - id: paren_void_probably_void - msg: >- - when calling this function in Swift 4 or later, you must pass a '()' - tuple; did you mean for the input type to be '()'? + msg: "when calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'?" - id: not_objc_empty_protocol_composition - msg: >- - 'Any' is not considered '@objc'; use 'AnyObject' instead + msg: "'Any' is not considered '@objc'; use 'AnyObject' instead" - id: not_objc_protocol - msg: >- - protocol-constrained type containing protocol %0 cannot be represented in - Objective-C + msg: "protocol-constrained type containing protocol %0 cannot be represented in Objective-C" - id: not_objc_class_constraint - msg: >- - protocol-constrained type containing class %0 cannot be represented in - Objective-C + msg: "protocol-constrained type containing class %0 cannot be represented in Objective-C" - id: not_objc_error_protocol_composition - msg: >- - protocol-constrained type containing 'Error' cannot be represented in - Objective-C + msg: "protocol-constrained type containing 'Error' cannot be represented in Objective-C" - id: not_objc_empty_tuple - msg: >- - empty tuple type cannot be represented in Objective-C + msg: "empty tuple type cannot be represented in Objective-C" - id: not_objc_tuple - msg: >- - tuples cannot be represented in Objective-C + msg: "tuples cannot be represented in Objective-C" - id: not_objc_swift_class - msg: >- - classes not annotated with @objc cannot be represented in Objective-C + msg: "classes not annotated with @objc cannot be represented in Objective-C" - id: not_objc_swift_struct - msg: >- - Swift structs cannot be represented in Objective-C + msg: "Swift structs cannot be represented in Objective-C" - id: not_objc_swift_enum - msg: >- - non-'@objc' enums cannot be represented in Objective-C + msg: "non-'@objc' enums cannot be represented in Objective-C" - id: not_objc_generic_type_param - msg: >- - generic type parameters cannot be represented in Objective-C + msg: "generic type parameters cannot be represented in Objective-C" - id: not_objc_function_type_param - msg: >- - function types cannot be represented in Objective-C unless their - parameters and returns can be + msg: "function types cannot be represented in Objective-C unless their parameters and returns can be" - id: not_objc_function_type_throwing - msg: >- - throwing function types cannot be represented in Objective-C + msg: "throwing function types cannot be represented in Objective-C" - id: objc_inferring_on_objc_protocol_member - msg: >- - inferring '@objc' because the declaration is a member of an '@objc' protocol + msg: "inferring '@objc' because the declaration is a member of an '@objc' protocol" - id: objc_overriding_objc_decl - msg: >- - overriding '@objc' %select{property|subscript|initializer|method}0 %1 here + msg: "overriding '@objc' %select{property|subscript|initializer|method}0 %1 here" - id: objc_witness_objc_requirement - msg: >- - satisfying requirement for %0 %1 in protocol %2 + msg: "satisfying requirement for %0 %1 in protocol %2" - id: witness_swift3_objc_inference - msg: >- - use of %0 %1 to satisfy a requirement of protocol %2 depends on '@objc' - inference deprecated in Swift 4 + msg: "use of %0 %1 to satisfy a requirement of protocol %2 depends on '@objc' inference deprecated in Swift 4" - id: no_opaque_return_type_of - msg: >- - unable to resolve type for _opaqueReturnTypeOf attribute + msg: "unable to resolve type for _opaqueReturnTypeOf attribute" - id: objc_observing_accessor - msg: >- - observing accessors are not allowed to be marked @objc + msg: "observing accessors are not allowed to be marked @objc" - id: objc_addressor - msg: >- - addressors are not allowed to be marked @objc + msg: "addressors are not allowed to be marked @objc" - id: objc_coroutine_accessor - msg: >- - 'read' and 'modify' accessors are not allowed to be marked @objc + msg: "'read' and 'modify' accessors are not allowed to be marked @objc" - id: objc_invalid_on_func_variadic - msg: >- - method cannot be %select{marked @_cdecl|marked dynamic|marked - @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked - @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc - override|an implementation of an @objc requirement|marked - @IBInspectable|marked @GKInspectable|in an @objc extension of a class - (without @nonobjc)}0 because it has a variadic parameter + msg: "method cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}0 because it has a variadic parameter" - id: objc_invalid_on_func_inout - msg: >- - method cannot be %select{marked @_cdecl|marked dynamic|marked - @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked - @NSManaged|a member of an @objc protocol|implicitly @objc|an - @objc override|an implementation of an @objc requirement|marked - @IBInspectable|marked @GKInspectable|in an @objc extension of a class - (without @nonobjc)}0 because inout parameters cannot be represented in - Objective-C + msg: "method cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}0 because inout parameters cannot be represented in Objective-C" - id: objc_invalid_on_func_param_type - msg: >- - method cannot be %select{marked @_cdecl|marked dynamic|marked - @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked - @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc - override|an implementation of an @objc requirement|marked - @IBInspectable|marked @GKInspectable|in an @objc extension of a class - (without @nonobjc)}1 because the type of the parameter %0 cannot be - represented in Objective-C + msg: "method cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}1 because the type of the parameter %0 cannot be represented in Objective-C" - id: objc_invalid_on_func_single_param_type - msg: >- - method cannot be %select{marked @_cdecl|marked dynamic|marked - @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked - @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc - override|an implementation of an @objc requirement|marked - @IBInspectable|marked @GKInspectable|in an @objc extension of a class - (without @nonobjc)}0 because the type of the parameter cannot be - represented in Objective-C + msg: "method cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}0 because the type of the parameter cannot be represented in Objective-C" - id: objc_invalid_on_func_result_type - msg: >- - method cannot be %select{marked @_cdecl|marked dynamic|marked - @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked - @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc - override|an implementation of an @objc requirement|marked - @IBInspectable|marked @GKInspectable|in an @objc extension of a class - (without @nonobjc)}0 because its result type cannot be represented in - Objective-C + msg: "method cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}0 because its result type cannot be represented in Objective-C" - id: objc_invalid_on_foreign_class - msg: >- - method cannot be %select{marked @_cdecl|marked dynamic|marked - @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked - @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc - override|an implementation of an @objc requirement|marked - @IBInspectable|marked @GKInspectable|in an @objc extension of a class - (without @nonobjc)}0 because Core Foundation types are not classes in - Objective-C + msg: "method cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}0 because Core Foundation types are not classes in Objective-C" - id: objc_invalid_on_throwing_optional_result - msg: >- - throwing method cannot be %select{marked @_cdecl|marked dynamic|marked - @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked - @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc - override|an implementation of an @objc requirement|marked - @IBInspectable|marked @GKInspectable|in an @objc extension of a class - (without @nonobjc)}0 because it returns a value of optional type %1; 'nil' - indicates failure to Objective-C + msg: "throwing method cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}0 because it returns a value of optional type %1; 'nil' indicates failure to Objective-C" - id: objc_invalid_on_throwing_result - msg: >- - throwing method cannot be %select{marked @_cdecl|marked dynamic|marked - @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked - @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc - override|an implementation of an @objc requirement|marked - @IBInspectable|marked @GKInspectable|in an @objc extension of a class - (without @nonobjc)}0 because it returns a value of type %1; return 'Void' - or a type that bridges to an Objective-C class + msg: "throwing method cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}0 because it returns a value of type %1; return 'Void' or a type that bridges to an Objective-C class" - id: objc_invalid_on_failing_init - msg: >- - a failable and throwing initializer cannot be %select{marked - @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked - @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly - @objc|an @objc override|an implementation of an @objc requirement|marked - @IBInspectable|marked @GKInspectable|in an @objc extension of a class - (without @nonobjc)}0 because 'nil' indicates failure to Objective-C + msg: "a failable and throwing initializer cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}0 because 'nil' indicates failure to Objective-C" - id: objc_in_objc_runtime_visible - msg: >- - %0 cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked - @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member - of an @objc protocol|implicitly @objc|an @objc override|an implementation of - an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an - @objc extension of a class (without @nonobjc)}1 because class %2 is only - visible via the Objective-C runtime + msg: "%0 cannot be %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}1 because class %2 is only visible via the Objective-C runtime" - id: objc_override_method_selector_mismatch - msg: >- - Objective-C method has a different selector from the method it overrides - (%0 vs. %1) + msg: "Objective-C method has a different selector from the method it overrides (%0 vs. %1)" - id: objc_override_property_name_mismatch - msg: >- - Objective-C property has a different name from the property it overrides - (%0 vs. %1) + msg: "Objective-C property has a different name from the property it overrides (%0 vs. %1)" - id: objc_ambiguous_inference - msg: >- - ambiguous inference of Objective-C name for %0 %1 (%2 vs %3) + msg: "ambiguous inference of Objective-C name for %0 %1 (%2 vs %3)" - id: objc_ambiguous_inference_candidate - msg: >- - %0 (in protocol %1) provides Objective-C name %2 + msg: "%0 (in protocol %1) provides Objective-C name %2" - id: objc_ambiguous_error_convention - msg: >- - %0 overrides or implements protocol requirements for Objective-C - declarations with incompatible error argument conventions + msg: "%0 overrides or implements protocol requirements for Objective-C declarations with incompatible error argument conventions" - id: objc_ambiguous_error_convention_candidate - msg: >- - %0 provides an error argument here + msg: "%0 provides an error argument here" - id: nonlocal_bridged_to_objc - msg: >- - conformance of %0 to %1 can only be written in module %2 + msg: "conformance of %0 to %1 can only be written in module %2" - id: missing_bridging_function - msg: >- - missing - '%select{_forceBridgeFromObjectiveC|_conditionallyBridgeFromObjectiveC}0' + msg: "missing '%select{_forceBridgeFromObjectiveC|_conditionallyBridgeFromObjectiveC}0'" - id: objc_redecl - msg: >- - %select{initializer %1|implicit initializer %1|deinitializer|implicit - deinitializer|method %1|getter for %1|subscript getter|setter for - %1|subscript setter}0 with Objective-C selector %4 conflicts with - %select{initializer %3|implicit initializer %3|deinitializer|implicit - deinitializer|method %3|getter for %3|subscript getter|setter - for %3|subscript setter}2 with the same Objective-C selector + msg: "%select{initializer %1|implicit initializer %1|deinitializer|implicit deinitializer|method %1|getter for %1|subscript getter|setter for %1|subscript setter}0 with Objective-C selector %4 conflicts with %select{initializer %3|implicit initializer %3|deinitializer|implicit deinitializer|method %3|getter for %3|subscript getter|setter for %3|subscript setter}2 with the same Objective-C selector" - id: objc_declared_here - msg: >- - %select{initializer %1|implicit initializer %1|deinitializer|implicit - deinitializer|method %1|getter for %1|subscript getter|setter for - %1|subscript setter}0 declared here + msg: "%select{initializer %1|implicit initializer %1|deinitializer|implicit deinitializer|method %1|getter for %1|subscript getter|setter for %1|subscript setter}0 declared here" - id: objc_redecl_same - msg: >- - %select{initializer %1|implicit initializer %1|deinitializer|implicit - deinitializer|method %1|getter for %1|subscript getter|setter for - %1|subscript setter}0 with Objective-C selector %2 conflicts with previous - declaration with the same Objective-C selector + msg: "%select{initializer %1|implicit initializer %1|deinitializer|implicit deinitializer|method %1|getter for %1|subscript getter|setter for %1|subscript setter}0 with Objective-C selector %2 conflicts with previous declaration with the same Objective-C selector" - id: objc_override_other - msg: >- - %select{initializer %1|implicit initializer %1|deinitializer|implicit - deinitializer|method %1|getter for %1|subscript getter|setter for - %1|subscript setter}0 with Objective-C selector %4 conflicts with - %select{initializer %3|implicit initializer %3|deinitializer|implicit - deinitializer|method %3|getter for %3|subscript getter|setter for - %3|subscript setter}2 from superclass %5 with the same Objective-C selector + msg: "%select{initializer %1|implicit initializer %1|deinitializer|implicit deinitializer|method %1|getter for %1|subscript getter|setter for %1|subscript setter}0 with Objective-C selector %4 conflicts with %select{initializer %3|implicit initializer %3|deinitializer|implicit deinitializer|method %3|getter for %3|subscript getter|setter for %3|subscript setter}2 from superclass %5 with the same Objective-C selector" - id: objc_class_method_not_permitted - msg: >- - %select{initializer %1|implicit initializer %1|deinitializer|implicit - deinitializer|method %1|getter for %1|subscript getter|setter for - %1|subscript setter}0 defines Objective-C class method %2, which is not - permitted by Swift + msg: "%select{initializer %1|implicit initializer %1|deinitializer|implicit deinitializer|method %1|getter for %1|subscript getter|setter for %1|subscript setter}0 defines Objective-C class method %2, which is not permitted by Swift" - id: objc_witness_selector_mismatch - msg: >- - Objective-C method %2 provided by %select{initializer %1|implicit - initializer %1|deinitializer|implicit deinitializer|method %1|getter for - %1|subscript getter|setter for %1|subscript setter}0 does not match the - requirement's selector (%3) + msg: "Objective-C method %2 provided by %select{initializer %1|implicit initializer %1|deinitializer|implicit deinitializer|method %1|getter for %1|subscript getter|setter for %1|subscript setter}0 does not match the requirement's selector (%3)" - id: objc_optional_requirement_conflict - msg: >- - Objective-C method %4 provided by %select{initializer %1|implicit - initializer %1|deinitializer|implicit deinitializer|method %1|getter for - %1|subscript getter|setter for %1|subscript setter}0 conflicts with optional - requirement %select{initializer %3|implicit initializer - %3|deinitializer|implicit deinitializer|method %3|getter for %3|subscript - getter|setter for %3|subscript setter}2 in protocol %5 + msg: "Objective-C method %4 provided by %select{initializer %1|implicit initializer %1|deinitializer|implicit deinitializer|method %1|getter for %1|subscript getter|setter for %1|subscript setter}0 conflicts with optional requirement %select{initializer %3|implicit initializer %3|deinitializer|implicit deinitializer|method %3|getter for %3|subscript getter|setter for %3|subscript setter}2 in protocol %5" - id: objc_optional_requirement_swift_rename - msg: >- - rename %select{method|initializer|property|subscript}0 to match - requirement %1 + msg: "rename %select{method|initializer|property|subscript}0 to match requirement %1" - id: witness_non_objc - msg: >- - non-'@objc' %select{initializer %1|implicit initializer - %1|deinitializer|implicit deinitializer|method %1|getter for %1|subscript - getter|setter for %1|subscript setter}0 does not satisfy requirement of - '@objc' protocol %2 + msg: "non-'@objc' %select{initializer %1|implicit initializer %1|deinitializer|implicit deinitializer|method %1|getter for %1|subscript getter|setter for %1|subscript setter}0 does not satisfy requirement of '@objc' protocol %2" - id: witness_non_objc_optional - msg: >- - non-'@objc' %select{initializer %1|implicit initializer - %1|deinitializer|implicit deinitializer|method %1|getter for %1|subscript - getter|setter for %1|subscript setter}0 does not satisfy optional - requirement of '@objc' protocol %2 + msg: "non-'@objc' %select{initializer %1|implicit initializer %1|deinitializer|implicit deinitializer|method %1|getter for %1|subscript getter|setter for %1|subscript setter}0 does not satisfy optional requirement of '@objc' protocol %2" - id: witness_non_objc_storage - msg: >- - non-'@objc' %select{property %1|subscript}0 does not satisfy requirement - of '@objc' protocol %2 + msg: "non-'@objc' %select{property %1|subscript}0 does not satisfy requirement of '@objc' protocol %2" - id: witness_non_objc_storage_optional - msg: >- - non-'@objc' %select{property %1|subscript}0 does not satisfy optional - requirement of '@objc' protocol %2 + msg: "non-'@objc' %select{property %1|subscript}0 does not satisfy optional requirement of '@objc' protocol %2" - id: nonobjc_not_allowed - msg: >- - declaration is %select{marked @_cdecl|marked dynamic|marked @objc|marked - @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a - member of an @objc protocol|implicitly @objc|an @objc override|an - implementation of an @objc requirement|marked @IBInspectable|marked - @GKInspectable|in an @objc extension of a class (without @nonobjc)}0, - and cannot be marked @nonobjc + msg: "declaration is %select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}0, and cannot be marked @nonobjc" - id: borrowed_with_objc_dynamic - msg: >- - %0 cannot be '@_borrowed' if it is '@objc dynamic' + msg: "%0 cannot be '@_borrowed' if it is '@objc dynamic'" - id: borrowed_on_objc_protocol_requirement - msg: >- - %0 cannot be '@_borrowed' if it is an @objc protocol requirement + msg: "%0 cannot be '@_borrowed' if it is an @objc protocol requirement" - id: dynamic_with_transparent - msg: >- - a declaration cannot be both '@_tranparent' and 'dynamic' + msg: "a declaration cannot be both '@_tranparent' and 'dynamic'" - id: dynamic_replacement_accessor_type_mismatch - msg: >- - replaced accessor %0's type does not match + msg: "replaced accessor %0's type does not match" - id: dynamic_replacement_accessor_not_dynamic - msg: >- - replaced accessor for %0 is not marked dynamic + msg: "replaced accessor for %0 is not marked dynamic" - id: dynamic_replacement_accessor_not_explicit - msg: >- - replaced accessor - %select{get|set|_read|_modify|willSet|didSet|unsafeAddress|addressWithOwner|addressWithNativeOwner|unsafeMutableAddress|mutableAddressWithOwner|}0 - for %1 is not explicitly defined + msg: "replaced accessor %select{get|set|_read|_modify|willSet|didSet|unsafeAddress|addressWithOwner|addressWithNativeOwner|unsafeMutableAddress|mutableAddressWithOwner|}0 for %1 is not explicitly defined" - id: dynamic_replacement_function_not_dynamic - msg: >- - replaced function %0 is not marked dynamic + msg: "replaced function %0 is not marked dynamic" - id: dynamic_replacement_function_not_found - msg: >- - replaced function %0 could not be found + msg: "replaced function %0 could not be found" - id: dynamic_replacement_accessor_not_found - msg: >- - replaced accessor for %0 could not be found + msg: "replaced accessor for %0 could not be found" - id: dynamic_replacement_accessor_ambiguous - msg: >- - replaced accessor for %0 occurs in multiple places + msg: "replaced accessor for %0 occurs in multiple places" - id: dynamic_replacement_accessor_ambiguous_candidate - msg: >- - candidate accessor found in module %0 + msg: "candidate accessor found in module %0" - id: dynamic_replacement_function_of_type_not_found - msg: >- - replaced function %0 of type %1 could not be found + msg: "replaced function %0 of type %1 could not be found" - id: dynamic_replacement_found_function_of_type - msg: >- - found function %0 of type %1 + msg: "found function %0 of type %1" - id: dynamic_replacement_not_in_extension - msg: >- - dynamicReplacement(for:) of %0 is not defined in an extension or at the - file level + msg: "dynamicReplacement(for:) of %0 is not defined in an extension or at the file level" - id: dynamic_replacement_must_not_be_dynamic - msg: >- - dynamicReplacement(for:) of %0 must not be dynamic itself + msg: "dynamicReplacement(for:) of %0 must not be dynamic itself" - id: dynamic_replacement_replaced_not_objc_dynamic - msg: >- - %0 is not marked @objc dynamic + msg: "%0 is not marked @objc dynamic" - id: dynamic_replacement_replacement_not_objc_dynamic - msg: >- - %0 is marked @objc dynamic + msg: "%0 is marked @objc dynamic" - id: dynamic_replacement_replaced_constructor_is_convenience - msg: >- - replaced constructor %0 is marked as convenience + msg: "replaced constructor %0 is marked as convenience" - id: dynamic_replacement_replaced_constructor_is_not_convenience - msg: >- - replaced constructor %0 is not marked as convenience + msg: "replaced constructor %0 is not marked as convenience" - id: non_nominal_type_eraser - msg: >- - type eraser must be a class, struct, or enum + msg: "type eraser must be a class, struct, or enum" - id: type_eraser_does_not_conform - msg: >- - type eraser %0 must conform to protocol %1 + msg: "type eraser %0 must conform to protocol %1" - id: type_eraser_not_accessible - msg: >- - %select{private|fileprivate|internal|public|open}0 type eraser %1 cannot - have more restrictive access than protocol %2 (which is - %select{private|fileprivate|internal|public|open}3) + msg: "%select{private|fileprivate|internal|public|open}0 type eraser %1 cannot have more restrictive access than protocol %2 (which is %select{private|fileprivate|internal|public|open}3)" - id: type_eraser_missing_init - msg: >- - type eraser %0 must have an initializer of the form 'init(erasing: - T)' + msg: "type eraser %0 must have an initializer of the form 'init(erasing: T)'" - id: type_eraser_unviable_init - msg: >- - type eraser %0 has no viable initializer of the form 'init(erasing: T)' + msg: "type eraser %0 has no viable initializer of the form 'init(erasing: T)'" - id: type_eraser_declared_here - msg: >- - type eraser declared here + msg: "type eraser declared here" - id: type_eraser_failable_init - msg: >- - 'init(erasing:)' cannot be failable + msg: "'init(erasing:)' cannot be failable" - id: type_eraser_init_unsatisfied_requirements - msg: >- - 'init(erasing:)' cannot have unsatisfied requirements when %0 = 'some %1' + msg: "'init(erasing:)' cannot have unsatisfied requirements when %0 = 'some %1'" - id: type_eraser_init_not_accessible - msg: >- - %select{private|fileprivate|internal|public|open}0 'init(erasing:)' - cannot have more restrictive access than protocol %1 (which is - %select{private|fileprivate|internal|public|open}2) + msg: "%select{private|fileprivate|internal|public|open}0 'init(erasing:)' cannot have more restrictive access than protocol %1 (which is %select{private|fileprivate|internal|public|open}2)" - id: availability_decl_unavailable - msg: >- - %select{getter for |setter for |}0%1 is unavailable%select{ in - %3|}2%select{|: %4}4 + msg: "%select{getter for |setter for |}0%1 is unavailable%select{ in %3|}2%select{|: %4}4" - id: availability_decl_unavailable_warn - msg: >- - %select{getter for |setter for |}0%1 is unavailable%select{ in - %3|}2%select{|: %4}4 + msg: "%select{getter for |setter for |}0%1 is unavailable%select{ in %3|}2%select{|: %4}4" - id: availability_decl_unavailable_rename - msg: >- - %select{getter for |setter for |}0%1 has been %select{renamed to|replaced - by}2%select{| instance method| property}3 '%4'%select{|: %5}5 + msg: "%select{getter for |setter for |}0%1 has been %select{renamed to|replaced by}2%select{| instance method| property}3 '%4'%select{|: %5}5" - id: availability_decl_unavailable_rename_warn - msg: >- - %select{getter for |setter for |}0%1 has been %select{renamed to|replaced - by}2%select{| instance method| property}3 '%4'%select{|: %5}5 + msg: "%select{getter for |setter for |}0%1 has been %select{renamed to|replaced by}2%select{| instance method| property}3 '%4'%select{|: %5}5" - id: availability_marked_unavailable - msg: >- - %select{getter for |setter for |}0%1 has been explicitly marked - unavailable here + msg: "%select{getter for |setter for |}0%1 has been explicitly marked unavailable here" - id: availability_introduced_in_version - msg: >- - %select{getter for |setter for |}0%1 was introduced in %2 %3 + msg: "%select{getter for |setter for |}0%1 was introduced in %2 %3" - id: availability_obsoleted - msg: >- - %select{getter for |setter for |}0%1 was obsoleted in %2 %3 + msg: "%select{getter for |setter for |}0%1 was obsoleted in %2 %3" - id: availability_deprecated - msg: >- - %select{getter for |setter for |}0%1 %select{is|%select{is|was}4}2 - deprecated%select{| in %3%select{| %5}4}2%select{|: %6}6 + msg: "%select{getter for |setter for |}0%1 %select{is|%select{is|was}4}2 deprecated%select{| in %3%select{| %5}4}2%select{|: %6}6" - id: availability_deprecated_rename - msg: >- - %select{getter for |setter for |}0%1 %select{is|%select{is|was}4}2 - deprecated%select{| in %3%select{| %5}4}2: %select{renamed to|replaced - by}6%select{| instance method| property}7 '%8' + msg: "%select{getter for |setter for |}0%1 %select{is|%select{is|was}4}2 deprecated%select{| in %3%select{| %5}4}2: %select{renamed to|replaced by}6%select{| instance method| property}7 '%8'" - id: note_deprecated_rename - msg: >- - use '%0' instead + msg: "use '%0' instead" - id: availability_decl_more_than_enclosing - msg: >- - declaration cannot be more available than enclosing scope + msg: "declaration cannot be more available than enclosing scope" - id: availability_decl_more_than_enclosing_enclosing_here - msg: >- - enclosing scope here + msg: "enclosing scope here" - id: availability_decl_only_version_newer - msg: >- - %0 is only available in %1 %2 or newer + msg: "%0 is only available in %1 %2 or newer" - id: availability_opaque_types_only_version_newer - msg: >- - 'some' return types are only available in %0 %1 or newer + msg: "'some' return types are only available in %0 %1 or newer" - id: availability_guard_with_version_check - msg: >- - add 'if #available' version check + msg: "add 'if #available' version check" - id: availability_add_attribute - msg: >- - add @available attribute to enclosing %0 + msg: "add @available attribute to enclosing %0" - id: availability_accessor_only_version_newer - msg: >- - %select{getter|setter}0 for %1 is only available in %2 %3 or newer + msg: "%select{getter|setter}0 for %1 is only available in %2 %3 or newer" - id: availability_inout_accessor_only_version_newer - msg: >- - cannot pass as inout because %select{getter|setter}0 for %1 is only - available in %2 %3 or newer + msg: "cannot pass as inout because %select{getter|setter}0 for %1 is only available in %2 %3 or newer" - id: availability_query_required_for_platform - msg: >- - condition required for target platform '%0' + msg: "condition required for target platform '%0'" - id: availability_query_useless_enclosing_scope - msg: >- - unnecessary check for '%0'; enclosing scope ensures guard will always be - true + msg: "unnecessary check for '%0'; enclosing scope ensures guard will always be true" - id: availability_query_useless_enclosing_scope_here - msg: >- - enclosing scope here + msg: "enclosing scope here" - id: availability_global_script_no_potential - msg: >- - global variable cannot be marked potentially unavailable with - '@available' in script mode + msg: "global variable cannot be marked potentially unavailable with '@available' in script mode" - id: availability_stored_property_no_potential - msg: >- - stored properties cannot be marked potentially unavailable with - '@available' + msg: "stored properties cannot be marked potentially unavailable with '@available'" - id: availability_protocol_requires_version - msg: >- - protocol %0 requires %1 to be available in %2 %3 and newer + msg: "protocol %0 requires %1 to be available in %2 %3 and newer" - id: availability_protocol_requirement_here - msg: >- - protocol requirement here + msg: "protocol requirement here" - id: public_decl_needs_availability - msg: >- - public declarations should have an availability attribute when building - with -require-explicit-availability + msg: "public declarations should have an availability attribute when building with -require-explicit-availability" - id: availabilty_string_subscript_migration - msg: >- - subscripts returning String were obsoleted in Swift 4; explicitly - construct a String from subscripted result + msg: "subscripts returning String were obsoleted in Swift 4; explicitly construct a String from subscripted result" - id: discardable_result_on_void_never_function - msg: >- - @discardableResult declared on a function returning %select{Never|Void}0 - is unnecessary + msg: "@discardableResult declared on a function returning %select{Never|Void}0 is unnecessary" - id: fixed_layout_attr_on_internal_type - msg: >- - '@_fixed_layout' attribute can only be applied to '@usableFromInline' or - public declarations, but %0 is - %select{private|fileprivate|internal|%error|%error}1 + msg: "'@_fixed_layout' attribute can only be applied to '@usableFromInline' or public declarations, but %0 is %select{private|fileprivate|internal|%error|%error}1" - id: fixed_layout_struct - msg: >- - '@frozen' attribute is now used for fixed-layout structs + msg: "'@frozen' attribute is now used for fixed-layout structs" - id: frozen_attr_on_internal_type - msg: >- - '@frozen' attribute can only be applied to '@usableFromInline' or public - declarations, but %0 is %select{private|fileprivate|internal|%error|%error}1 + msg: "'@frozen' attribute can only be applied to '@usableFromInline' or public declarations, but %0 is %select{private|fileprivate|internal|%error|%error}1" - id: usable_from_inline_attr_with_explicit_access - msg: >- - '@usableFromInline' attribute can only be applied to internal - declarations, but %0 is %select{private|fileprivate|%error|public|open}1 + msg: "'@usableFromInline' attribute can only be applied to internal declarations, but %0 is %select{private|fileprivate|%error|public|open}1" - id: inlinable_implies_usable_from_inline - msg: >- - '@inlinable' declaration is already '@usableFromInline' + msg: "'@inlinable' declaration is already '@usableFromInline'" - id: usable_from_inline_attr_in_protocol - msg: >- - '@usableFromInline' attribute cannot be used in protocols + msg: "'@usableFromInline' attribute cannot be used in protocols" - id: local_type_in_inlinable_function - msg: >- - type %0 cannot be nested inside %select{a '@_transparent' function|an - '@inlinable' function|an '@_alwaysEmitIntoClient' function|a default - argument value|a property initializer in a '@frozen' type}1 + msg: "type %0 cannot be nested inside %select{a '@_transparent' function|an '@inlinable' function|an '@_alwaysEmitIntoClient' function|a default argument value|a property initializer in a '@frozen' type}1" - id: resilience_decl_unavailable - msg: >- - %select{%0|%0 for}4 %1 is - %select{private|fileprivate|internal|'@_spi'|'@_spi'}2 and cannot be - referenced from %select{a '@_transparent' function|an '@inlinable' - function|an '@_alwaysEmitIntoClient' function|a default argument value|a - property initializer in a '@frozen' type}3 + msg: "%select{%0|%0 for}4 %1 is %select{private|fileprivate|internal|'@_spi'|'@_spi'}2 and cannot be referenced from %select{a '@_transparent' function|an '@inlinable' function|an '@_alwaysEmitIntoClient' function|a default argument value|a property initializer in a '@frozen' type}3" - id: resilience_decl_unavailable_warn - msg: >- - %select{%0|%0 for}4 %1 is - %select{private|fileprivate|internal|'@_spi'|'@_spi'}2 and should not be - referenced from %select{a '@_transparent' function|an '@inlinable' - function|an '@_alwaysEmitIntoClient' function|a default argument value|a - property initializer in a '@frozen' type}3 + msg: "%select{%0|%0 for}4 %1 is %select{private|fileprivate|internal|'@_spi'|'@_spi'}2 and should not be referenced from %select{a '@_transparent' function|an '@inlinable' function|an '@_alwaysEmitIntoClient' function|a default argument value|a property initializer in a '@frozen' type}3" - id: inlinable_decl_ref_from_hidden_module - msg: >- - %0 %1 cannot be used in %select{a '@_transparent' function|an - '@inlinable' function|an '@_alwaysEmitIntoClient' function|a default - argument value|a property initializer in a '@frozen' type}2 because - %select{%3 was imported implementation-only|it is an SPI imported from - %3|it is SPI}4 + msg: "%0 %1 cannot be used in %select{a '@_transparent' function|an '@inlinable' function|an '@_alwaysEmitIntoClient' function|a default argument value|a property initializer in a '@frozen' type}2 because %select{%3 was imported implementation-only|it is an SPI imported from %3|it is SPI}4" - id: resilience_decl_declared_here_public - msg: >- - %select{%0|%0 for}2 %1 is not public + msg: "%select{%0|%0 for}2 %1 is not public" - id: resilience_decl_declared_here - msg: >- - %select{%0|%0 for}2 %1 is not '@usableFromInline' or public + msg: "%select{%0|%0 for}2 %1 is not '@usableFromInline' or public" - id: class_designated_init_inlinable_resilient - msg: >- - initializer for class %0 is - '%select{@_transparent|@inlinable|@_alwaysEmitIntoClient|%error}1' - and must delegate to another initializer + msg: "initializer for class %0 is '%select{@_transparent|@inlinable|@_alwaysEmitIntoClient|%error}1' and must delegate to another initializer" - id: attribute_invalid_on_stored_property - msg: >- - '%0' attribute cannot be applied to stored properties + msg: "'%0' attribute cannot be applied to stored properties" - id: inlinable_dynamic_not_supported - msg: >- - '@inlinable' attribute cannot be applied to 'dynamic' declarations + msg: "'@inlinable' attribute cannot be applied to 'dynamic' declarations" - id: inlinable_decl_not_public - msg: >- - '@inlinable' attribute can only be applied to public declarations, but %0 - is %select{private|fileprivate|internal|%error|%error}1 + msg: "'@inlinable' attribute can only be applied to public declarations, but %0 is %select{private|fileprivate|internal|%error|%error}1" - id: inlinable_resilient_deinit - msg: >- - deinitializer can only be '@inlinable' if the class is '@_fixed_layout' + msg: "deinitializer can only be '@inlinable' if the class is '@_fixed_layout'" - id: specialize_attr_nongeneric_trailing_where - msg: >- - trailing 'where' clause in '_specialize' attribute of non-generic - function %0 + msg: "trailing 'where' clause in '_specialize' attribute of non-generic function %0" - id: specialize_missing_where_clause - msg: >- - missing 'where' clause in '_specialize' attribute + msg: "missing 'where' clause in '_specialize' attribute" - id: specialize_empty_where_clause - msg: >- - empty 'where' clause in '_specialize' attribute + msg: "empty 'where' clause in '_specialize' attribute" - id: specialize_attr_non_concrete_same_type_req - msg: >- - Only concrete type same-type requirements are supported by '_specialize' - attribute + msg: "Only concrete type same-type requirements are supported by '_specialize' attribute" - id: specialize_attr_only_generic_param_req - msg: >- - Only requirements on generic parameters are supported by '_specialize' - attribute + msg: "Only requirements on generic parameters are supported by '_specialize' attribute" - id: specialize_attr_only_one_concrete_same_type_req - msg: >- - Only one concrete type should be used in the same-type requirement in - '_specialize' attribute + msg: "Only one concrete type should be used in the same-type requirement in '_specialize' attribute" - id: specialize_attr_non_protocol_type_constraint_req - msg: >- - Only conformances to protocol types are supported by '_specialize' attribute + msg: "Only conformances to protocol types are supported by '_specialize' attribute" - id: specialize_attr_type_parameter_count_mismatch - msg: >- - %select{too many|too few}2 type parameters are specified in '_specialize' - attribute (got %1, but expected %0) + msg: "%select{too many|too few}2 type parameters are specified in '_specialize' attribute (got %1, but expected %0)" - id: specialize_attr_missing_constraint - msg: >- - Missing constraint for %0 in '_specialize' attribute + msg: "Missing constraint for %0 in '_specialize' attribute" - id: specialize_attr_unsupported_kind_of_req - msg: >- - Only same-type and layout requirements are supported by '_specialize' - attribute + msg: "Only same-type and layout requirements are supported by '_specialize' attribute" - id: pbd_never_used_stmtcond - msg: >- - value %0 was defined but never used; consider replacing with boolean test + msg: "value %0 was defined but never used; consider replacing with boolean test" - id: unused_setter_parameter - msg: >- - setter argument %0 was never used, but the property was accessed + msg: "setter argument %0 was never used, but the property was accessed" - id: fixit_for_unused_setter_parameter - msg: >- - did you mean to use %0 instead of accessing the property's current value? + msg: "did you mean to use %0 instead of accessing the property's current value?" - id: pbd_never_used - msg: >- - initialization of %select{variable|immutable value}1 %0 was never used; - consider replacing with assignment to '_' or removing it + msg: "initialization of %select{variable|immutable value}1 %0 was never used; consider replacing with assignment to '_' or removing it" - id: capture_never_used - msg: >- - capture %0 was never used + msg: "capture %0 was never used" - id: variable_never_used - msg: >- - %select{variable|immutable value}1 %0 was never used; consider replacing - with '_' or removing it + msg: "%select{variable|immutable value}1 %0 was never used; consider replacing with '_' or removing it" - id: immutable_value_never_used_but_assigned - msg: >- - immutable value %0 was never used; consider removing it + msg: "immutable value %0 was never used; consider removing it" - id: variable_never_mutated - msg: >- - variable %0 was never mutated; consider %select{removing 'var' to make - it|changing to 'let'}1 constant + msg: "variable %0 was never mutated; consider %select{removing 'var' to make it|changing to 'let'}1 constant" - id: variable_never_read - msg: >- - variable %0 was written to, but never read + msg: "variable %0 was written to, but never read" - id: observe_keypath_property_not_objc_dynamic - msg: >- - passing reference to non-'@objc dynamic' property %0 to KVO method %1 may - lead to unexpected behavior or runtime trap + msg: "passing reference to non-'@objc dynamic' property %0 to KVO method %1 may lead to unexpected behavior or runtime trap" - id: default_magic_identifier_mismatch - msg: >- - parameter %0 with default argument '%1' passed to parameter %2, whose - default argument is '%3' + msg: "parameter %0 with default argument '%1' passed to parameter %2, whose default argument is '%3'" - id: change_caller_default_to_match_callee - msg: >- - did you mean for parameter %0 to default to '%1'? + msg: "did you mean for parameter %0 to default to '%1'?" - id: silence_default_magic_identifier_mismatch - msg: >- - add parentheses to silence this warning + msg: "add parentheses to silence this warning" - id: debug_long_function_body - msg: >- - %0 %1 took %2ms to type-check (limit: %3ms) + msg: "%0 %1 took %2ms to type-check (limit: %3ms)" - id: debug_long_closure_body - msg: >- - closure took %0ms to type-check (limit: %1ms) + msg: "closure took %0ms to type-check (limit: %1ms)" - id: debug_long_expression - msg: >- - expression took %0ms to type-check (limit: %1ms) + msg: "expression took %0ms to type-check (limit: %1ms)" - id: empty_switch_stmt - msg: >- - 'switch' statement body must have at least one 'case' or 'default' block; - do you want to add a default case? + msg: "'switch' statement body must have at least one 'case' or 'default' block; do you want to add a default case?" - id: non_exhaustive_switch - msg: >- - switch must be exhaustive + msg: "switch must be exhaustive" - id: possibly_non_exhaustive_switch - msg: >- - the compiler is unable to check that this switch is exhaustive in - reasonable time + msg: "the compiler is unable to check that this switch is exhaustive in reasonable time" - id: missing_several_cases - msg: >- - do you want to add %select{missing cases|a default clause}0? + msg: "do you want to add %select{missing cases|a default clause}0?" - id: missing_unknown_case - msg: >- - handle unknown values using "@unknown default" + msg: "handle unknown values using \"@unknown default\"" - id: non_exhaustive_switch_drop_unknown - msg: >- - remove '@unknown' to handle remaining values + msg: "remove '@unknown' to handle remaining values" - id: missing_particular_case - msg: >- - add missing case: '%0' + msg: "add missing case: '%0'" - id: redundant_particular_case - msg: >- - case is already handled by previous patterns; consider removing it + msg: "case is already handled by previous patterns; consider removing it" - id: redundant_particular_literal_case - msg: >- - literal value is already handled by previous pattern; consider removing it + msg: "literal value is already handled by previous pattern; consider removing it" - id: redundant_particular_literal_case_here - msg: >- - first occurrence of identical literal pattern is here + msg: "first occurrence of identical literal pattern is here" - id: non_exhaustive_switch_warn - msg: >- - switch must be exhaustive + msg: "switch must be exhaustive" - id: non_exhaustive_switch_unknown_only - msg: >- - switch covers known cases, but %0 may have additional unknown - values%select{|, possibly added in future versions}1 + msg: "switch covers known cases, but %0 may have additional unknown values%select{|, possibly added in future versions}1" - id: override_nsobject_hashvalue_error - msg: >- - 'NSObject.hashValue' is not overridable; did you mean to override - 'NSObject.hash'? + msg: "'NSObject.hashValue' is not overridable; did you mean to override 'NSObject.hash'?" - id: hashvalue_implementation - msg: >- - 'Hashable.hashValue' is deprecated as a protocol requirement; conform - type %0 to 'Hashable' by implementing 'hash(into:)' instead + msg: "'Hashable.hashValue' is deprecated as a protocol requirement; conform type %0 to 'Hashable' by implementing 'hash(into:)' instead" - id: property_wrapper_no_value_property - msg: >- - property wrapper type %0 does not contain a non-static property named %1 + msg: "property wrapper type %0 does not contain a non-static property named %1" - id: property_wrapper_ambiguous_value_property - msg: >- - property wrapper type %0 has multiple non-static properties named %1 + msg: "property wrapper type %0 has multiple non-static properties named %1" - id: property_wrapper_wrong_initial_value_init - msg: >- - %0 parameter type (%1) must be the same as its 'wrappedValue' property - type (%2) or an @autoclosure thereof + msg: "%0 parameter type (%1) must be the same as its 'wrappedValue' property type (%2) or an @autoclosure thereof" - id: property_wrapper_failable_init - msg: >- - property wrapper initializer %0 cannot be failable + msg: "property wrapper initializer %0 cannot be failable" - id: property_wrapper_type_requirement_not_accessible - msg: >- - %select{private|fileprivate|internal|public|open}0 %1 %2 cannot have more - restrictive access than its enclosing property wrapper type %3 (which is - %select{private|fileprivate|internal|public|open}4) + msg: "%select{private|fileprivate|internal|public|open}0 %1 %2 cannot have more restrictive access than its enclosing property wrapper type %3 (which is %select{private|fileprivate|internal|public|open}4)" - id: property_wrapper_ambiguous_enclosing_self_subscript - msg: >- - property wrapper type %0 has multiple enclosing-self subscripts %1 + msg: "property wrapper type %0 has multiple enclosing-self subscripts %1" - id: property_wrapper_dynamic_self_type - msg: >- - property wrapper %select{wrapped value|projected value}0 cannot have - dynamic Self type + msg: "property wrapper %select{wrapped value|projected value}0 cannot have dynamic Self type" - id: property_wrapper_attribute_not_on_property - msg: >- - property wrapper attribute %0 can only be applied to a property + msg: "property wrapper attribute %0 can only be applied to a property" - id: property_wrapper_declared_here - msg: >- - property wrapper type %0 declared here + msg: "property wrapper type %0 declared here" - id: property_wrapper_mutating_get_composed_to_get_only - msg: >- - property wrapper %0 with a mutating getter cannot be composed inside - get-only property wrapper %1 + msg: "property wrapper %0 with a mutating getter cannot be composed inside get-only property wrapper %1" - id: property_wrapper_local - msg: >- - property wrappers are not yet supported on local properties + msg: "property wrappers are not yet supported on local properties" - id: property_wrapper_top_level - msg: >- - property wrappers are not yet supported in top-level code + msg: "property wrappers are not yet supported in top-level code" - id: property_wrapper_let - msg: >- - property wrapper can only be applied to a 'var' + msg: "property wrapper can only be applied to a 'var'" - id: property_wrapper_computed - msg: >- - property wrapper cannot be applied to a computed property + msg: "property wrapper cannot be applied to a computed property" - id: property_with_wrapper_conflict_attribute - msg: >- - property %0 with a wrapper cannot also be - %select{lazy|@NSCopying|@NSManaged|weak|unowned|unmanaged}1 + msg: "property %0 with a wrapper cannot also be %select{lazy|@NSCopying|@NSManaged|weak|unowned|unmanaged}1" - id: property_wrapper_not_single_var - msg: >- - property wrapper can only apply to a single variable + msg: "property wrapper can only apply to a single variable" - id: property_with_wrapper_in_bad_context - msg: >- - %select{|non-static |non-static }1property %0 declared inside %select{a - protocol|an extension|an enum}1 cannot have a wrapper + msg: "%select{|non-static |non-static }1property %0 declared inside %select{a protocol|an extension|an enum}1 cannot have a wrapper" - id: property_with_wrapper_overrides - msg: >- - property %0 with attached wrapper cannot override another property + msg: "property %0 with attached wrapper cannot override another property" - id: property_wrapper_direct_init - msg: >- - initialize the property wrapper type directly with '(...') on the attribute + msg: "initialize the property wrapper type directly with '(...') on the attribute" - id: property_wrapper_incompatible_property - msg: >- - property type %0 does not match that of the 'wrappedValue' property of - its wrapper type %1 + msg: "property type %0 does not match that of the 'wrappedValue' property of its wrapper type %1" + +- id: wrapped_value_mismatch + msg: "property type %0 does not match 'wrappedValue' type %1" + +- id: composed_property_wrapper_mismatch + msg: "composed wrapper type %0 does not match former 'wrappedValue' type %1" - id: property_wrapper_type_access - msg: >- - %select{%select{variable|constant}0|property}1 %select{must be declared - %select{%select{private|fileprivate|internal|%error|%error}3|private or - fileprivate}4|cannot be declared %select{in this - context|fileprivate|internal|public|open}3}2 because its property wrapper - type uses %select{a private|a fileprivate|an internal|%error|%error}5 type + msg: "%select{%select{variable|constant}0|property}1 %select{must be declared %select{%select{private|fileprivate|internal|%error|%error}3|private or fileprivate}4|cannot be declared %select{in this context|fileprivate|internal|public|open}3}2 because its property wrapper type uses %select{a private|a fileprivate|an internal|%error|%error}5 type" - id: property_wrapper_type_not_usable_from_inline - msg: >- - property wrapper type referenced from a '@usableFromInline' - %select{%select{variable|constant}0|property}1 must be '@usableFromInline' - or public + msg: "property wrapper type referenced from a '@usableFromInline' %select{%select{variable|constant}0|property}1 must be '@usableFromInline' or public" - id: property_wrapper_wrapperValue - msg: >- - property wrapper's 'wrapperValue' property should be renamed to - 'projectedValue'; use of 'wrapperValue' is deprecated + msg: "property wrapper's 'wrapperValue' property should be renamed to 'projectedValue'; use of 'wrapperValue' is deprecated" - id: property_wrapper_init_initialValue - msg: >- - property wrapper's 'init(initialValue:)' should be renamed to - 'init(wrappedValue:)'; use of 'init(initialValue:)' is deprecated + msg: "property wrapper's 'init(initialValue:)' should be renamed to 'init(wrappedValue:)'; use of 'init(initialValue:)' is deprecated" - id: property_wrapper_projection_value_missing - msg: >- - could not find projection value property %0 + msg: "could not find projection value property %0" - id: property_wrapper_missing_arg_init - msg: >- - missing argument for parameter %0 in property wrapper initializer; add - 'wrappedValue' and %0 arguments in '@%1(...)' + msg: "missing argument for parameter %0 in property wrapper initializer; add 'wrappedValue' and %0 arguments in '@%1(...)'" - id: function_builder_decl - msg: >- - closure containing a declaration cannot be used with function builder %0 + msg: "closure containing a declaration cannot be used with function builder %0" - id: note_function_builder_decl - msg: >- - closure containing a declaration cannot be used with function builder %0 + msg: "closure containing a declaration cannot be used with function builder %0" - id: function_builder_control_flow - msg: >- - closure containing control flow statement cannot be used with function - builder %0 + msg: "closure containing control flow statement cannot be used with function builder %0" - id: note_function_builder_control_flow - msg: >- - closure containing control flow statement cannot be used with function - builder %0 + msg: "closure containing control flow statement cannot be used with function builder %0" - id: function_builder_attribute_not_allowed_here - msg: >- - function builder attribute %0 can only be applied to a parameter, - function, or computed property + msg: "function builder attribute %0 can only be applied to a parameter, function, or computed property" - id: function_builder_attribute_on_storage_without_getter - msg: >- - function builder attribute %0 can only be applied to a - %select{subscript|property|constant|variable}1 if it defines a getter + msg: "function builder attribute %0 can only be applied to a %select{subscript|property|constant|variable}1 if it defines a getter" - id: function_builder_parameter_not_of_function_type - msg: >- - function builder attribute %0 can only be applied to a parameter of - function type + msg: "function builder attribute %0 can only be applied to a parameter of function type" - id: function_builder_parameter_autoclosure - msg: >- - function builder attribute %0 cannot be applied to an autoclosure parameter + msg: "function builder attribute %0 cannot be applied to an autoclosure parameter" - id: function_builder_multiple - msg: >- - only one function builder attribute can be attached to a - %select{declaration|parameter}0 + msg: "only one function builder attribute can be attached to a %select{declaration|parameter}0" - id: previous_function_builder_here - msg: >- - previous function builder specified here + msg: "previous function builder specified here" - id: function_builder_arguments - msg: >- - function builder attributes cannot have arguments + msg: "function builder attributes cannot have arguments" - id: function_builder_disabled_by_return - msg: >- - application of function builder %0 disabled by explicit 'return' - statement + msg: "application of function builder %0 disabled by explicit 'return' statement" - id: function_builder_remove_attr - msg: >- - remove the attribute to explicitly disable the function builder + msg: "remove the attribute to explicitly disable the function builder" - id: function_builder_remove_returns - msg: >- - remove 'return' statements to apply the function builder + msg: "remove 'return' statements to apply the function builder" - id: function_builder_infer_ambig - msg: >- - ambiguous function builder inferred for %0: %1 or %2 + msg: "ambiguous function builder inferred for %0: %1 or %2" - id: function_builder_infer_add_return - msg: >- - add an explicit 'return' statement to not use a function builder + msg: "add an explicit 'return' statement to not use a function builder" - id: function_builder_infer_pick_specific - msg: >- - apply function builder %0 (inferred from %select{protocol|dynamic - replacement of}1 %2) + msg: "apply function builder %0 (inferred from %select{protocol|dynamic replacement of}1 %2)" + +- id: function_builder_missing_limited_availability + msg: "function builder %0 does not implement 'buildLimitedAvailability'; this code may crash on earlier versions of the OS" - id: warn_reordering_tuple_shuffle_deprecated - msg: >- - expression shuffles the elements of this tuple; this behavior is - deprecated + msg: "expression shuffles the elements of this tuple; this behavior is deprecated" - id: differentiable_programming_attr_used_without_required_module - msg: >- - '@%0' attribute used without importing module %1 + msg: "'@%0' attribute used without importing module %1" - id: oslog_arg_must_be_bool_literal - msg: >- - argument must be a bool literal + msg: "argument must be a bool literal" - id: oslog_arg_must_be_integer_literal - msg: >- - argument must be an integer literal + msg: "argument must be an integer literal" - id: oslog_arg_must_be_string_literal - msg: >- - argument must be a string literal + msg: "argument must be a string literal" - id: oslog_arg_must_be_float_literal - msg: >- - argument must be a floating-point literal + msg: "argument must be a floating-point literal" - id: oslog_arg_must_be_metatype_literal - msg: >- - argument must be a .self + msg: "argument must be a .self" - id: oslog_arg_must_be_closure - msg: >- - argument must be a closure + msg: "argument must be a closure" - id: argument_must_be_constant - msg: >- - argument must be an expression with only literals + msg: "argument must be an expression with only literals" - id: oslog_message_must_be_string_interpolation - msg: >- - argument must be a string interpolation + msg: "argument must be a string interpolation" - id: oslog_arg_must_be_enum_case - msg: >- - argument must be a case of enum %0 + msg: "argument must be a case of enum %0" - id: oslog_arg_must_be_type_member_access - msg: >- - argument must be a static method or property of %0 + msg: "argument must be a static method or property of %0" - id: atomics_ordering_must_be_constant - msg: >- - ordering argument must be a static method or property of %0 + msg: "ordering argument must be a static method or property of %0" - id: warning_from_clang - msg: >- - %0 + msg: "%0" - id: error_from_clang - msg: >- - %0 + msg: "%0" - id: note_from_clang - msg: >- - %0 + msg: "%0" - id: remark_from_clang - msg: >- - %0 + msg: "%0" - id: clang_cannot_build_module - msg: >- - could not build %select{C|Objective-C}0 module '%1' + msg: "could not build %select{C|Objective-C}0 module '%1'" - id: bridging_header_missing - msg: >- - bridging header '%0' does not exist + msg: "bridging header '%0' does not exist" - id: bridging_header_error - msg: >- - failed to import bridging header '%0' + msg: "failed to import bridging header '%0'" - id: could_not_rewrite_bridging_header - msg: >- - failed to serialize bridging header; target may not be debuggable outside - of its original project + msg: "failed to serialize bridging header; target may not be debuggable outside of its original project" - id: bridging_header_pch_error - msg: >- - failed to emit precompiled header '%0' for bridging header '%1' + msg: "failed to emit precompiled header '%0' for bridging header '%1'" - id: emit_pcm_error - msg: >- - failed to emit precompiled module '%0' for module map '%1' + msg: "failed to emit precompiled module '%0' for module map '%1'" - id: dump_pcm_error - msg: >- - failed to dump precompiled module '%0' + msg: "failed to dump precompiled module '%0'" - id: invalid_swift_name_method - msg: >- - too %select{few|many}0 parameters in swift_name attribute (expected %1; - got %2) + msg: "too %select{few|many}0 parameters in swift_name attribute (expected %1; got %2)" - id: note_while_importing - msg: >- - while importing '%0' + msg: "while importing '%0'" - id: swift_name_protocol_static - msg: >- - swift_name cannot be used to define %select{static member|init}0 on - protocol + msg: "swift_name cannot be used to define %select{static member|init}0 on protocol" - id: swift_name_no_prototype - msg: >- - swift_name cannot be used on a non-prototyped function declaration + msg: "swift_name cannot be used on a non-prototyped function declaration" - id: inconsistent_swift_name - msg: >- - inconsistent Swift name for Objective-C %select{method|property}0 '%1' in - '%2' (%3 in '%4' vs. %5 in '%6') + msg: "inconsistent Swift name for Objective-C %select{method|property}0 '%1' in '%2' (%3 in '%4' vs. %5 in '%6')" - id: unresolvable_clang_decl - msg: >- - imported declaration '%0' could not be mapped to '%1' + msg: "imported declaration '%0' could not be mapped to '%1'" - id: unresolvable_clang_decl_is_a_framework_bug - msg: >- - please report this issue to the owners of '%0' + msg: "please report this issue to the owners of '%0'" - id: implicit_bridging_header_imported_from_module - msg: >- - implicit import of bridging header '%0' via module %1 is deprecated and - will be removed in a later version of Swift + msg: "implicit import of bridging header '%0' via module %1 is deprecated and will be removed in a later version of Swift" - id: bridging_module_missing - msg: >- - unable to find module '%0' for implicit conversion function '%0.%1' + msg: "unable to find module '%0' for implicit conversion function '%0.%1'" - id: bridging_function_missing - msg: >- - unable to find implicit conversion function '%0.%1' + msg: "unable to find implicit conversion function '%0.%1'" - id: bridging_function_overloaded - msg: >- - multiple definitions of implicit conversion function '%0.%1' + msg: "multiple definitions of implicit conversion function '%0.%1'" - id: bridging_function_not_function - msg: >- - definition of implicit conversion function '%0.%1' is not a function + msg: "definition of implicit conversion function '%0.%1' is not a function" - id: bridging_function_not_correct_type - msg: >- - definition of implicit conversion function '%0.%1' is not of the correct - type + msg: "definition of implicit conversion function '%0.%1' is not of the correct type" - id: bridging_objcbridgeable_missing - msg: >- - cannot find definition of '_ObjectiveCBridgeable' protocol + msg: "cannot find definition of '_ObjectiveCBridgeable' protocol" - id: bridging_objcbridgeable_broken - msg: >- - broken definition of '_ObjectiveCBridgeable' protocol: missing %0 + msg: "broken definition of '_ObjectiveCBridgeable' protocol: missing %0" - id: invalid_sil_builtin - msg: >- - INTERNAL ERROR: invalid use of builtin: %0 + msg: "INTERNAL ERROR: invalid use of builtin: %0" - id: could_not_find_bridge_type - msg: >- - could not find Objective-C bridge type for type %0; did you forget to - import Foundation? + msg: "could not find Objective-C bridge type for type %0; did you forget to import Foundation?" - id: could_not_find_pointer_pointee_property - msg: >- - could not find 'pointee' property of pointer type %0 + msg: "could not find 'pointee' property of pointer type %0" - id: writeback_overlap_property - msg: >- - inout writeback to computed property %0 occurs in multiple arguments to - call, introducing invalid aliasing + msg: "inout writeback to computed property %0 occurs in multiple arguments to call, introducing invalid aliasing" - id: writeback_overlap_subscript - msg: >- - inout writeback through subscript occurs in multiple arguments to call, - introducing invalid aliasing + msg: "inout writeback through subscript occurs in multiple arguments to call, introducing invalid aliasing" - id: writebackoverlap_note - msg: >- - concurrent writeback occurred here + msg: "concurrent writeback occurred here" - id: inout_argument_alias - msg: >- - inout arguments are not allowed to alias each other + msg: "inout arguments are not allowed to alias each other" - id: previous_inout_alias - msg: >- - previous aliasing argument + msg: "previous aliasing argument" - id: unimplemented_generator_witnesses - msg: >- - protocol conformance emission for generator coroutines is unimplemented + msg: "protocol conformance emission for generator coroutines is unimplemented" - id: exclusivity_access_required - msg: >- - overlapping accesses to %0, but - %select{initialization|read|modification|deinitialization}1 requires - exclusive access; %select{consider copying to a local variable|consider - calling MutableCollection.swapAt(_:_:)}2 + msg: "overlapping accesses to %0, but %select{initialization|read|modification|deinitialization}1 requires exclusive access; %select{consider copying to a local variable|consider calling MutableCollection.swapAt(_:_:)}2" - id: exclusivity_access_required_unknown_decl - msg: >- - overlapping accesses, but - %select{initialization|read|modification|deinitialization}0 - requires exclusive access; consider copying to a local variable + msg: "overlapping accesses, but %select{initialization|read|modification|deinitialization}0 requires exclusive access; consider copying to a local variable" - id: exclusivity_conflicting_access - msg: >- - conflicting access is here + msg: "conflicting access is here" - id: unsupported_c_function_pointer_conversion - msg: >- - C function pointer signature %0 is not compatible with expected type %1 + msg: "C function pointer signature %0 is not compatible with expected type %1" - id: c_function_pointer_from_function_with_context - msg: >- - a C function pointer cannot be formed from a %select{local - function|closure}0 that captures %select{context|generic parameters|dynamic - Self type}1 + msg: "a C function pointer cannot be formed from a %select{local function|closure}0 that captures %select{context|generic parameters|dynamic Self type}1" - id: objc_selector_malformed - msg: >- - the type ObjectiveC.Selector is malformed + msg: "the type ObjectiveC.Selector is malformed" - id: capture_before_declaration - msg: >- - closure captures %0 before it is declared + msg: "closure captures %0 before it is declared" - id: capture_before_declaration_defer - msg: >- - 'defer' block captures %0 before it is declared + msg: "'defer' block captures %0 before it is declared" - id: captured_value_declared_here - msg: >- - captured value declared here + msg: "captured value declared here" - id: escaping_inout_capture - msg: >- - escaping %select{local function|closure|autoclosure}0 captures 'inout' - parameter %1 + msg: "escaping %select{local function|closure|autoclosure}0 captures 'inout' parameter %1" - id: inout_param_defined_here - msg: >- - parameter %0 is declared 'inout' + msg: "parameter %0 is declared 'inout'" - id: escaping_mutable_self_capture - msg: >- - escaping %select{local function|closure|autoclosure}0 captures mutating - 'self' parameter + msg: "escaping %select{local function|closure|autoclosure}0 captures mutating 'self' parameter" - id: escaping_noescape_param_capture - msg: >- - escaping %select{local function|closure|autoclosure}0 captures - non-escaping parameter %1 + msg: "escaping %select{local function|closure|autoclosure}0 captures non-escaping parameter %1" - id: noescape_param_defined_here - msg: >- - parameter %0 is implicitly non-escaping + msg: "parameter %0 is implicitly non-escaping" - id: escaping_noescape_var_capture - msg: >- - escaping %select{local function|closure|autoclosure}0 captures - non-escaping value + msg: "escaping %select{local function|closure|autoclosure}0 captures non-escaping value" - id: value_captured_here - msg: >- - captured here + msg: "captured here" - id: copy_inout_captured_by_autoclosure - msg: >- - pass a copy of %0 + msg: "pass a copy of %0" - id: copy_self_captured_by_autoclosure - msg: >- - pass a copy of 'self' + msg: "pass a copy of 'self'" - id: value_captured_transitively - msg: >- - captured indirectly by this call + msg: "captured indirectly by this call" - id: err_noescape_param_call - msg: >- - passing a %select{|closure which captures a }1non-escaping function - parameter %0 to a call to a non-escaping function parameter can allow - re-entrant modification of a variable + msg: "passing a %select{|closure which captures a }1non-escaping function parameter %0 to a call to a non-escaping function parameter can allow re-entrant modification of a variable" - id: variable_defined_here - msg: >- - %select{variable|constant}0 defined here + msg: "%select{variable|constant}0 defined here" - id: variable_used_before_initialized - msg: >- - %select{variable|constant}1 '%0' used before being initialized + msg: "%select{variable|constant}1 '%0' used before being initialized" - id: variable_inout_before_initialized - msg: >- - %select{variable|constant}1 '%0' passed by reference before being - initialized + msg: "%select{variable|constant}1 '%0' passed by reference before being initialized" - id: variable_closure_use_uninit - msg: >- - %select{variable|constant}1 '%0' captured by a closure before being - initialized + msg: "%select{variable|constant}1 '%0' captured by a closure before being initialized" - id: variable_defer_use_uninit - msg: >- - %select{variable|constant}1 '%0' used in defer before being initialized + msg: "%select{variable|constant}1 '%0' used in defer before being initialized" - id: self_closure_use_uninit - msg: >- - 'self' captured by a closure before all members were initialized + msg: "'self' captured by a closure before all members were initialized" - id: variable_addrtaken_before_initialized - msg: >- - address of %select{variable|constant}1 '%0' taken before it is initialized + msg: "address of %select{variable|constant}1 '%0' taken before it is initialized" - id: ivar_not_initialized_at_superinit - msg: >- - property '%0' not initialized at super.init call + msg: "property '%0' not initialized at super.init call" - id: ivar_not_initialized_at_implicit_superinit - msg: >- - property '%0' not initialized at implicitly generated super.init call + msg: "property '%0' not initialized at implicitly generated super.init call" - id: self_use_before_fully_init - msg: >- - 'self' used in %select{method call|property access}1 %0 before - %select{all stored properties are initialized|'super.init' call|'self.init' - call}2 + msg: "'self' used in %select{method call|property access}1 %0 before %select{all stored properties are initialized|'super.init' call|'self.init' call}2" - id: use_of_self_before_fully_init - msg: >- - 'self' used before all stored properties are initialized + msg: "'self' used before all stored properties are initialized" - id: stored_property_not_initialized - msg: >- - '%0' not initialized + msg: "'%0' not initialized" - id: selfinit_multiple_times - msg: >- - '%select{super|self}0.init' called multiple times in initializer + msg: "'%select{super|self}0.init' called multiple times in initializer" - id: superselfinit_not_called_before_return - msg: >- - '%select{super|self}0.init' isn't called on all paths before returning - from initializer + msg: "'%select{super|self}0.init' isn't called on all paths before returning from initializer" - id: self_before_superinit - msg: >- - 'self' used before 'super.init' call + msg: "'self' used before 'super.init' call" - id: self_before_selfinit - msg: >- - 'self' used before 'self.init' call + msg: "'self' used before 'self.init' call" - id: self_before_selfinit_value_type - msg: >- - 'self' used before 'self.init' call or assignment to 'self' + msg: "'self' used before 'self.init' call or assignment to 'self'" - id: self_inside_catch_superselfinit - msg: >- - 'self' used inside 'catch' block reachable from %select{super|self}0.init - call + msg: "'self' used inside 'catch' block reachable from %select{super|self}0.init call" - id: return_from_init_without_initing_stored_properties - msg: >- - return from initializer without initializing all stored properties + msg: "return from initializer without initializing all stored properties" - id: variable_function_use_uninit - msg: >- - %select{variable|constant}1 '%0' used by function definition before being - initialized + msg: "%select{variable|constant}1 '%0' used by function definition before being initialized" - id: struct_not_fully_initialized - msg: >- - struct '%0' must be completely initialized before a member is stored to + msg: "struct '%0' must be completely initialized before a member is stored to" - id: immutable_property_already_initialized - msg: >- - immutable value '%0' may only be initialized once + msg: "immutable value '%0' may only be initialized once" - id: initial_value_provided_in_let_decl - msg: >- - initial value already provided in 'let' declaration + msg: "initial value already provided in 'let' declaration" - id: mutation_of_property_of_immutable_value - msg: >- - cannot mutate %select{property %0|subscript}1 of immutable value '%2' + msg: "cannot mutate %select{property %0|subscript}1 of immutable value '%2'" - id: using_mutating_accessor_on_immutable_value - msg: >- - mutating accessor for %select{property %0|subscript}1 may not be used on - immutable value '%2' + msg: "mutating accessor for %select{property %0|subscript}1 may not be used on immutable value '%2'" - id: mutating_method_called_on_immutable_value - msg: >- - mutating %select{method|operator}1 %0 may not be used on immutable value - '%2' + msg: "mutating %select{method|operator}1 %0 may not be used on immutable value '%2'" - id: immutable_value_passed_inout - msg: >- - immutable value '%0' must not be passed inout + msg: "immutable value '%0' must not be passed inout" - id: assignment_to_immutable_value - msg: >- - immutable value '%0' must not be assigned to + msg: "immutable value '%0' must not be assigned to" - id: designated_init_in_cross_module_extension - msg: >- - initializer for struct %0 must use "self.init(...)" or "self = - ..."%select{| on all paths}1 because %select{it is not in module %2|the - struct was imported from C}3 + msg: "initializer for struct %0 must use \"self.init(...)\" or \"self = ...\"%select{| on all paths}1 because %select{it is not in module %2|the struct was imported from C}3" - id: designated_init_c_struct_fix - msg: >- - use "self.init()" to initialize the struct with zero values + msg: "use \"self.init()\" to initialize the struct with zero values" - id: missing_return - msg: >- - missing return in a %select{function|closure}1 expected to return %0 + msg: "missing return in a %select{function|closure}1 expected to return %0" - id: missing_return_last_expr - msg: >- - missing return in a %select{function|closure}1 expected to return %0; - did you mean to return the last expression? + msg: "missing return in a %select{function|closure}1 expected to return %0; did you mean to return the last expression?" - id: missing_never_call - msg: >- - %select{function|closure}1 with uninhabited return type %0 is missing - call to another never-returning function on all paths + msg: "%select{function|closure}1 with uninhabited return type %0 is missing call to another never-returning function on all paths" - id: guard_body_must_not_fallthrough - msg: >- - 'guard' body must not fall through, consider using a 'return' or 'throw' - to exit the scope + msg: "'guard' body must not fall through, consider using a 'return' or 'throw' to exit the scope" - id: unreachable_code - msg: >- - will never be executed + msg: "will never be executed" - id: unreachable_code_uninhabited_param_note - msg: >- - '%0' is uninhabited, so this function body can never be executed + msg: "'%0' is uninhabited, so this function body can never be executed" - id: unreachable_code_branch - msg: >- - condition always evaluates to %select{false|true}0 + msg: "condition always evaluates to %select{false|true}0" - id: call_to_noreturn_note - msg: >- - a call to a never-returning function + msg: "a call to a never-returning function" - id: unreachable_code_after_stmt - msg: >- - code after '%select{return|break|continue|throw}0' will never be executed + msg: "code after '%select{return|break|continue|throw}0' will never be executed" - id: unreachable_case - msg: >- - %select{case|default}0 will never be executed + msg: "%select{case|default}0 will never be executed" - id: switch_on_a_constant - msg: >- - switch condition evaluates to a constant + msg: "switch condition evaluates to a constant" - id: unreachable_code_note - msg: >- - will never be executed + msg: "will never be executed" - id: warn_infinite_recursive_function - msg: >- - all paths through this function will call itself + msg: "all paths through this function will call itself" - id: circular_transparent - msg: >- - inlining 'transparent' functions forms circular loop + msg: "inlining 'transparent' functions forms circular loop" - id: note_while_inlining - msg: >- - while inlining here + msg: "while inlining here" - id: cannot_prespecialize - msg: >- - Cannot pre-specialize %0 + msg: "Cannot pre-specialize %0" - id: missing_prespecialization - msg: >- - Pre-specialized function %0 missing in SwiftOnoneSupport module + msg: "Pre-specialized function %0 missing in SwiftOnoneSupport module" - id: integer_conversion_overflow - msg: >- - integer overflows when converted from %0 to %1 + msg: "integer overflows when converted from %0 to %1" - id: integer_conversion_overflow_builtin_types - msg: >- - integer overflows when converted from %select{unsigned|signed}0 %1 to - %select{unsigned|signed}2 %3 + msg: "integer overflows when converted from %select{unsigned|signed}0 %1 to %select{unsigned|signed}2 %3" - id: integer_conversion_overflow_warn - msg: >- - integer overflows when converted from %0 to %1 + msg: "integer overflows when converted from %0 to %1" - id: negative_integer_literal_overflow_unsigned - msg: >- - negative integer '%1' overflows when stored into unsigned type %0 + msg: "negative integer '%1' overflows when stored into unsigned type %0" - id: integer_literal_overflow - msg: >- - integer literal '%1' overflows when stored into %0 + msg: "integer literal '%1' overflows when stored into %0" - id: integer_literal_overflow_builtin_types - msg: >- - integer literal '%2' overflows when stored into %select{unsigned|signed}0 %1 + msg: "integer literal '%2' overflows when stored into %select{unsigned|signed}0 %1" - id: integer_literal_overflow_warn - msg: >- - integer literal overflows when stored into %0 + msg: "integer literal overflows when stored into %0" - id: arithmetic_operation_overflow - msg: >- - arithmetic operation '%0 %1 %2' (on type %3) results in an overflow + msg: "arithmetic operation '%0 %1 %2' (on type %3) results in an overflow" - id: arithmetic_operation_overflow_generic_type - msg: >- - arithmetic operation '%0 %1 %2' (on %select{unsigned|signed}3 %4-bit - integer type) results in an overflow + msg: "arithmetic operation '%0 %1 %2' (on %select{unsigned|signed}3 %4-bit integer type) results in an overflow" - id: division_overflow - msg: >- - division '%0 %1 %2' results in an overflow + msg: "division '%0 %1 %2' results in an overflow" - id: division_by_zero - msg: >- - division by zero + msg: "division by zero" - id: wrong_non_negative_assumption - msg: >- - assumed non-negative value '%0' is negative + msg: "assumed non-negative value '%0' is negative" - id: shifting_all_significant_bits - msg: >- - shift amount is greater than or equal to type size in bits + msg: "shift amount is greater than or equal to type size in bits" - id: static_report_error - msg: >- - static report error + msg: "static report error" - id: pound_assert_condition_not_constant - msg: >- - #assert condition not constant + msg: "#assert condition not constant" - id: pound_assert_failure - msg: >- - %0 + msg: "%0" - id: constexpr_unknown_reason_default - msg: >- - cannot evaluate expression as constant here + msg: "cannot evaluate expression as constant here" - id: constexpr_unevaluable_operation - msg: >- - cannot constant evaluate operation%select{| used by this call}0 + msg: "cannot constant evaluate operation%select{| used by this call}0" - id: constexpr_too_many_instructions - msg: >- - exceeded instruction limit: %0 when evaluating the expression at compile - time + msg: "exceeded instruction limit: %0 when evaluating the expression at compile time" - id: constexpr_limit_exceeding_instruction - msg: >- - limit exceeded %select{here|during this call}0 + msg: "limit exceeded %select{here|during this call}0" - id: constexpr_loop_found_note - msg: >- - control-flow loop found during evaluation + msg: "control-flow loop found during evaluation " - id: constexpr_loop_instruction - msg: >- - found loop %select{here|inside this call}0 + msg: "found loop %select{here|inside this call}0" - id: constexpr_overflow - msg: >- - integer overflow detected + msg: "integer overflow detected" - id: constexpr_overflow_operation - msg: >- - operation%select{| performed during this call}0 overflows + msg: "operation%select{| performed during this call}0 overflows" - id: constexpr_trap - msg: >- - %0 + msg: "%0" - id: constexpr_trap_operation - msg: >- - operation%select{| performed during this call}0 traps + msg: "operation%select{| performed during this call}0 traps" - id: constexpr_invalid_operand_seen - msg: >- - operation with invalid operands encountered during evaluation + msg: "operation with invalid operands encountered during evaluation" - id: constexpr_operand_invalid_here - msg: >- - operation with invalid operands encountered %select{here|during this call}0 + msg: "operation with invalid operands encountered %select{here|during this call}0" - id: constexpr_value_unknown_at_top_level - msg: >- - cannot evaluate top-level value as constant here + msg: "cannot evaluate top-level value as constant here" - id: constexpr_multiple_writers_found_at_top_level - msg: >- - top-level value has multiple assignments + msg: "top-level value has multiple assignments" - id: constexpr_unsupported_instruction_found - msg: >- - encountered operation not supported by the evaluator: %0 + msg: "encountered operation not supported by the evaluator: %0" - id: constexpr_unsupported_instruction_found_here - msg: >- - operation%select{| used by this call is}0 not supported by the evaluator + msg: "operation%select{| used by this call is}0 not supported by the evaluator" - id: constexpr_found_callee_with_no_body - msg: >- - encountered call to '%0' whose body is not available. Imported functions - must be marked '@inlinable' to constant evaluate + msg: "encountered call to '%0' whose body is not available. Imported functions must be marked '@inlinable' to constant evaluate" - id: constexpr_callee_with_no_body - msg: >- - %select{|calls a }0function whose body is not available + msg: "%select{|calls a }0function whose body is not available" - id: constexpr_found_call_with_unknown_arg - msg: >- - encountered call to '%0' where the %1 argument is not a constant + msg: "encountered call to '%0' where the %1 argument is not a constant" - id: constexpr_call_with_unknown_arg - msg: >- - %select{|makes a }0function call with non-constant arguments + msg: "%select{|makes a }0function call with non-constant arguments" - id: constexpr_untracked_sil_value_use_found - msg: >- - encountered use of a variable not tracked by the evaluator + msg: "encountered use of a variable not tracked by the evaluator" - id: constexpr_untracked_sil_value_used_here - msg: >- - untracked variable used %select{here|by this call}0 + msg: "untracked variable used %select{here|by this call}0" - id: constexpr_unevaluable_cast_found - msg: >- - encountered an unevaluable cast + msg: "encountered an unevaluable cast" - id: constexpr_unevaluable_cast_used_here - msg: >- - unevaluable cast encountered %select{here|by this call}0 + msg: "unevaluable cast encountered %select{here|by this call}0" - id: constexpr_unresolvable_witness_call - msg: >- - encountered unresolvable witness method call: '%0' + msg: "encountered unresolvable witness method call: '%0'" - id: constexpr_no_witness_table_entry - msg: >- - cannot find witness table entry %select{for this call|for a - witness-method invoked during this call}0 + msg: "cannot find witness table entry %select{for this call|for a witness-method invoked during this call}0" - id: constexpr_witness_call_with_no_conformance - msg: >- - cannot find concrete conformance %select{for this call|for a - witness-method invoked during this call}0 + msg: "cannot find concrete conformance %select{for this call|for a witness-method invoked during this call}0" - id: constexpr_unknown_control_flow_due_to_skip - msg: >- - branch depends on non-constant value produced by an unevaluated - instructions + msg: "branch depends on non-constant value produced by an unevaluated instructions" - id: constexpr_returned_by_unevaluated_instruction - msg: >- - result of an unevaluated instruction is not a constant + msg: "result of an unevaluated instruction is not a constant" - id: constexpr_mutated_by_unevaluated_instruction - msg: >- - value mutable by an unevaluated instruction is not a constant + msg: "value mutable by an unevaluated instruction is not a constant" - id: not_constant_evaluable - msg: >- - not constant evaluable + msg: "not constant evaluable" - id: constexpr_imported_func_not_onone - msg: >- - imported constant evaluable function '%0' must be annotated - '@_optimize(none)' + msg: "imported constant evaluable function '%0' must be annotated '@_optimize(none)'" - id: autodiff_internal_swift_not_imported - msg: >- - Automatic differentiation internal error: the Swift module is not - imported + msg: "Automatic differentiation internal error: the Swift module is not imported" - id: autodiff_differentiation_module_not_imported - msg: >- - Automatic differentiation requires the '_Differentiation' module to be - imported + msg: "Automatic differentiation requires the '_Differentiation' module to be imported" - id: autodiff_conversion_to_linear_function_not_supported - msg: >- - conversion to '@differentiable(linear)' function type is not yet - supported + msg: "conversion to '@differentiable(linear)' function type is not yet supported" - id: autodiff_function_not_differentiable_error - msg: >- - function is not differentiable + msg: "function is not differentiable" - id: autodiff_expression_not_differentiable_error - msg: >- - expression is not differentiable + msg: "expression is not differentiable" - id: autodiff_expression_not_differentiable_note - msg: >- - expression is not differentiable + msg: "expression is not differentiable" - id: autodiff_when_differentiating_function_call - msg: >- - when differentiating this function call + msg: "when differentiating this function call" - id: autodiff_when_differentiating_function_definition - msg: >- - when differentiating this function definition + msg: "when differentiating this function definition" - id: autodiff_implicitly_inherited_differentiable_attr_here - msg: >- - differentiability required by the corresponding protocol requirement here + msg: "differentiability required by the corresponding protocol requirement here" - id: autodiff_jvp_control_flow_not_supported - msg: >- - forward-mode differentiation does not yet support control flow + msg: "forward-mode differentiation does not yet support control flow" - id: autodiff_control_flow_not_supported - msg: >- - cannot differentiate unsupported control flow + msg: "cannot differentiate unsupported control flow" - id: autodiff_missing_return - msg: >- - missing return for differentiation + msg: "missing return for differentiation" - id: autodiff_external_nondifferentiable_function - msg: >- - cannot differentiate functions that have not been marked - '@differentiable' and that are defined in other files + msg: "cannot differentiate functions that have not been marked '@differentiable' and that are defined in other files" - id: autodiff_opaque_function_not_differentiable - msg: >- - opaque non-'@differentiable' function is not differentiable + msg: "opaque non-'@differentiable' function is not differentiable" - id: autodiff_private_derivative_from_fragile - msg: >- - differentiated functions in %select{'@inlinable' functions|default - arguments}0 must be marked '@differentiable' or have a public - '@derivative'%select{|; this is not possible with a closure, make a - top-level function instead}1 + msg: "differentiated functions in %select{'@inlinable' functions|default arguments}0 must be marked '@differentiable' or have a public '@derivative'%select{|; this is not possible with a closure, make a top-level function instead}1" - id: autodiff_function_noderivative_parameter_not_differentiable - msg: >- - cannot differentiate with respect to a '@noDerivative' parameter + msg: "cannot differentiate with respect to a '@noDerivative' parameter" - id: autodiff_function_assoc_func_unmet_requirements - msg: >- - function call is not differentiable because generic requirements are not - met: '%0' + msg: "function call is not differentiable because generic requirements are not met: '%0'" - id: autodiff_nondifferentiable_argument - msg: >- - cannot differentiate through a non-differentiable argument; do you want - to use 'withoutDerivative(at:)'? + msg: "cannot differentiate through a non-differentiable argument; do you want to use 'withoutDerivative(at:)'?" - id: autodiff_nondifferentiable_result - msg: >- - cannot differentiate through a non-differentiable result; do you want to - use 'withoutDerivative(at:)'? + msg: "cannot differentiate through a non-differentiable result; do you want to use 'withoutDerivative(at:)'?" - id: autodiff_protocol_member_not_differentiable - msg: >- - member is not differentiable because the corresponding protocol - requirement is not '@differentiable' + msg: "member is not differentiable because the corresponding protocol requirement is not '@differentiable'" - id: autodiff_class_member_not_differentiable - msg: >- - member is not differentiable because the corresponding class member is - not '@differentiable' + msg: "member is not differentiable because the corresponding class member is not '@differentiable'" - id: autodiff_member_subset_indices_not_differentiable - msg: >- - member is differentiable only with respect to a smaller subset of arguments + msg: "member is differentiable only with respect to a smaller subset of arguments" - id: autodiff_cannot_param_subset_thunk_partially_applied_orig_fn - msg: >- - cannot convert a direct method reference to a '@differentiable' function; - use an explicit closure instead + msg: "cannot convert a direct method reference to a '@differentiable' function; use an explicit closure instead" - id: autodiff_cannot_differentiate_through_multiple_results - msg: >- - cannot differentiate through multiple results + msg: "cannot differentiate through multiple results" - id: autodiff_cannot_differentiate_through_inout_arguments - msg: >- - cannot differentiate through 'inout' arguments + msg: "cannot differentiate through 'inout' arguments" - id: autodiff_enums_unsupported - msg: >- - differentiating enum values is not yet supported + msg: "differentiating enum values is not yet supported" - id: autodiff_stored_property_parent_not_differentiable - msg: >- - cannot differentiate access to property '%0.%1' because '%0' does not - conform to 'Differentiable' + msg: "cannot differentiate access to property '%0.%1' because '%0' does not conform to 'Differentiable'" - id: autodiff_stored_property_not_differentiable - msg: >- - cannot differentiate access to property '%0.%1' because property type %2 - does not conform to 'Differentiable' + msg: "cannot differentiate access to property '%0.%1' because property type %2 does not conform to 'Differentiable'" - id: autodiff_stored_property_tangent_not_struct - msg: >- - cannot differentiate access to property '%0.%1' because - '%0.TangentVector' is not a struct + msg: "cannot differentiate access to property '%0.%1' because '%0.TangentVector' is not a struct" - id: autodiff_stored_property_no_corresponding_tangent - msg: >- - cannot differentiate access to property '%0.%1' because - '%0.TangentVector' does not have a stored property named '%1' + msg: "cannot differentiate access to property '%0.%1' because '%0.TangentVector' does not have a stored property named '%1'" - id: autodiff_tangent_property_wrong_type - msg: >- - cannot differentiate access to property '%0.%1' because - '%0.TangentVector.%1' does not have expected type %2 + msg: "cannot differentiate access to property '%0.%1' because '%0.TangentVector.%1' does not have expected type %2" - id: autodiff_tangent_property_not_stored - msg: >- - cannot differentiate access to property '%0.%1' because - '%0.TangentVector.%1' is not a stored property + msg: "cannot differentiate access to property '%0.%1' because '%0.TangentVector.%1' is not a stored property" - id: autodiff_coroutines_not_supported - msg: >- - differentiation of coroutine calls is not yet supported + msg: "differentiation of coroutine calls is not yet supported" - id: autodiff_cannot_differentiate_writes_to_global_variables - msg: >- - cannot differentiate writes to global variables + msg: "cannot differentiate writes to global variables" - id: autodiff_cannot_differentiate_writes_to_mutable_captures - msg: >- - cannot differentiate writes to mutable captures + msg: "cannot differentiate writes to mutable captures" - id: non_physical_addressof - msg: >- - addressof only works with purely physical lvalues; use - 'withUnsafePointer' or 'withUnsafeBytes' unless you're implementing - 'withUnsafePointer' or 'withUnsafeBytes' + msg: "addressof only works with purely physical lvalues; use 'withUnsafePointer' or 'withUnsafeBytes' unless you're implementing 'withUnsafePointer' or 'withUnsafeBytes'" - id: non_borrowed_indirect_addressof - msg: >- - addressof only works with borrowable in-memory rvalues; use - 'withUnsafePointer' or 'withUnsafeBytes' unless you're implementing - 'withUnsafePointer' or 'withUnsafeBytes' + msg: "addressof only works with borrowable in-memory rvalues; use 'withUnsafePointer' or 'withUnsafeBytes' unless you're implementing 'withUnsafePointer' or 'withUnsafeBytes'" - id: opt_remark_passed - msg: >- - %0 + msg: "%0" - id: opt_remark_missed - msg: >- - %0 + msg: "%0" + +- id: opt_remark_note + msg: "%0" - id: float_to_int_overflow - msg: >- - invalid%select{| implicit}2 conversion: '%0' overflows %1 + msg: "invalid%select{| implicit}2 conversion: '%0' overflows %1" - id: negative_fp_literal_overflow_unsigned - msg: >- - negative literal '%0' cannot be converted to %select{|unsigned }2%1 + msg: "negative literal '%0' cannot be converted to %select{|unsigned }2%1" - id: warning_float_trunc_overflow - msg: >- - '%0' overflows to %select{|-}2inf during conversion to %1 + msg: "'%0' overflows to %select{|-}2inf during conversion to %1" - id: warning_float_trunc_underflow - msg: >- - '%0' underflows and loses precision during conversion to %1 + msg: "'%0' underflows and loses precision during conversion to %1" - id: warning_float_trunc_hex_inexact - msg: >- - '%0' loses precision during conversion to %1 + msg: "'%0' loses precision during conversion to %1" - id: warning_float_overflows_maxbuiltin - msg: >- - '%0' overflows to %select{|-}1inf because its magnitude exceeds the - limits of a float literal + msg: "'%0' overflows to %select{|-}1inf because its magnitude exceeds the limits of a float literal" - id: warning_int_to_fp_inexact - msg: >- - '%1' is not exactly representable as %0; it becomes '%2' + msg: "'%1' is not exactly representable as %0; it becomes '%2'" - id: return_before_yield - msg: >- - accessor must yield before returning + msg: "accessor must yield before returning" - id: multiple_yields - msg: >- - accessor must not yield more than once + msg: "accessor must not yield more than once" - id: previous_yield - msg: >- - previous yield was here + msg: "previous yield was here" - id: possible_return_before_yield - msg: >- - accessor must yield on all paths before returning + msg: "accessor must yield on all paths before returning" - id: branch_doesnt_yield - msg: >- - missing yield when the condition is %select{false|true}0 + msg: "missing yield when the condition is %select{false|true}0" - id: named_case_doesnt_yield - msg: >- - missing yield in the %0 case + msg: "missing yield in the %0 case" - id: case_doesnt_yield - msg: >- - missing yield in %select{this|the nil|the non-nil}0 case + msg: "missing yield in %select{this|the nil|the non-nil}0 case" - id: switch_value_case_doesnt_yield - msg: >- - missing yield in the %0 case + msg: "missing yield in the %0 case" - id: try_branch_doesnt_yield - msg: >- - missing yield when error is %select{not |}0thrown + msg: "missing yield when error is %select{not |}0thrown" - id: oslog_constant_eval_trap - msg: >- - %0 + msg: "%0" - id: oslog_too_many_instructions - msg: >- - interpolated expression and arguments are too complex + msg: "interpolated expression and arguments are too complex" - id: oslog_invalid_log_message - msg: >- - invalid log message; extending types defined in the os module is not - supported + msg: "invalid log message; extending types defined in the os module is not supported" - id: oslog_const_evaluable_fun_error - msg: >- - '%0' failed evaluation + msg: "'%0' failed evaluation" - id: oslog_non_constant_message - msg: >- - 'OSLogMessage' instance passed to the log call is not a constant + msg: "'OSLogMessage' instance passed to the log call is not a constant" - id: oslog_non_constant_interpolation - msg: >- - 'OSLogInterpolation' instance passed to 'OSLogMessage.init' is not a - constant + msg: "'OSLogInterpolation' instance passed to 'OSLogMessage.init' is not a constant" - id: oslog_property_not_constant - msg: >- - 'OSLogInterpolation.%0' is not a constant + msg: "'OSLogInterpolation.%0' is not a constant" - id: oslog_message_alive_after_opts - msg: >- - string interpolation cannot be used in this context; if you are calling - an os_log function, try a different overload + msg: "string interpolation cannot be used in this context; if you are calling an os_log function, try a different overload" - id: oslog_message_explicitly_created - msg: >- - 'OSLogMessage' must be created from a string interpolation or string - literal + msg: "'OSLogMessage' must be created from a string interpolation or string literal" - id: oslog_call_in_unreachable_code - msg: >- - os log call will never be executed and may have undiagnosed errors + msg: "os log call will never be executed and may have undiagnosed errors" - id: global_string_pointer_on_non_constant - msg: >- - globalStringTablePointer builtin must be used only on string literals + msg: "globalStringTablePointer builtin must be used only on string literals" - id: polymorphic_builtin_passed_non_trivial_non_builtin_type - msg: >- - Argument of type %0 can not be passed as an argument to a Polymorphic - builtin. Polymorphic builtins can only be passed arguments that are trivial - builtin typed + msg: "Argument of type %0 can not be passed as an argument to a Polymorphic builtin. Polymorphic builtins can only be passed arguments that are trivial builtin typed" - id: polymorphic_builtin_passed_type_without_static_overload - msg: >- - Static overload %0 does not exist for polymorphic builtin '%1'. Static - overload implied by passing argument of type %2 + msg: "Static overload %0 does not exist for polymorphic builtin '%1'. Static overload implied by passing argument of type %2" - id: box_to_stack_cannot_promote_box_to_stack_due_to_escape_alloc - msg: >- - Can not promote value from heap to stack due to value escaping + msg: "Can not promote value from heap to stack due to value escaping" - id: box_to_stack_cannot_promote_box_to_stack_due_to_escape_location - msg: >- - value escapes here + msg: "value escapes here" - id: no_llvm_target - msg: >- - error loading LLVM target for triple '%0': %1 + msg: "error loading LLVM target for triple '%0': %1" - id: error_codegen_init_fail - msg: >- - cannot initialize code generation passes for target + msg: "cannot initialize code generation passes for target" - id: irgen_unimplemented - msg: >- - unimplemented IR generation feature %0 + msg: "unimplemented IR generation feature %0" - id: irgen_failure - msg: >- - IR generation failure: %0 + msg: "IR generation failure: %0" - id: type_to_verify_not_found - msg: >- - unable to find type '%0' to verify + msg: "unable to find type '%0' to verify" - id: type_to_verify_ambiguous - msg: >- - type to verify '%0' is ambiguous + msg: "type to verify '%0' is ambiguous" - id: type_to_verify_dependent - msg: >- - type to verify '%0' has unbound generic parameters + msg: "type to verify '%0' has unbound generic parameters" - id: too_few_output_filenames - msg: >- - too few output file names specified + msg: "too few output file names specified" - id: no_input_files_for_mt - msg: >- - no swift input files for multi-threaded compilation + msg: "no swift input files for multi-threaded compilation" - id: alignment_dynamic_type_layout_unsupported - msg: >- - @_alignment is not supported on types with dynamic layout + msg: "@_alignment is not supported on types with dynamic layout" - id: alignment_less_than_natural - msg: >- - @_alignment cannot decrease alignment below natural alignment of %0 + msg: "@_alignment cannot decrease alignment below natural alignment of %0" - id: alignment_more_than_maximum - msg: >- - @_alignment cannot increase alignment above maximum alignment of %0 + msg: "@_alignment cannot increase alignment above maximum alignment of %0" - id: warning_no_such_sdk - msg: >- - no such SDK: '%0' + msg: "no such SDK: '%0'" - id: error_no_frontend_args - msg: >- - no arguments provided to '-frontend' + msg: "no arguments provided to '-frontend'" - id: error_no_such_file_or_directory - msg: >- - no such file or directory: '%0' + msg: "no such file or directory: '%0'" - id: error_unsupported_target_os - msg: >- - unsupported target OS: '%0' + msg: "unsupported target OS: '%0'" - id: error_unsupported_target_arch - msg: >- - unsupported target architecture: '%0' + msg: "unsupported target architecture: '%0'" - id: error_unsupported_opt_for_target - msg: >- - unsupported option '%0' for target '%1' + msg: "unsupported option '%0' for target '%1'" - id: warning_inferred_simulator_target - msg: >- - inferring simulator environment for target '%0'; use '-target %1' instead + msg: "inferring simulator environment for target '%0'; use '-target %1' instead" - id: error_argument_not_allowed_with - msg: >- - argument '%0' is not allowed with '%1' + msg: "argument '%0' is not allowed with '%1'" - id: warning_argument_not_supported_with_optimization - msg: >- - argument '%0' is not supported with optimization + msg: "argument '%0' is not supported with optimization" - id: error_option_requires_sanitizer - msg: >- - option '%0' requires a sanitizer to be enabled. Use -sanitize= to enable - a sanitizer + msg: "option '%0' requires a sanitizer to be enabled. Use -sanitize= to enable a sanitizer" - id: warning_option_requires_specific_sanitizer - msg: >- - option '%0' has no effect when '%1' sanitizer is disabled. Use - -sanitize=%1 to enable the sanitizer + msg: "option '%0' has no effect when '%1' sanitizer is disabled. Use -sanitize=%1 to enable the sanitizer" - id: error_option_missing_required_argument - msg: >- - option '%0' is missing a required argument (%1) + msg: "option '%0' is missing a required argument (%1)" - id: cannot_open_file - msg: >- - cannot open file '%0' (%1) + msg: "cannot open file '%0' (%1)" - id: cannot_open_serialized_file - msg: >- - cannot open file '%0' for diagnostics emission (%1) + msg: "cannot open file '%0' for diagnostics emission (%1)" - id: error_open_input_file - msg: >- - error opening input file '%0' (%1) + msg: "error opening input file '%0' (%1)" - id: error_clang_importer_create_fail - msg: >- - clang importer creation failed + msg: "clang importer creation failed" - id: error_missing_arg_value - msg: >- - missing argument value for '%0', expected %1 argument(s) + msg: "missing argument value for '%0', expected %1 argument(s)" - id: error_unknown_arg - msg: >- - unknown argument: '%0' + msg: "unknown argument: '%0'" - id: error_invalid_arg_value - msg: >- - invalid value '%1' in '%0' + msg: "invalid value '%1' in '%0'" - id: warning_invalid_locale_code - msg: >- - unsupported locale code; supported locale codes are: '%0' + msg: "unsupported locale code; supported locale codes are: '%0'" - id: warning_locale_path_not_found - msg: >- - specified localization directory '%0' does not exist, translation is - disabled + msg: "specified localization directory '%0' does not exist, translation is disabled" - id: warning_cannot_find_locale_file - msg: >- - cannot find translations for '%0' at '%1': no such file + msg: "cannot find translations for '%0' at '%1': no such file" - id: warning_cannot_multithread_batch_mode - msg: >- - ignoring -num-threads argument; cannot multithread batch mode + msg: "ignoring -num-threads argument; cannot multithread batch mode" - id: error_unsupported_option_argument - msg: >- - unsupported argument '%1' to option '%0' + msg: "unsupported argument '%1' to option '%0'" - id: error_immediate_mode_missing_stdlib - msg: >- - could not load the swift standard library + msg: "could not load the swift standard library" - id: error_immediate_mode_missing_library - msg: >- - could not load %select{shared library|framework}0 '%1' + msg: "could not load %select{shared library|framework}0 '%1'" - id: error_immediate_mode_primary_file - msg: >- - immediate mode is incompatible with -primary-file + msg: "immediate mode is incompatible with -primary-file" - id: error_missing_frontend_action - msg: >- - no frontend action was selected + msg: "no frontend action was selected" - id: error_invalid_source_location_str - msg: >- - invalid source location string '%0' + msg: "invalid source location string '%0'" - id: error_no_source_location_scope_map - msg: >- - -dump-scope-maps argument must be 'expanded' or a list of source - locations + msg: "-dump-scope-maps argument must be 'expanded' or a list of source locations" - id: note_valid_swift_versions - msg: >- - valid arguments to '-swift-version' are %0 + msg: "valid arguments to '-swift-version' are %0" - id: error_mode_cannot_emit_dependencies - msg: >- - this mode does not support emitting dependency files + msg: "this mode does not support emitting dependency files" - id: error_mode_cannot_emit_reference_dependencies - msg: >- - this mode does not support emitting reference dependency files + msg: "this mode does not support emitting reference dependency files" - id: error_mode_cannot_emit_swift_ranges - msg: >- - this mode does not support emitting unparsed ranges files + msg: "this mode does not support emitting unparsed ranges files" - id: error_mode_cannot_emit_compiled_source - msg: >- - this mode does not support emitting compiled source files + msg: "this mode does not support emitting compiled source files" - id: error_mode_cannot_emit_header - msg: >- - this mode does not support emitting Objective-C headers + msg: "this mode does not support emitting Objective-C headers" - id: error_mode_cannot_emit_loaded_module_trace - msg: >- - this mode does not support emitting the loaded module trace + msg: "this mode does not support emitting the loaded module trace" - id: error_mode_cannot_emit_module - msg: >- - this mode does not support emitting modules + msg: "this mode does not support emitting modules" - id: error_mode_cannot_emit_module_doc - msg: >- - this mode does not support emitting module documentation files + msg: "this mode does not support emitting module documentation files" - id: error_mode_cannot_emit_module_source_info - msg: >- - this mode does not support emitting module source info files + msg: "this mode does not support emitting module source info files" - id: error_mode_cannot_emit_interface - msg: >- - this mode does not support emitting module interface files + msg: "this mode does not support emitting module interface files" - id: cannot_emit_ir_skipping_function_bodies - msg: >- - -experimental-skip-non-inlinable-function-bodies does not support - emitting IR + msg: "-experimental-skip-non-inlinable-function-bodies does not support emitting IR" - id: emit_reference_dependencies_without_primary_file - msg: >- - ignoring -emit-reference-dependencies (requires -primary-file) + msg: "ignoring -emit-reference-dependencies (requires -primary-file)" - id: emit_swift_ranges_without_primary_file - msg: >- - ignoring -emit-swift-ranges (requires -primary-file) + msg: "ignoring -emit-swift-ranges (requires -primary-file)" - id: emit_compiled_source_without_primary_file - msg: >- - ignoring -emit-compiled-source (requires -primary-file) + msg: "ignoring -emit-compiled-source (requires -primary-file)" - id: error_bad_module_name - msg: >- - module name "%0" is not a valid identifier%select{|; use -module-name - flag to specify an alternate name}1 + msg: "module name \"%0\" is not a valid identifier%select{|; use -module-name flag to specify an alternate name}1" - id: error_stdlib_module_name - msg: >- - module name "%0" is reserved for the standard library%select{|; use - -module-name flag to specify an alternate name}1 + msg: "module name \"%0\" is reserved for the standard library%select{|; use -module-name flag to specify an alternate name}1" - id: error_stdlib_not_found - msg: >- - unable to load standard library for target '%0' + msg: "unable to load standard library for target '%0'" - id: error_unable_to_load_supplementary_output_file_map - msg: >- - unable to load supplementary output file map '%0': %1 + msg: "unable to load supplementary output file map '%0': %1" - id: error_missing_entry_in_supplementary_output_file_map - msg: >- - supplementary output file map '%0' is missing an entry for '%1' (this - likely indicates a compiler issue; please file a bug report) + msg: "supplementary output file map '%0' is missing an entry for '%1' (this likely indicates a compiler issue; please file a bug report)" - id: error_repl_requires_no_input_files - msg: >- - REPL mode requires no input files + msg: "REPL mode requires no input files" - id: error_mode_requires_one_input_file - msg: >- - this mode requires a single input file + msg: "this mode requires a single input file" - id: error_mode_requires_an_input_file - msg: >- - this mode requires at least one input file + msg: "this mode requires at least one input file" - id: error_mode_requires_one_sil_multi_sib - msg: >- - this mode requires .sil for primary-file and only .sib for other inputs + msg: "this mode requires .sil for primary-file and only .sib for other inputs" - id: error_no_output_filename_specified - msg: >- - an output filename was not specified for a mode which requires an output - filename + msg: "an output filename was not specified for a mode which requires an output filename" - id: error_implicit_output_file_is_directory - msg: >- - the implicit output file '%0' is a directory; explicitly specify a - filename using -o + msg: "the implicit output file '%0' is a directory; explicitly specify a filename using -o" - id: error_if_any_output_files_are_specified_they_all_must_be - msg: >- - if any output files are specified, they all must be + msg: "if any output files are specified, they all must be" - id: error_primary_file_not_found - msg: >- - primary file '%0' was not found in file list '%1' + msg: "primary file '%0' was not found in file list '%1'" - id: error_cannot_have_input_files_with_file_list - msg: >- - cannot have input files with file list + msg: "cannot have input files with file list" - id: error_cannot_have_primary_files_with_primary_file_list - msg: >- - cannot have primary input files with primary file list + msg: "cannot have primary input files with primary file list" - id: error_cannot_have_supplementary_outputs - msg: >- - cannot have '%0' with '%1' + msg: "cannot have '%0' with '%1'" - id: error_duplicate_input_file - msg: >- - duplicate input file '%0' + msg: "duplicate input file '%0'" - id: repl_must_be_initialized - msg: >- - variables currently must have an initial value when entered at the top - level of the REPL + msg: "variables currently must have an initial value when entered at the top level of the REPL" - id: verify_encountered_fatal - msg: >- - fatal error encountered while in -verify mode + msg: "fatal error encountered while in -verify mode" - id: error_parse_input_file - msg: >- - error parsing input file '%0' (%1) + msg: "error parsing input file '%0' (%1)" - id: error_write_index_unit - msg: >- - writing index unit file: %0 + msg: "writing index unit file: %0" - id: error_create_index_dir - msg: >- - creating index directory: %0 + msg: "creating index directory: %0" - id: error_write_index_record - msg: >- - writing index record file: %0 + msg: "writing index record file: %0" - id: error_index_failed_status_check - msg: >- - failed file status check: %0 + msg: "failed file status check: %0" - id: error_index_inputs_more_than_outputs - msg: >- - index output filenames do not match input source files + msg: "index output filenames do not match input source files" - id: error_wrong_number_of_arguments - msg: >- - wrong number of '%0' arguments (expected %1, got %2) + msg: "wrong number of '%0' arguments (expected %1, got %2)" - id: error_formatting_multiple_file_ranges - msg: >- - file ranges don't support multiple input files + msg: "file ranges don't support multiple input files" - id: error_formatting_invalid_range - msg: >- - file range is invalid + msg: "file range is invalid" - id: stats_disabled - msg: >- - compiler was not built with support for collecting statistics + msg: "compiler was not built with support for collecting statistics" - id: tbd_warn_truncating_version - msg: >- - truncating %select{current|compatibility}0 version '%1' in TBD file to - fit in 32-bit space used by old mach-o format + msg: "truncating %select{current|compatibility}0 version '%1' in TBD file to fit in 32-bit space used by old mach-o format" - id: tbd_err_invalid_version - msg: >- - invalid dynamic library %select{current|compatibility}0 version '%1' + msg: "invalid dynamic library %select{current|compatibility}0 version '%1'" - id: tbd_only_supported_in_whole_module - msg: >- - TBD generation is only supported when the whole module can be seen + msg: "TBD generation is only supported when the whole module can be seen" - id: tbd_not_supported_with_cmo - msg: >- - Test-Based InstallAPI (TBD) is not support with cross-module-optimization + msg: "Test-Based InstallAPI (TBD) is not support with cross-module-optimization" - id: linker_directives_choice_confusion - msg: >- - only one of -emit-ldadd-cfile-path and -module-installname-map-file can - be specified;the c file won't be generated + msg: "only one of -emit-ldadd-cfile-path and -module-installname-map-file can be specified;the c file won't be generated" - id: previous_installname_map_missing - msg: >- - cannot open previous install name map from %0 + msg: "cannot open previous install name map from %0" - id: previous_installname_map_corrupted - msg: >- - previous install name map from %0 is malformed + msg: "previous install name map from %0 is malformed" - id: explicit_swift_module_map_missing - msg: >- - cannot open explicit Swift module map from %0 + msg: "cannot open explicit Swift module map from %0" - id: explicit_swift_module_map_corrupted - msg: >- - explicit Swift module map from %0 is malformed + msg: "explicit Swift module map from %0 is malformed" + +- id: placeholder_dependency_module_map_missing + msg: "cannot open Swift placeholder dependency module map from %0" + +- id: placeholder_dependency_module_map_corrupted + msg: "Swift placeholder dependency module map from %0 is malformed" - id: default_previous_install_name - msg: >- - default previous install name for %0 is %1 + msg: "default previous install name for %0 is %1" - id: platform_previous_install_name - msg: >- - previous install name for %0 in %1 is %2 + msg: "previous install name for %0 in %1 is %2" - id: unknown_platform_name - msg: >- - unkown platform name %0 + msg: "unkown platform name %0" - id: unknown_swift_module_name - msg: >- - cannot find Swift module with name %0 + msg: "cannot find Swift module with name %0" - id: cannot_find_install_name - msg: >- - cannot find previous install name for module %0 in %1 + msg: "cannot find previous install name for module %0 in %1" - id: symbol_in_tbd_not_in_ir - msg: >- - symbol '%0' (%1) is in TBD file, but not in generated IR + msg: "symbol '%0' (%1) is in TBD file, but not in generated IR" - id: symbol_in_ir_not_in_tbd - msg: >- - symbol '%0' (%1) is in generated IR file, but not in TBD file + msg: "symbol '%0' (%1) is in generated IR file, but not in TBD file" - id: tbd_validation_failure - msg: >- - please file a radar or open a bug on bugs.swift.org with this code, and - add -Xfrontend -validate-tbd-against-ir=none to squash the errors + msg: "please file a radar or open a bug on bugs.swift.org with this code, and add -Xfrontend -validate-tbd-against-ir=none to squash the errors" - id: redundant_prefix_compilation_flag - msg: >- - invalid argument '-D%0'; did you provide a redundant '-D' in your build - settings? + msg: "invalid argument '-D%0'; did you provide a redundant '-D' in your build settings?" - id: invalid_conditional_compilation_flag - msg: >- - conditional compilation flags must be valid Swift identifiers (rather - than '%0') + msg: "conditional compilation flags must be valid Swift identifiers (rather than '%0')" - id: cannot_assign_value_to_conditional_compilation_flag - msg: >- - conditional compilation flags do not have values in Swift; they are - either present or absent (rather than '%0') + msg: "conditional compilation flags do not have values in Swift; they are either present or absent (rather than '%0')" - id: framework_search_path_includes_framework_extension - msg: >- - framework search path ends in ".framework"; add directory containing - framework instead: %0 + msg: "framework search path ends in \".framework\"; add directory containing framework instead: %0" - id: error_optimization_remark_pattern - msg: >- - %0 in '%1' + msg: "%0 in '%1'" - id: error_invalid_debug_prefix_map - msg: >- - invalid argument '%0' to -debug-prefix-map; it must be of the form - 'original=remapped' + msg: "invalid argument '%0' to -debug-prefix-map; it must be of the form 'original=remapped'" - id: error_invalid_coverage_prefix_map - msg: >- - invalid argument '%0' to -coverage-prefix-map; it must be of the form - 'original=remapped' + msg: "invalid argument '%0' to -coverage-prefix-map; it must be of the form 'original=remapped'" - id: error_unable_to_write_swift_ranges_file - msg: >- - unable to write unparsed ranges file '$0': %1 + msg: "unable to write unparsed ranges file '$0': %1" - id: error_unable_to_write_compiled_source_file - msg: >- - unable to write compiled source file: '$0': %1 + msg: "unable to write compiled source file: '$0': %1" - id: invalid_vfs_overlay_file - msg: >- - invalid virtual overlay file '%0' + msg: "invalid virtual overlay file '%0'" - id: module_interface_scoped_import_unsupported - msg: >- - scoped imports are not yet supported in module interfaces + msg: "scoped imports are not yet supported in module interfaces" - id: warn_unsupported_module_interface_swift_version - msg: >- - module interfaces are only supported with Swift language version 5 or - later (currently using -swift-version %0) + msg: "module interfaces are only supported with Swift language version 5 or later (currently using -swift-version %0)" - id: warn_unsupported_module_interface_library_evolution - msg: >- - module interfaces are only supported with -enable-library-evolution + msg: "module interfaces are only supported with -enable-library-evolution" - id: error_extracting_version_from_module_interface - msg: >- - error extracting version from module interface + msg: "error extracting version from module interface" - id: unsupported_version_of_module_interface - msg: >- - unsupported version of module interface '%0': '%1' + msg: "unsupported version of module interface '%0': '%1'" - id: error_opening_explicit_module_file - msg: >- - failed to open explicit Swift module: %0 + msg: "failed to open explicit Swift module: %0" - id: error_extracting_flags_from_module_interface - msg: >- - error extracting flags from module interface + msg: "error extracting flags from module interface" - id: rebuilding_module_from_interface - msg: >- - rebuilding module '%0' from interface '%1' + msg: "rebuilding module '%0' from interface '%1'" - id: out_of_date_module_here - msg: >- - %select{compiled|cached|forwarding|prebuilt}0 module is out of date: '%1' + msg: "%select{compiled|cached|forwarding|prebuilt}0 module is out of date: '%1'" - id: module_interface_dependency_out_of_date - msg: >- - dependency is out of date: '%0' + msg: "dependency is out of date: '%0'" - id: module_interface_dependency_missing - msg: >- - dependency is missing: '%0' + msg: "dependency is missing: '%0'" - id: compiled_module_invalid - msg: >- - unable to load compiled module '%0' + msg: "unable to load compiled module '%0'" - id: compiled_module_invalid_reason - msg: >- - unable to load compiled module '%0': %1 + msg: "unable to load compiled module '%0': %1" - id: unknown_forced_module_loading_mode - msg: >- - unknown value for SWIFT_FORCE_MODULE_LOADING variable: '%0' + msg: "unknown value for SWIFT_FORCE_MODULE_LOADING variable: '%0'" - id: error_creating_remark_serializer - msg: >- - error while creating remark serializer: '%0' + msg: "error while creating remark serializer: '%0'" - id: interface_file_lock_failure - msg: >- - could not acquire lock file for module interface '%0' + msg: "could not acquire lock file for module interface '%0'" - id: interface_file_lock_timed_out - msg: >- - timed out waiting to acquire lock file for module interface '%0' + msg: "timed out waiting to acquire lock file for module interface '%0'" - id: dependency_cascading_mismatch - msg: >- - expected %select{non-cascading|cascading}0 dependency; found - %select{non-cascading|cascading}1 dependency instead + msg: "expected %select{non-cascading|cascading}0 dependency; found %select{non-cascading|cascading}1 dependency instead" - id: potential_dependency_cascading_mismatch - msg: >- - expected %select{non-cascading|cascading}0 potential member dependency; - found %select{non-cascading|cascading}1 potential member dependency instead + msg: "expected %select{non-cascading|cascading}0 potential member dependency; found %select{non-cascading|cascading}1 potential member dependency instead" - id: missing_member_dependency - msg: >- - expected %select{%error|provided|member|potential member|dynamic member}0 - dependency does not exist: %1 + msg: "expected %select{%error|provided|member|potential member|dynamic member}0 dependency does not exist: %1" - id: unexpected_dependency - msg: >- - unexpected %0 %select{%error|%error|member|potential member|dynamic - member}1 dependency: %2 + msg: "unexpected %0 %select{%error|%error|member|potential member|dynamic member}1 dependency: %2" - id: unexpected_provided_entity - msg: >- - unexpected provided entity: %0 + msg: "unexpected provided entity: %0" - id: negative_expectation_violated - msg: >- - unexpected dependency exists: %0 + msg: "unexpected dependency exists: %0" - id: expectation_missing_opening_braces - msg: >- - expected {{ in expectation + msg: "expected {{ in expectation" - id: expectation_missing_closing_braces - msg: >- - didn't find '}}' to match '{{' in expectation + msg: "didn't find '}}' to match '{{' in expectation" - id: module_incompatible_with_skip_function_bodies - msg: >- - module '%0' cannot be built with - -experimental-skip-non-inlinable-function-bodies; this option has been - automatically disabled + msg: "module '%0' cannot be built with -experimental-skip-non-inlinable-function-bodies; this option has been automatically disabled" - id: warning_parallel_execution_not_supported - msg: >- - parallel execution not supported; falling back to serial execution + msg: "parallel execution not supported; falling back to serial execution" - id: error_unable_to_execute_command - msg: >- - unable to execute command: %0 + msg: "unable to execute command: %0" - id: error_command_signalled_without_signal_number - msg: >- - %0 command failed due to signal (use -v to see invocation) + msg: "%0 command failed due to signal (use -v to see invocation)" - id: error_command_signalled - msg: >- - %0 command failed due to signal %1 (use -v to see invocation) + msg: "%0 command failed due to signal %1 (use -v to see invocation)" - id: error_command_failed - msg: >- - %0 command failed with exit code %1 (use -v to see invocation) + msg: "%0 command failed with exit code %1 (use -v to see invocation)" - id: error_expected_one_frontend_job - msg: >- - unable to handle compilation, expected exactly one frontend job + msg: "unable to handle compilation, expected exactly one frontend job" - id: error_expected_frontend_command - msg: >- - expected a swift frontend command + msg: "expected a swift frontend command" - id: error_cannot_specify__o_for_multiple_outputs - msg: >- - cannot specify -o when generating multiple output files + msg: "cannot specify -o when generating multiple output files" - id: error_static_emit_executable_disallowed - msg: >- - -static may not be used with -emit-executable + msg: "-static may not be used with -emit-executable" - id: error_unable_to_load_output_file_map - msg: >- - unable to load output file map '%1': %0 + msg: "unable to load output file map '%1': %0" - id: error_no_output_file_map_specified - msg: >- - no output file map specified + msg: "no output file map specified" - id: error_unable_to_make_temporary_file - msg: >- - unable to make temporary file: %0 + msg: "unable to make temporary file: %0" - id: error_no_input_files - msg: >- - no input files + msg: "no input files" - id: error_unexpected_input_file - msg: >- - unexpected input file: %0 + msg: "unexpected input file: %0" - id: error_unknown_target - msg: >- - unknown target '%0' + msg: "unknown target '%0'" - id: error_framework_bridging_header - msg: >- - using bridging headers with framework targets is unsupported + msg: "using bridging headers with framework targets is unsupported" - id: error_bridging_header_module_interface - msg: >- - using bridging headers with module interfaces is unsupported + msg: "using bridging headers with module interfaces is unsupported" - id: error_i_mode - msg: >- - the flag '-i' is no longer required and has been removed; use '%0 - input-filename' + msg: "the flag '-i' is no longer required and has been removed; use '%0 input-filename'" - id: warning_unnecessary_repl_mode - msg: >- - unnecessary option '%0'; this is the default for '%1' with no input files + msg: "unnecessary option '%0'; this is the default for '%1' with no input files" - id: error_unsupported_option - msg: >- - option '%0' is not supported by '%1'; did you mean to use '%2'? + msg: "option '%0' is not supported by '%1'; did you mean to use '%2'?" - id: incremental_requires_output_file_map - msg: >- - ignoring -incremental (currently requires an output file map) + msg: "ignoring -incremental (currently requires an output file map)" - id: incremental_requires_build_record_entry - msg: >- - ignoring -incremental; output file map has no master dependencies entry - ("%0" under "") + msg: "ignoring -incremental; output file map has no master dependencies entry (\"%0\" under \"\")" - id: unable_to_open_incremental_comparison_log - msg: >- - unable to open incremental comparison log file '%0' + msg: "unable to open incremental comparison log file '%0'" - id: error_os_minimum_deployment - msg: >- - Swift requires a minimum deployment target of %0 + msg: "Swift requires a minimum deployment target of %0" - id: error_sdk_too_old - msg: >- - Swift does not support the SDK '%0' + msg: "Swift does not support the SDK '%0'" - id: error_ios_maximum_deployment_32 - msg: >- - iOS %0 does not support 32-bit programs + msg: "iOS %0 does not support 32-bit programs" - id: error_unsupported_target_variant - msg: >- - unsupported '%select{-target|-target-variant}1' value '%0'; use - 'ios-macabi' instead + msg: "unsupported '%select{-target|-target-variant}1' value '%0'; use 'ios-macabi' instead" - id: warn_arclite_not_found_when_link_objc_runtime - msg: >- - unable to find Objective-C runtime support library 'arclite'; pass - '-no-link-objc-runtime' to silence this warning - -- id: error_two_files_same_name - msg: >- - filename "%0" used twice: '%1' and '%2' - -- id: note_explain_two_files_same_name - msg: >- - filenames are used to distinguish private declarations with the same name + msg: "unable to find Objective-C runtime support library 'arclite'; pass '-no-link-objc-runtime' to silence this warning" - id: warn_cannot_stat_input - msg: >- - unable to determine when '%0' was last modified: %1 + msg: "unable to determine when '%0' was last modified: %1" - id: warn_unable_to_load_dependencies - msg: >- - unable to load dependencies file "%0", disabling incremental mode + msg: "unable to load dependencies file \"%0\", disabling incremental mode" - id: error_input_changed_during_build - msg: >- - input file '%0' was modified during the build + msg: "input file '%0' was modified during the build" - id: error_conflicting_options - msg: >- - conflicting options '%0' and '%1' + msg: "conflicting options '%0' and '%1'" - id: error_option_not_supported - msg: >- - '%0' is not supported with '%1' + msg: "'%0' is not supported with '%1'" + +- id: error_requirement_not_met + msg: "'%0' requires '%1'" - id: warn_ignore_embed_bitcode - msg: >- - ignoring -embed-bitcode since no object file is being generated + msg: "ignoring -embed-bitcode since no object file is being generated" - id: warn_ignore_embed_bitcode_marker - msg: >- - ignoring -embed-bitcode-marker since no object file is being generated + msg: "ignoring -embed-bitcode-marker since no object file is being generated" - id: verify_debug_info_requires_debug_option - msg: >- - ignoring '-verify-debug-info'; no debug info is being generated + msg: "ignoring '-verify-debug-info'; no debug info is being generated" - id: verify_incremental_dependencies_needs_incremental - msg: >- - '-verify-incremental-dependencies' requires '-incremental' + msg: "'-verify-incremental-dependencies' requires '-incremental'" - id: error_profile_missing - msg: >- - no profdata file exists at '%0' + msg: "no profdata file exists at '%0'" - id: warn_opt_remark_disabled - msg: >- - Emission of optimization records has been disabled, because it requires a - single compiler invocation: consider enabling the -whole-module-optimization - flag + msg: "Emission of optimization records has been disabled, because it requires a single compiler invocation: consider enabling the -whole-module-optimization flag" - id: warn_ignoring_batch_mode - msg: >- - ignoring '-enable-batch-mode' because '%0' was also specified + msg: "ignoring '-enable-batch-mode' because '%0' was also specified" - id: warn_ignoring_wmo - msg: >- - ignoring '-wmo' because '-dump-ast' was also specified + msg: "ignoring '-wmo' because '-dump-ast' was also specified" - id: warn_ignoring_source_range_dependencies - msg: >- - ignoring '-enable-source-range-dependencies' because '%0' was also specified + msg: "ignoring '-enable-source-range-dependencies' because '%0' was also specified" - id: warn_bad_swift_ranges_header - msg: >- - ignoring '-enable-source-range-dependencies' because of bad header in '%0' + msg: "ignoring '-enable-source-range-dependencies' because of bad header in '%0'" - id: warn_bad_swift_ranges_format - msg: >- - ignoring '-enable-source-range-dependencies' because of bad format '%1' - in '%0' + msg: "ignoring '-enable-source-range-dependencies' because of bad format '%1' in '%0'" - id: warn_use_filelists_deprecated - msg: >- - the option '-driver-use-filelists' is deprecated; use - '-driver-filelist-threshold=0' instead + msg: "the option '-driver-use-filelists' is deprecated; use '-driver-filelist-threshold=0' instead" - id: warn_unable_to_load_swift_ranges - msg: >- - unable to load swift ranges file "%0", %1 + msg: "unable to load swift ranges file \"%0\", %1" - id: warn_unable_to_load_compiled_swift - msg: >- - unable to load previously compiled swift file "%0", %1 + msg: "unable to load previously compiled swift file \"%0\", %1" - id: warn_unable_to_load_primary - msg: >- - unable to load primary swift file "%0", %1 + msg: "unable to load primary swift file \"%0\", %1" - id: cannot_find_migration_script - msg: >- - missing migration script from path '%0' + msg: "missing migration script from path '%0'" - id: error_darwin_static_stdlib_not_supported - msg: >- - -static-stdlib is no longer supported on Apple platforms + msg: "-static-stdlib is no longer supported on Apple platforms" + +- id: error_darwin_only_supports_libcxx + msg: "The only C++ standard library supported on Apple platforms is libc++" - id: warn_drv_darwin_sdk_invalid_settings - msg: >- - SDK settings were ignored because 'SDKSettings.json' could not be parsed + msg: "SDK settings were ignored because 'SDKSettings.json' could not be parsed" - id: invalid_name - msg: >- - '%0' is not a valid name + msg: "'%0' is not a valid name" - id: invalid_location - msg: >- - given location is not valid + msg: "given location is not valid" - id: arity_mismatch - msg: >- - the given new name '%0' does not match the arity of the old name '%1' + msg: "the given new name '%0' does not match the arity of the old name '%1'" - id: name_not_functionlike - msg: >- - the 'call' name usage cannot be used with a non-function-like name '%0' + msg: "the 'call' name usage cannot be used with a non-function-like name '%0'" - id: unresolved_location - msg: >- - cannot resolve location as name + msg: "cannot resolve location as name" - id: location_module_mismatch - msg: >- - given location does not belong to module '%0' + msg: "given location does not belong to module '%0'" - id: value_decl_no_loc - msg: >- - value decl '%0' has no declaration location + msg: "value decl '%0' has no declaration location" - id: value_decl_referenced_out_of_range - msg: >- - value decl '%0' is referenced out of range + msg: "value decl '%0' is referenced out of range" - id: multi_entry_range - msg: >- - selected range has more than one entry point + msg: "selected range has more than one entry point" - id: orphan_loop_keyword - msg: >- - selected range contains %0 but not its target loop + msg: "selected range contains %0 but not its target loop" - id: invalid_default_location - msg: >- - given location is not on a default statement + msg: "given location is not on a default statement" - id: no_parent_switch - msg: >- - cannot find enclosing switch statement + msg: "cannot find enclosing switch statement" - id: no_remaining_cases - msg: >- - no remaining cases to expand + msg: "no remaining cases to expand" - id: mismatched_rename - msg: >- - the name at the given location cannot be renamed to '%0' + msg: "the name at the given location cannot be renamed to '%0'" - id: no_insert_position - msg: >- - cannot find inserting position + msg: "cannot find inserting position" - id: generic_sig_change - msg: >- - %0 has generic signature change from %1 to %2 + msg: "%0 has generic signature change from %1 to %2" - id: raw_type_change - msg: >- - %0(%1) is now %2 representable + msg: "%0(%1) is now %2 representable" - id: removed_decl - msg: >- - %0 has been removed%select{| (deprecated)}1 + msg: "%0 has been removed%select{| (deprecated)}1" - id: moved_decl - msg: >- - %0 has been moved to %1 + msg: "%0 has been moved to %1" - id: renamed_decl - msg: >- - %0 has been renamed to %1 + msg: "%0 has been renamed to %1" - id: decl_type_change - msg: >- - %0 has %1 type change from %2 to %3 + msg: "%0 has %1 type change from %2 to %3" - id: decl_attr_change - msg: >- - %0 changes from %1 to %2 + msg: "%0 changes from %1 to %2" - id: decl_new_attr - msg: >- - %0 is now %1 + msg: "%0 is now %1" - id: decl_reorder - msg: >- - %0 in a non-resilient type changes position from %1 to %2 + msg: "%0 in a non-resilient type changes position from %1 to %2" - id: decl_added - msg: >- - %0 is added to a non-resilient type + msg: "%0 is added to a non-resilient type" - id: var_has_fixed_order_change - msg: >- - %0 is %select{now|no longer}1 a stored property + msg: "%0 is %select{now|no longer}1 a stored property" - id: func_has_fixed_order_change - msg: >- - %0 is %select{now|no longer}1 a non-final instance function + msg: "%0 is %select{now|no longer}1 a non-final instance function" - id: default_arg_removed - msg: >- - %0 has removed default argument from %1 + msg: "%0 has removed default argument from %1" - id: conformance_removed - msg: >- - %0 has removed %select{conformance to|inherited protocol}2 %1 + msg: "%0 has removed %select{conformance to|inherited protocol}2 %1" - id: conformance_added - msg: >- - %0 has added inherited protocol %1 + msg: "%0 has added inherited protocol %1" - id: existing_conformance_added - msg: >- - %0 has added a conformance to an existing protocol %1 + msg: "%0 has added a conformance to an existing protocol %1" - id: default_associated_type_removed - msg: >- - %0 has removed default type %1 + msg: "%0 has removed default type %1" - id: protocol_req_added - msg: >- - %0 has been added as a protocol requirement + msg: "%0 has been added as a protocol requirement" - id: super_class_removed - msg: >- - %0 has removed its super class %1 + msg: "%0 has removed its super class %1" - id: super_class_changed - msg: >- - %0 has changed its super class from %1 to %2 + msg: "%0 has changed its super class from %1 to %2" - id: decl_kind_changed - msg: >- - %0 has been changed to a %1 + msg: "%0 has been changed to a %1" - id: optional_req_changed - msg: >- - %0 is %select{now|no longer}1 an optional requirement + msg: "%0 is %select{now|no longer}1 an optional requirement" - id: no_longer_open - msg: >- - %0 is no longer open for subclassing + msg: "%0 is no longer open for subclassing" - id: func_type_escaping_changed - msg: >- - %0 has %select{removed|added}2 @escaping in %1 + msg: "%0 has %select{removed|added}2 @escaping in %1" - id: func_self_access_change - msg: >- - %0 has self access kind changing from %1 to %2 + msg: "%0 has self access kind changing from %1 to %2" - id: param_ownership_change - msg: >- - %0 has %1 changing from %2 to %3 + msg: "%0 has %1 changing from %2 to %3" - id: type_witness_change - msg: >- - %0 has type witness type for %1 changing from %2 to %3 + msg: "%0 has type witness type for %1 changing from %2 to %3" - id: decl_new_witness_table_entry - msg: >- - %0 now requires %select{|no}1 new witness table entry + msg: "%0 now requires %select{|no}1 new witness table entry" - id: new_decl_without_intro - msg: >- - %0 is a new API without @available attribute + msg: "%0 is a new API without @available attribute" - id: objc_name_change - msg: >- - %0 has ObjC name change from %1 to %2 + msg: "%0 has ObjC name change from %1 to %2" - id: desig_init_added - msg: >- - %0 has been added as a designated initializer to an open class + msg: "%0 has been added as a designated initializer to an open class" - id: added_invisible_designated_init - msg: >- - %0 has new designated initializers that are not visible to clients + msg: "%0 has new designated initializers that are not visible to clients" - id: not_inheriting_convenience_inits - msg: >- - %0 no longer inherits convenience inits from its superclass + msg: "%0 no longer inherits convenience inits from its superclass" - id: enum_case_added - msg: >- - %0 has been added as a new enum case + msg: "%0 has been added as a new enum case" diff --git a/stdlib/CMakeLists.txt b/stdlib/CMakeLists.txt index 00f23b8a0f267..d692ef67d1d70 100644 --- a/stdlib/CMakeLists.txt +++ b/stdlib/CMakeLists.txt @@ -9,6 +9,26 @@ project(swift-stdlib LANGUAGES C CXX) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") +# +# User-configurable options for the standard library. +# + +option(SWIFT_ENABLE_COMPATIBILITY_OVERRIDES + "Support back-deploying compatibility fixes for newer apps running on older runtimes." + TRUE) + +option(SWIFT_RUNTIME_MACHO_NO_DYLD + "Build stdlib assuming the runtime environment uses Mach-O but does not support dynamic modules." + FALSE) + +option(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + "Build the standard libraries assuming that they will be used in an environment with only a single thread." + FALSE) + +# +# End of user-configurable options. +# + include(AddSwiftStdlib) # Create convenience targets for the Swift standard library. diff --git a/stdlib/cmake/modules/AddSwiftStdlib.cmake b/stdlib/cmake/modules/AddSwiftStdlib.cmake index a899f495df78f..adf466ee1c144 100644 --- a/stdlib/cmake/modules/AddSwiftStdlib.cmake +++ b/stdlib/cmake/modules/AddSwiftStdlib.cmake @@ -2,20 +2,6 @@ include(AddSwift) include(SwiftSource) -function(is_darwin_based_sdk sdk_name out_var) - if ("${sdk_name}" STREQUAL "OSX" OR - "${sdk_name}" STREQUAL "IOS" OR - "${sdk_name}" STREQUAL "IOS_SIMULATOR" OR - "${sdk_name}" STREQUAL "TVOS" OR - "${sdk_name}" STREQUAL "TVOS_SIMULATOR" OR - "${sdk_name}" STREQUAL "WATCHOS" OR - "${sdk_name}" STREQUAL "WATCHOS_SIMULATOR") - set(${out_var} TRUE PARENT_SCOPE) - else() - set(${out_var} FALSE PARENT_SCOPE) - endif() -endfunction() - function(add_dependencies_multiple_targets) cmake_parse_arguments( ADMT # prefix @@ -63,8 +49,7 @@ function(_add_target_variant_c_compile_link_flags) set(result ${${CFLAGS_RESULT_VAR_NAME}}) - is_darwin_based_sdk("${CFLAGS_SDK}" IS_DARWIN) - if(IS_DARWIN) + if("${CFLAGS_SDK}" IN_LIST SWIFT_APPLE_PLATFORMS) # Check if there's a specific OS deployment version needed for this invocation if("${CFLAGS_SDK}" STREQUAL "OSX") if(DEFINED maccatalyst_build_flavor) @@ -98,7 +83,7 @@ function(_add_target_variant_c_compile_link_flags) endif() set(_sysroot "${SWIFT_SDK_${CFLAGS_SDK}_ARCH_${CFLAGS_ARCH}_PATH}") - if(IS_DARWIN) + if(SWIFT_SDK_${CFLAGS_SDK}_USE_ISYSROOT) list(APPEND result "-isysroot" "${_sysroot}") elseif(NOT SWIFT_COMPILER_IS_MSVC_LIKE AND NOT "${_sysroot}" STREQUAL "/") list(APPEND result "--sysroot=${_sysroot}") @@ -113,7 +98,7 @@ function(_add_target_variant_c_compile_link_flags) endif() endif() - if(IS_DARWIN) + if("${CFLAGS_SDK}" IN_LIST SWIFT_APPLE_PLATFORMS) # We collate -F with the framework path to avoid unwanted deduplication # of options by target_compile_options -- this way no undesired # side effects are introduced should a new search path be added. @@ -179,13 +164,18 @@ function(_add_target_variant_c_compile_flags) MACCATALYST_BUILD_FLAVOR "${CFLAGS_MACCATALYST_BUILD_FLAVOR}") is_build_type_optimized("${CFLAGS_BUILD_TYPE}" optimized) - if(optimized) - list(APPEND result "-O2") + is_build_type_with_debuginfo("${CFLAGS_BUILD_TYPE}" debuginfo) + + # Add -O0/-O2/-O3/-Os/-g/... based on CFLAGS_BUILD_TYPE. + list(APPEND result "${CMAKE_CXX_FLAGS_${CFLAGS_BUILD_TYPE}}") + if(optimized) # Omit leaf frame pointers on x86 production builds (optimized, no debug # info, and no asserts). - is_build_type_with_debuginfo("${CFLAGS_BUILD_TYPE}" debug) - if(NOT debug AND NOT CFLAGS_ENABLE_ASSERTIONS) + if(NOT debuginfo AND NOT CFLAGS_ENABLE_ASSERTIONS) + # Unfortunately, this cannot be folded into the standard + # CMAKE_CXX_FLAGS_... because Apple multi-SDK builds use different + # architectures for different SDKs (CFLAGS_ARCH isn't constant here). if("${CFLAGS_ARCH}" STREQUAL "i386" OR "${CFLAGS_ARCH}" STREQUAL "i686") if(NOT SWIFT_COMPILER_IS_MSVC_LIKE) list(APPEND result "-momit-leaf-frame-pointer") @@ -194,27 +184,6 @@ function(_add_target_variant_c_compile_flags) endif() endif() endif() - else() - if(NOT SWIFT_COMPILER_IS_MSVC_LIKE) - list(APPEND result "-O0") - else() - list(APPEND result "/Od") - endif() - endif() - - # CMake automatically adds the flags for debug info if we use MSVC/clang-cl. - if(NOT SWIFT_COMPILER_IS_MSVC_LIKE) - is_build_type_with_debuginfo("${CFLAGS_BUILD_TYPE}" debuginfo) - if(debuginfo) - _compute_lto_flag("${CFLAGS_ENABLE_LTO}" _lto_flag_out) - if(_lto_flag_out) - list(APPEND result "-gline-tables-only") - else() - list(APPEND result "-g") - endif() - else() - list(APPEND result "-g0") - endif() endif() if("${CFLAGS_SDK}" STREQUAL "WINDOWS") @@ -329,6 +298,22 @@ function(_add_target_variant_c_compile_flags) list(APPEND result "-D_WASI_EMULATED_MMAN") endif() + if(SWIFT_DISABLE_OBJC_INTEROP) + list(APPEND result "-DSWIFT_OBJC_INTEROP=0") + endif() + + if(NOT SWIFT_ENABLE_COMPATIBILITY_OVERRIDES) + list(APPEND result "-DSWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES") + endif() + + if(SWIFT_RUNTIME_MACHO_NO_DYLD) + list(APPEND result "-DSWIFT_RUNTIME_MACHO_NO_DYLD") + endif() + + if(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME) + list(APPEND result "-DSWIFT_STDLIB_SINGLE_THREADED_RUNTIME") + endif() + set("${CFLAGS_RESULT_VAR_NAME}" "${result}" PARENT_SCOPE) endfunction() @@ -497,7 +482,7 @@ function(_add_swift_lipo_target) list(APPEND source_binaries $) endforeach() - if(${LIPO_SDK} IN_LIST SWIFT_APPLE_PLATFORMS) + if("${SWIFT_SDK_${LIPO_SDK}_OBJECT_FORMAT}" STREQUAL "MACHO") if(LIPO_CODESIGN) set(codesign_command COMMAND "codesign" "-f" "-s" "-" "${LIPO_OUTPUT}") endif() diff --git a/stdlib/cmake/modules/SwiftSource.cmake b/stdlib/cmake/modules/SwiftSource.cmake index e6f63c08298d1..d7ac8afa8f0bf 100644 --- a/stdlib/cmake/modules/SwiftSource.cmake +++ b/stdlib/cmake/modules/SwiftSource.cmake @@ -11,6 +11,21 @@ function(compute_library_subdir result_var_name sdk arch) endif() endfunction() +# Return a swiftc flag (e.g. -O or -Onone) to control optimization level based +# on the build type. +function(swift_optimize_flag_for_build_type build_type result_var_name) + if("${build_type}" STREQUAL "Debug") + set("${result_var_name}" "-Onone" PARENT_SCOPE) + elseif("${build_type}" STREQUAL "RelWithDebInfo" OR + "${build_type}" STREQUAL "Release") + set("${result_var_name}" "-O" PARENT_SCOPE) + elseif("${build_type}" STREQUAL "MinSizeRel") + set("${result_var_name}" "-Osize" PARENT_SCOPE) + else() + message(FATAL_ERROR "Unknown build type: ${build_type}") + endif() +endfunction() + # Process the sources within the given variable, pulling out any Swift # sources to be compiled with 'swift' directly. This updates # ${sourcesvar} in place with the resulting list and ${externalvar} with the @@ -195,8 +210,7 @@ function(_add_target_variant_swift_compile_flags list(APPEND result "-sdk" "${SWIFT_SDK_${sdk}_ARCH_${arch}_PATH}") endif() - is_darwin_based_sdk("${sdk}" IS_DARWIN) - if(IS_DARWIN) + if("${sdk}" IN_LIST SWIFT_APPLE_PLATFORMS) set(sdk_deployment_version "${SWIFT_SDK_${sdk}_DEPLOYMENT_VERSION}") get_target_triple(target target_variant "${sdk}" "${arch}" MACCATALYST_BUILD_FLAVOR "${VARIANT_MACCATALYST_BUILD_FLAVOR}" @@ -224,7 +238,7 @@ function(_add_target_variant_swift_compile_flags list(APPEND result "-resource-dir" "${SWIFTLIB_DIR}") endif() - if(IS_DARWIN) + if("${sdk}" IN_LIST SWIFT_APPLE_PLATFORMS) # We collate -F with the framework path to avoid unwanted deduplication # of options by target_compile_options -- this way no undesired # side effects are introduced should a new search path be added. @@ -232,12 +246,8 @@ function(_add_target_variant_swift_compile_flags "-F${SWIFT_SDK_${sdk}_ARCH_${arch}_PATH}/../../../Developer/Library/Frameworks") endif() - is_build_type_optimized("${build_type}" optimized) - if(optimized) - list(APPEND result "-O") - else() - list(APPEND result "-Onone") - endif() + swift_optimize_flag_for_build_type("${CMAKE_BUILD_TYPE}" optimize_flag) + list(APPEND result "${optimize_flag}") is_build_type_with_debuginfo("${build_type}" debuginfo) if(debuginfo) @@ -396,7 +406,7 @@ function(_compile_swift_files list(APPEND swift_flags "-enable-library-evolution") endif() - if(SWIFT_STDLIB_USE_NONATOMIC_RC) + if(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME) list(APPEND swift_flags "-Xfrontend" "-assume-single-threaded") endif() @@ -441,6 +451,10 @@ function(_compile_swift_files list(APPEND swift_flags "-warn-swift3-objc-inference-complete") endif() + if(SWIFT_DISABLE_OBJC_INTEROP) + list(APPEND swift_flags "-Xfrontend" "-disable-objc-interop") + endif() + list(APPEND swift_flags ${SWIFT_EXPERIMENTAL_EXTRA_FLAGS}) if(SWIFTFILE_OPT_FLAGS) diff --git a/stdlib/private/DifferentiationUnittest/CMakeLists.txt b/stdlib/private/DifferentiationUnittest/CMakeLists.txt index bb6284b191310..33da12b9b766a 100644 --- a/stdlib/private/DifferentiationUnittest/CMakeLists.txt +++ b/stdlib/private/DifferentiationUnittest/CMakeLists.txt @@ -1,6 +1,6 @@ add_swift_target_library(swiftDifferentiationUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB # This file should be listed first. Module name is inferred from the filename. - DifferentiationUnittest.swift + GYB_SOURCES DifferentiationUnittest.swift.gyb SWIFT_MODULE_DEPENDS _Differentiation StdlibUnittest INSTALL_IN_COMPONENT stdlib-experimental diff --git a/stdlib/private/DifferentiationUnittest/DifferentiationUnittest.swift b/stdlib/private/DifferentiationUnittest/DifferentiationUnittest.swift.gyb similarity index 50% rename from stdlib/private/DifferentiationUnittest/DifferentiationUnittest.swift rename to stdlib/private/DifferentiationUnittest/DifferentiationUnittest.swift.gyb index f24dd18a7925e..282f89f93324f 100644 --- a/stdlib/private/DifferentiationUnittest/DifferentiationUnittest.swift +++ b/stdlib/private/DifferentiationUnittest/DifferentiationUnittest.swift.gyb @@ -1,4 +1,4 @@ -//===--- DifferentiationUnittest.swift ------------------------------------===// +//===--- DifferentiationUnittest.swift.gyb --------------------------------===// // // This source file is part of the Swift.org open source project // @@ -43,19 +43,21 @@ public extension TestSuite { _ testFunction: @escaping () -> Void ) { test(name, file: file, line: line) { - withLeakChecking(expectedLeakCount: expectedLeakCount, file: file, - line: line, testFunction) + withLeakChecking( + expectedLeakCount: expectedLeakCount, file: file, + line: line, testFunction) } } } -/// A type that tracks the number of live instances of a wrapped value type. +/// A resilient type that tracks the number of live instances of a wrapped +/// value type. /// /// `Tracked` is used to check for memory leaks in functions created via /// automatic differentiation. public struct Tracked { - fileprivate class Box { - fileprivate var value : T + internal class Box { + fileprivate var value: T init(_ value: T) { self.value = value _GlobalLeakCount.count += 1 @@ -64,71 +66,109 @@ public struct Tracked { _GlobalLeakCount.count -= 1 } } - private var handle: Box + internal var handle: Box - @differentiable(where T : Differentiable, T == T.TangentVector) + @differentiable(where T: Differentiable, T == T.TangentVector) public init(_ value: T) { self.handle = Box(value) } - @differentiable(where T : Differentiable, T == T.TangentVector) + @differentiable(where T: Differentiable, T == T.TangentVector) public var value: T { get { handle.value } set { handle.value = newValue } } } -extension Tracked : ExpressibleByFloatLiteral where T : ExpressibleByFloatLiteral { +/// A non-resilient type that tracks the number of live instances of a wrapped +/// value type. +/// +/// `NonresilientTracked` is used to check for memory leaks in functions +/// created via automatic differentiation. +@frozen +public struct NonresilientTracked { + @usableFromInline + internal class Box { + fileprivate var value: T + init(_ value: T) { + self.value = value + _GlobalLeakCount.count += 1 + } + deinit { + _GlobalLeakCount.count -= 1 + } + } + @usableFromInline + internal var handle: Box + + @differentiable(where T: Differentiable, T == T.TangentVector) + public init(_ value: T) { + self.handle = Box(value) + } + + @differentiable(where T: Differentiable, T == T.TangentVector) + public var value: T { + get { handle.value } + set { handle.value = newValue } + } +} + +% for Self in ['Tracked', 'NonresilientTracked']: + +extension ${Self}: ExpressibleByFloatLiteral +where T: ExpressibleByFloatLiteral { public init(floatLiteral value: T.FloatLiteralType) { self.handle = Box(T(floatLiteral: value)) } } -extension Tracked : CustomStringConvertible { - public var description: String { return "Tracked(\(value))" } +extension ${Self}: CustomStringConvertible { + public var description: String { return "${Self}(\(value))" } } -extension Tracked : ExpressibleByIntegerLiteral where T : ExpressibleByIntegerLiteral { +extension ${Self}: ExpressibleByIntegerLiteral +where T: ExpressibleByIntegerLiteral { public init(integerLiteral value: T.IntegerLiteralType) { self.handle = Box(T(integerLiteral: value)) } } -extension Tracked : Comparable where T : Comparable { - public static func < (lhs: Tracked, rhs: Tracked) -> Bool { +extension ${Self}: Comparable where T: Comparable { + public static func < (lhs: ${Self}, rhs: ${Self}) -> Bool { return lhs.value < rhs.value } - public static func <= (lhs: Tracked, rhs: Tracked) -> Bool { + public static func <= (lhs: ${Self}, rhs: ${Self}) -> Bool { return lhs.value <= rhs.value } - public static func > (lhs: Tracked, rhs: Tracked) -> Bool { + public static func > (lhs: ${Self}, rhs: ${Self}) -> Bool { return lhs.value > rhs.value } - public static func >= (lhs: Tracked, rhs: Tracked) -> Bool { + public static func >= (lhs: ${Self}, rhs: ${Self}) -> Bool { return lhs.value >= rhs.value } } -extension Tracked : AdditiveArithmetic where T : AdditiveArithmetic { - public static var zero: Tracked { return Tracked(T.zero) } - public static func + (lhs: Tracked, rhs: Tracked) -> Tracked { - return Tracked(lhs.value + rhs.value) +extension ${Self}: AdditiveArithmetic where T: AdditiveArithmetic { + public static var zero: ${Self} { return ${Self}(T.zero) } + public static func + (lhs: ${Self}, rhs: ${Self}) -> ${Self} { + return ${Self}(lhs.value + rhs.value) } - public static func - (lhs: Tracked, rhs: Tracked) -> Tracked { - return Tracked(lhs.value - rhs.value) + public static func - (lhs: ${Self}, rhs: ${Self}) -> ${Self} { + return ${Self}(lhs.value - rhs.value) } } -extension Tracked : Equatable where T : Equatable { - public static func == (lhs: Tracked, rhs: Tracked) -> Bool { +extension ${Self}: Equatable where T: Equatable { + public static func == (lhs: ${Self}, rhs: ${Self}) -> Bool { return lhs.value == rhs.value } } -extension Tracked : SignedNumeric & Numeric where T : SignedNumeric, T == T.Magnitude { - public typealias Magnitude = Tracked +extension ${Self}: SignedNumeric & Numeric +where T: SignedNumeric, T == T.Magnitude { + public typealias Magnitude = ${Self} - public init?(exactly source: U) where U : BinaryInteger { + public init?(exactly source: U) where U: BinaryInteger { if let t = T(exactly: source) { self.init(t) } @@ -136,169 +176,191 @@ extension Tracked : SignedNumeric & Numeric where T : SignedNumeric, T == T.Magn } public var magnitude: Magnitude { return Magnitude(value.magnitude) } - public static func * (lhs: Tracked, rhs: Tracked) -> Tracked { - return Tracked(lhs.value * rhs.value) + public static func * (lhs: ${Self}, rhs: ${Self}) -> ${Self} { + return ${Self}(lhs.value * rhs.value) } - public static func *= (lhs: inout Tracked, rhs: Tracked) { + public static func *= (lhs: inout ${Self}, rhs: ${Self}) { lhs = lhs * rhs } } -extension Tracked where T : FloatingPoint { - public static func / (lhs: Tracked, rhs: Tracked) -> Tracked { - return Tracked(lhs.value / rhs.value) +extension ${Self} where T: FloatingPoint { + public static func / (lhs: ${Self}, rhs: ${Self}) -> ${Self} { + return ${Self}(lhs.value / rhs.value) } - public static func /= (lhs: inout Tracked, rhs: Tracked) { + public static func /= (lhs: inout ${Self}, rhs: ${Self}) { lhs = lhs / rhs } } -extension Tracked : Strideable where T : Strideable, T.Stride == T.Stride.Magnitude { - public typealias Stride = Tracked +extension ${Self}: Strideable +where T: Strideable, T.Stride == T.Stride.Magnitude { + public typealias Stride = ${Self} - public func distance(to other: Tracked) -> Stride { + public func distance(to other: ${Self}) -> Stride { return Stride(value.distance(to: other.value)) } - public func advanced(by n: Stride) -> Tracked { - return Tracked(value.advanced(by: n.value)) + public func advanced(by n: Stride) -> ${Self} { + return ${Self}(value.advanced(by: n.value)) } } // For now, `T` must be restricted to trivial types (like `Float` or `Tensor`). -extension Tracked : Differentiable where T : Differentiable, T == T.TangentVector { - public typealias TangentVector = Tracked +extension ${Self}: Differentiable +where T: Differentiable, T == T.TangentVector { + public typealias TangentVector = ${Self} } -extension Tracked where T : Differentiable, T == T.TangentVector { +extension ${Self} where T: Differentiable, T == T.TangentVector { @usableFromInline @derivative(of: init) internal static func _vjpInit(_ value: T) - -> (value: Self, pullback: (Self.TangentVector) -> (T.TangentVector)) { - return (Tracked(value), { v in v.value }) + -> (value: Self, pullback: (Self.TangentVector) -> (T.TangentVector)) + { + return (${Self}(value), { v in v.value }) } @usableFromInline @derivative(of: init) internal static func _jvpInit(_ value: T) - -> (value: Self, differential: (T.TangentVector) -> (Self.TangentVector)) { - return (Tracked(value), { v in Tracked(v) }) + -> (value: Self, differential: (T.TangentVector) -> (Self.TangentVector)) + { + return (${Self}(value), { v in ${Self}(v) }) } @usableFromInline @derivative(of: value) - internal func _vjpValue() -> (value: T, pullback: (T.TangentVector) -> Self.TangentVector) { - return (value, { v in Tracked(v) }) + internal func _vjpValue() -> ( + value: T, pullback: (T.TangentVector) -> Self.TangentVector + ) { + return (value, { v in ${Self}(v) }) } @usableFromInline @derivative(of: value) - internal func _jvpValue() -> (value: T, differential: (Self.TangentVector) -> T.TangentVector) { + internal func _jvpValue() -> ( + value: T, differential: (Self.TangentVector) -> T.TangentVector + ) { return (value, { v in v.value }) } } -extension Tracked where T : Differentiable, T == T.TangentVector { +extension ${Self} where T: Differentiable, T == T.TangentVector { @usableFromInline @derivative(of: +) internal static func _vjpAdd(lhs: Self, rhs: Self) - -> (value: Self, pullback: (Self) -> (Self, Self)) { + -> (value: Self, pullback: (Self) -> (Self, Self)) + { return (lhs + rhs, { v in (v, v) }) } @usableFromInline @derivative(of: +) internal static func _jvpAdd(lhs: Self, rhs: Self) - -> (value: Self, differential: (Self, Self) -> Self) { + -> (value: Self, differential: (Self, Self) -> Self) + { return (lhs + rhs, { $0 + $1 }) } @usableFromInline @derivative(of: -) internal static func _vjpSubtract(lhs: Self, rhs: Self) - -> (value: Self, pullback: (Self) -> (Self, Self)) { + -> (value: Self, pullback: (Self) -> (Self, Self)) + { return (lhs - rhs, { v in (v, .zero - v) }) } @usableFromInline @derivative(of: -) internal static func _jvpSubtract(lhs: Self, rhs: Self) - -> (value: Self, differential: (Self, Self) -> Self) { + -> (value: Self, differential: (Self, Self) -> Self) + { return (lhs - rhs, { $0 - $1 }) } } -extension Tracked where T : Differentiable & SignedNumeric, T == T.Magnitude, - T == T.TangentVector { +extension ${Self} +where + T: Differentiable & SignedNumeric, T == T.Magnitude, + T == T.TangentVector +{ @usableFromInline @derivative(of: *) internal static func _vjpMultiply(lhs: Self, rhs: Self) - -> (value: Self, pullback: (Self) -> (Self, Self)) { + -> (value: Self, pullback: (Self) -> (Self, Self)) + { return (lhs * rhs, { v in (v * rhs, v * lhs) }) } @usableFromInline @derivative(of: *) internal static func _jvpMultiply(lhs: Self, rhs: Self) - -> (value: Self, differential: (Self, Self) -> (Self)) { + -> (value: Self, differential: (Self, Self) -> (Self)) + { return (lhs * rhs, { (dx, dy) in dx * rhs + dy * lhs }) } } -extension Tracked where T : Differentiable & FloatingPoint, T == T.TangentVector { +extension ${Self} +where T: Differentiable & FloatingPoint, T == T.TangentVector { @usableFromInline @derivative(of: /) internal static func _vjpDivide(lhs: Self, rhs: Self) - -> (value: Self, pullback: (Self) -> (Self, Self)) { + -> (value: Self, pullback: (Self) -> (Self, Self)) + { return (lhs / rhs, { v in (v / rhs, -lhs / (rhs * rhs) * v) }) } @usableFromInline @derivative(of: /) internal static func _jvpDivide(lhs: Self, rhs: Self) - -> (value: Self, differential: (Self, Self) -> (Self)) { + -> (value: Self, differential: (Self, Self) -> (Self)) + { return (lhs / rhs, { (dx, dy) in dx / rhs - lhs / (rhs * rhs) * dy }) } } -// Differential operators for `Tracked`. +// Differential operators for `${Self}`. public func gradient( - at x: T, in f: @differentiable (T) -> Tracked + at x: T, in f: @differentiable (T) -> ${Self} ) -> T.TangentVector where R.TangentVector == R { return pullback(at: x, in: f)(1) } public func gradient( - at x: T, _ y: U, in f: @differentiable (T, U) -> Tracked + at x: T, _ y: U, in f: @differentiable (T, U) -> ${Self} ) -> (T.TangentVector, U.TangentVector) where R.TangentVector == R { return pullback(at: x, y, in: f)(1) } public func derivative( - at x: Tracked, in f: @differentiable (Tracked) -> R + at x: ${Self}, in f: @differentiable (${Self}) -> R ) -> R.TangentVector where T.TangentVector == T { return differential(at: x, in: f)(1) } public func derivative( - at x: Tracked, _ y: Tracked, - in f: @differentiable (Tracked, Tracked) -> R + at x: ${Self}, _ y: ${Self}, + in f: @differentiable (${Self}, ${Self}) -> R ) -> R.TangentVector where T.TangentVector == T, U.TangentVector == U { return differential(at: x, y, in: f)(1, 1) } public func valueWithGradient( - at x: T, in f: @differentiable (T) -> Tracked -) -> (value: Tracked, gradient: T.TangentVector) { + at x: T, in f: @differentiable (T) -> ${Self} +) -> (value: ${Self}, gradient: T.TangentVector) { let (y, pullback) = valueWithPullback(at: x, in: f) return (y, pullback(1)) } public func valueWithDerivative( - at x: Tracked, in f: @differentiable (Tracked) -> R + at x: ${Self}, in f: @differentiable (${Self}) -> R ) -> (value: R, derivative: R.TangentVector) { let (y, differential) = valueWithDifferential(at: x, in: f) return (y, differential(1)) } + +% end diff --git a/stdlib/public/Differentiation/FloatingPointDifferentiation.swift.gyb b/stdlib/public/Differentiation/FloatingPointDifferentiation.swift.gyb index 8de2cd5ca2a5b..f2ff2fcbff530 100644 --- a/stdlib/public/Differentiation/FloatingPointDifferentiation.swift.gyb +++ b/stdlib/public/Differentiation/FloatingPointDifferentiation.swift.gyb @@ -205,8 +205,9 @@ extension ${Self} { static func _jvpMultiplyAssign(_ lhs: inout ${Self}, _ rhs: ${Self}) -> ( value: Void, differential: (inout ${Self}, ${Self}) -> Void ) { + let oldLhs = lhs lhs *= rhs - return ((), { $0 *= $1 }) + return ((), { $0 = $0 * rhs + oldLhs * $1 }) } ${Availability(bits)} @@ -251,8 +252,9 @@ extension ${Self} { static func _jvpDivideAssign(_ lhs: inout ${Self}, _ rhs: ${Self}) -> ( value: Void, differential: (inout ${Self}, ${Self}) -> Void ) { + let oldLhs = lhs lhs /= rhs - return ((), { $0 /= $1 }) + return ((), { $0 = ($0 * rhs - oldLhs * $1) / (rhs * rhs) }) } } diff --git a/stdlib/public/Platform/ucrt.modulemap b/stdlib/public/Platform/ucrt.modulemap index 03fe87bf74451..2d88621038f4a 100644 --- a/stdlib/public/Platform/ucrt.modulemap +++ b/stdlib/public/Platform/ucrt.modulemap @@ -95,6 +95,7 @@ module ucrt [system] { module stat { header "sys/stat.h" + header "direct.h" export * } diff --git a/stdlib/public/Reflection/TypeLowering.cpp b/stdlib/public/Reflection/TypeLowering.cpp index d9d437f234ff0..0c15c3da24e3e 100644 --- a/stdlib/public/Reflection/TypeLowering.cpp +++ b/stdlib/public/Reflection/TypeLowering.cpp @@ -317,13 +317,13 @@ class UnsupportedEnumTypeInfo: public EnumTypeInfo { bool readExtraInhabitantIndex(remote::MemoryReader &reader, remote::RemoteAddress address, - int *index) const { + int *index) const override { return false; } bool projectEnumValue(remote::MemoryReader &reader, remote::RemoteAddress address, - int *CaseIndex) const { + int *CaseIndex) const override { return false; } }; @@ -337,13 +337,13 @@ class EmptyEnumTypeInfo: public EnumTypeInfo { bool readExtraInhabitantIndex(remote::MemoryReader &reader, remote::RemoteAddress address, - int *index) const { + int *index) const override { return false; } bool projectEnumValue(remote::MemoryReader &reader, remote::RemoteAddress address, - int *CaseIndex) const { + int *CaseIndex) const override { return false; } }; @@ -361,14 +361,14 @@ class TrivialEnumTypeInfo: public EnumTypeInfo { bool readExtraInhabitantIndex(remote::MemoryReader &reader, remote::RemoteAddress address, - int *index) const { + int *index) const override { *index = -1; return true; } bool projectEnumValue(remote::MemoryReader &reader, remote::RemoteAddress address, - int *CaseIndex) const { + int *CaseIndex) const override { *CaseIndex = 0; return true; } @@ -389,7 +389,7 @@ class NoPayloadEnumTypeInfo: public EnumTypeInfo { bool readExtraInhabitantIndex(remote::MemoryReader &reader, remote::RemoteAddress address, - int *index) const { + int *index) const override { uint32_t tag = 0; if (!reader.readInteger(address, getSize(), &tag)) { return false; @@ -404,7 +404,7 @@ class NoPayloadEnumTypeInfo: public EnumTypeInfo { bool projectEnumValue(remote::MemoryReader &reader, remote::RemoteAddress address, - int *CaseIndex) const { + int *CaseIndex) const override { uint32_t tag = 0; if (!reader.readInteger(address, getSize(), &tag)) { return false; @@ -433,7 +433,7 @@ class SinglePayloadEnumTypeInfo: public EnumTypeInfo { bool readExtraInhabitantIndex(remote::MemoryReader &reader, remote::RemoteAddress address, - int *extraInhabitantIndex) const { + int *extraInhabitantIndex) const override { FieldInfo PayloadCase = getCases()[0]; if (getSize() < PayloadCase.TI.getSize()) { // Single payload enums that use a separate tag don't export any XIs @@ -464,7 +464,7 @@ class SinglePayloadEnumTypeInfo: public EnumTypeInfo { bool projectEnumValue(remote::MemoryReader &reader, remote::RemoteAddress address, - int *CaseIndex) const { + int *CaseIndex) const override { auto PayloadCase = getCases()[0]; auto PayloadSize = PayloadCase.TI.getSize(); auto DiscriminatorAddress = address + PayloadSize; @@ -550,7 +550,7 @@ class SimpleMultiPayloadEnumTypeInfo: public EnumTypeInfo { bool readExtraInhabitantIndex(remote::MemoryReader &reader, remote::RemoteAddress address, - int *extraInhabitantIndex) const { + int *extraInhabitantIndex) const override { unsigned long PayloadSize = getPayloadSize(); unsigned PayloadCount = getNumPayloadCases(); unsigned TagSize = getSize() - PayloadSize; @@ -573,7 +573,7 @@ class SimpleMultiPayloadEnumTypeInfo: public EnumTypeInfo { bool projectEnumValue(remote::MemoryReader &reader, remote::RemoteAddress address, - int *CaseIndex) const { + int *CaseIndex) const override { unsigned long PayloadSize = getPayloadSize(); unsigned PayloadCount = getNumPayloadCases(); unsigned NumCases = getNumCases(); @@ -802,7 +802,7 @@ class MultiPayloadEnumTypeInfo: public EnumTypeInfo { bool readExtraInhabitantIndex(remote::MemoryReader &reader, remote::RemoteAddress address, - int *extraInhabitantIndex) const { + int *extraInhabitantIndex) const override { unsigned long payloadSize = getPayloadSize(); // Multi payload enums that use spare bits export unused tag values as XIs. @@ -879,7 +879,7 @@ class MultiPayloadEnumTypeInfo: public EnumTypeInfo { bool projectEnumValue(remote::MemoryReader &reader, remote::RemoteAddress address, - int *CaseIndex) const { + int *CaseIndex) const override { unsigned long payloadSize = getPayloadSize(); unsigned NumPayloadCases = getNumPayloadCases(); diff --git a/stdlib/public/Reflection/TypeRefBuilder.cpp b/stdlib/public/Reflection/TypeRefBuilder.cpp index 772afeb1e98f2..d811f53d89036 100644 --- a/stdlib/public/Reflection/TypeRefBuilder.cpp +++ b/stdlib/public/Reflection/TypeRefBuilder.cpp @@ -135,7 +135,8 @@ lookupTypeWitness(const std::string &MangledTypeName, auto SubstitutedTypeName = readTypeRef(AssocTy, AssocTy->SubstitutedTypeName); auto Demangled = demangleTypeRef(SubstitutedTypeName); - auto *TypeWitness = swift::Demangle::decodeMangledType(*this, Demangled); + auto *TypeWitness = + swift::Demangle::decodeMangledType(*this, Demangled).getType(); AssociatedTypeCache.insert(std::make_pair(key, TypeWitness)); return TypeWitness; @@ -155,7 +156,8 @@ lookupSuperclass(const TypeRef *TR) { return nullptr; auto Demangled = demangleTypeRef(readTypeRef(FD, FD->Superclass)); - auto Unsubstituted = swift::Demangle::decodeMangledType(*this, Demangled); + auto Unsubstituted = + swift::Demangle::decodeMangledType(*this, Demangled).getType(); if (!Unsubstituted) return nullptr; @@ -226,7 +228,8 @@ bool TypeRefBuilder::getFieldTypeRefs( } auto Demangled = demangleTypeRef(readTypeRef(Field,Field->MangledTypeName)); - auto Unsubstituted = swift::Demangle::decodeMangledType(*this, Demangled); + auto Unsubstituted = + swift::Demangle::decodeMangledType(*this, Demangled).getType(); if (!Unsubstituted) return false; @@ -304,7 +307,7 @@ TypeRefBuilder::getClosureContextInfo(RemoteRef CD) { if (CR->hasMangledTypeName()) { auto MangledName = readTypeRef(CR, CR->MangledTypeName); auto DemangleTree = demangleTypeRef(MangledName); - TR = swift::Demangle::decodeMangledType(*this, DemangleTree); + TR = swift::Demangle::decodeMangledType(*this, DemangleTree).getType(); } Info.CaptureTypes.push_back(TR); } @@ -316,7 +319,7 @@ TypeRefBuilder::getClosureContextInfo(RemoteRef CD) { if (MSR->hasMangledTypeName()) { auto MangledName = readTypeRef(MSR, MSR->MangledTypeName); auto DemangleTree = demangleTypeRef(MangledName); - TR = swift::Demangle::decodeMangledType(*this, DemangleTree); + TR = swift::Demangle::decodeMangledType(*this, DemangleTree).getType(); } const MetadataSource *MS = nullptr; @@ -344,12 +347,17 @@ TypeRefBuilder::dumpTypeRef(RemoteRef MangledName, auto DemangleTree = demangleTypeRef(MangledName); auto TypeName = nodeToString(DemangleTree); fprintf(file, "%s\n", TypeName.c_str()); - auto TR = swift::Demangle::decodeMangledType(*this, DemangleTree); - if (!TR) { + auto Result = swift::Demangle::decodeMangledType(*this, DemangleTree); + if (Result.isError()) { + auto *Error = Result.getError(); + char *ErrorStr = Error->copyErrorString(); auto str = getTypeRefString(MangledName); - fprintf(file, "!!! Invalid typeref: %s\n", std::string(str.begin(), str.end()).c_str()); + fprintf(file, "!!! Invalid typeref: %s - %s\n", + std::string(str.begin(), str.end()).c_str(), ErrorStr); + Error->freeErrorString(ErrorStr); return; } + auto TR = Result.getType(); TR->dump(file); fprintf(file, "\n"); } diff --git a/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp b/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp index 114cf058512d0..b10f8981149be 100644 --- a/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp +++ b/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp @@ -298,7 +298,7 @@ swift_reflection_typeRefForMangledTypeName(SwiftReflectionContextRef ContextRef, const char *MangledTypeName, uint64_t Length) { auto Context = ContextRef->nativeContext; - auto TR = Context->readTypeFromMangledName(MangledTypeName, Length); + auto TR = Context->readTypeFromMangledName(MangledTypeName, Length).getType(); return reinterpret_cast(TR); } @@ -447,6 +447,12 @@ static swift_childinfo_t convertChild(const TypeInfo *TI, unsigned Index) { FieldInfo = &(RecordTI->getFields()[Index]); } else { assert(false && "convertChild(TI): TI must be record or enum typeinfo"); + return { + "unknown TypeInfo kind", + 0, + SWIFT_UNKNOWN, + 0, + }; } return { diff --git a/stdlib/public/SwiftShims/LibcOverlayShims.h b/stdlib/public/SwiftShims/LibcOverlayShims.h index b4c2ba1d0a002..6395656355330 100644 --- a/stdlib/public/SwiftShims/LibcOverlayShims.h +++ b/stdlib/public/SwiftShims/LibcOverlayShims.h @@ -52,7 +52,7 @@ static inline int _swift_stdlib_fcntlPtr(int fd, int cmd, void* ptr) { #endif // Environment -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) static inline char * _Nullable * _Null_unspecified _swift_stdlib_getEnviron() { extern char **environ; return environ; diff --git a/stdlib/public/core/Array.swift b/stdlib/public/core/Array.swift index fd72700ca95b8..42fcd9d672e44 100644 --- a/stdlib/public/core/Array.swift +++ b/stdlib/public/core/Array.swift @@ -264,7 +264,7 @@ /// let colors = ["periwinkle", "rose", "moss"] /// let moreColors: [String?] = ["ochre", "pine"] /// -/// let url = NSURL(fileURLWithPath: "names.plist") +/// let url = URL(fileURLWithPath: "names.plist") /// (colors as NSArray).write(to: url, atomically: true) /// // true /// diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt index 5cb634ad1d360..ad74e0e699039 100644 --- a/stdlib/public/core/CMakeLists.txt +++ b/stdlib/public/core/CMakeLists.txt @@ -211,6 +211,7 @@ set(SWIFTLIB_SOURCES CollectionOfOne.swift DiscontiguousSlice.swift Diffing.swift + FloatingPointRandom.swift Mirror.swift PlaygroundDisplay.swift CommandLine.swift @@ -287,8 +288,10 @@ if(SWIFT_STDLIB_SIL_DEBUGGING) list(APPEND swift_stdlib_compile_flags "-Xfrontend" "-gsil") endif() -list(APPEND swift_stdlib_compile_flags "-Xllvm" "-sil-inline-generics") -list(APPEND swift_stdlib_compile_flags "-Xllvm" "-sil-partial-specialization") +if(NOT "${CMAKE_BUILD_TYPE}" STREQUAL "MinSizeRel") + list(APPEND swift_stdlib_compile_flags "-Xllvm" "-sil-inline-generics") + list(APPEND swift_stdlib_compile_flags "-Xllvm" "-sil-partial-specialization") +endif() if(SWIFT_STDLIB_ENABLE_STDLIBCORE_EXCLUSIVITY_CHECKING) list(APPEND swift_stdlib_compile_flags "-enforce-exclusivity=checked") endif() diff --git a/stdlib/public/core/DebuggerSupport.swift b/stdlib/public/core/DebuggerSupport.swift index 0e7095aebd783..82cfedd5eb4fb 100644 --- a/stdlib/public/core/DebuggerSupport.swift +++ b/stdlib/public/core/DebuggerSupport.swift @@ -152,7 +152,14 @@ public enum _DebuggerSupport { // yes, a type can lie and say it's a class when it's not since we only // check the displayStyle - but then the type would have a custom Mirror // anyway, so there's that... - let willExpand = mirror.displayStyle != .`class` || value is CustomReflectable? + let isNonClass = mirror.displayStyle != .`class` + let isCustomReflectable: Bool + if let value = value { + isCustomReflectable = value is CustomReflectable + } else { + isCustomReflectable = true + } + let willExpand = isNonClass || isCustomReflectable let count = mirror._children.count let bullet = isRoot && (count == 0 || !willExpand) ? "" diff --git a/stdlib/public/core/FloatingPoint.swift b/stdlib/public/core/FloatingPoint.swift index a6339654ff6d9..fa7ce591f6530 100644 --- a/stdlib/public/core/FloatingPoint.swift +++ b/stdlib/public/core/FloatingPoint.swift @@ -2013,205 +2013,4 @@ extension BinaryFloatingPoint where Self.RawSignificand: FixedWidthInteger { guard exact else { return nil } self = value_ } - - /// Returns a random value within the specified range, using the given - /// generator as a source for randomness. - /// - /// Use this method to generate a floating-point value within a specific - /// range when you are using a custom random number generator. This example - /// creates three new values in the range `10.0 ..< 20.0`. - /// - /// for _ in 1...3 { - /// print(Double.random(in: 10.0 ..< 20.0, using: &myGenerator)) - /// } - /// // Prints "18.1900709259179" - /// // Prints "14.2286325689993" - /// // Prints "13.1485686260762" - /// - /// The `random(in:using:)` static method chooses a random value from a - /// continuous uniform distribution in `range`, and then converts that value - /// to the nearest representable value in this type. Depending on the size - /// and span of `range`, some concrete values may be represented more - /// frequently than others. - /// - /// - Note: The algorithm used to create random values may change in a future - /// version of Swift. If you're passing a generator that results in the - /// same sequence of floating-point values each time you run your program, - /// that sequence may change when your program is compiled using a - /// different version of Swift. - /// - /// - Parameters: - /// - range: The range in which to create a random value. - /// `range` must be finite and non-empty. - /// - generator: The random number generator to use when creating the - /// new random value. - /// - Returns: A random value within the bounds of `range`. - @inlinable - public static func random( - in range: Range, - using generator: inout T - ) -> Self { - _precondition( - !range.isEmpty, - "Can't get random value with an empty range" - ) - let delta = range.upperBound - range.lowerBound - // TODO: this still isn't quite right, because the computation of delta - // can overflow (e.g. if .upperBound = .maximumFiniteMagnitude and - // .lowerBound = -.upperBound); this should be re-written with an - // algorithm that handles that case correctly, but this precondition - // is an acceptable short-term fix. - _precondition( - delta.isFinite, - "There is no uniform distribution on an infinite range" - ) - let rand: Self.RawSignificand - if Self.RawSignificand.bitWidth == Self.significandBitCount + 1 { - rand = generator.next() - } else { - let significandCount = Self.significandBitCount + 1 - let maxSignificand: Self.RawSignificand = 1 << significandCount - // Rather than use .next(upperBound:), which has to work with arbitrary - // upper bounds, and therefore does extra work to avoid bias, we can take - // a shortcut because we know that maxSignificand is a power of two. - rand = generator.next() & (maxSignificand - 1) - } - let unitRandom = Self.init(rand) * (Self.ulpOfOne / 2) - let randFloat = delta * unitRandom + range.lowerBound - if randFloat == range.upperBound { - return Self.random(in: range, using: &generator) - } - return randFloat - } - - /// Returns a random value within the specified range. - /// - /// Use this method to generate a floating-point value within a specific - /// range. This example creates three new values in the range - /// `10.0 ..< 20.0`. - /// - /// for _ in 1...3 { - /// print(Double.random(in: 10.0 ..< 20.0)) - /// } - /// // Prints "18.1900709259179" - /// // Prints "14.2286325689993" - /// // Prints "13.1485686260762" - /// - /// The `random()` static method chooses a random value from a continuous - /// uniform distribution in `range`, and then converts that value to the - /// nearest representable value in this type. Depending on the size and span - /// of `range`, some concrete values may be represented more frequently than - /// others. - /// - /// This method is equivalent to calling `random(in:using:)`, passing in the - /// system's default random generator. - /// - /// - Parameter range: The range in which to create a random value. - /// `range` must be finite and non-empty. - /// - Returns: A random value within the bounds of `range`. - @inlinable - public static func random(in range: Range) -> Self { - var g = SystemRandomNumberGenerator() - return Self.random(in: range, using: &g) - } - - /// Returns a random value within the specified range, using the given - /// generator as a source for randomness. - /// - /// Use this method to generate a floating-point value within a specific - /// range when you are using a custom random number generator. This example - /// creates three new values in the range `10.0 ... 20.0`. - /// - /// for _ in 1...3 { - /// print(Double.random(in: 10.0 ... 20.0, using: &myGenerator)) - /// } - /// // Prints "18.1900709259179" - /// // Prints "14.2286325689993" - /// // Prints "13.1485686260762" - /// - /// The `random(in:using:)` static method chooses a random value from a - /// continuous uniform distribution in `range`, and then converts that value - /// to the nearest representable value in this type. Depending on the size - /// and span of `range`, some concrete values may be represented more - /// frequently than others. - /// - /// - Note: The algorithm used to create random values may change in a future - /// version of Swift. If you're passing a generator that results in the - /// same sequence of floating-point values each time you run your program, - /// that sequence may change when your program is compiled using a - /// different version of Swift. - /// - /// - Parameters: - /// - range: The range in which to create a random value. Must be finite. - /// - generator: The random number generator to use when creating the - /// new random value. - /// - Returns: A random value within the bounds of `range`. - @inlinable - public static func random( - in range: ClosedRange, - using generator: inout T - ) -> Self { - _precondition( - !range.isEmpty, - "Can't get random value with an empty range" - ) - let delta = range.upperBound - range.lowerBound - // TODO: this still isn't quite right, because the computation of delta - // can overflow (e.g. if .upperBound = .maximumFiniteMagnitude and - // .lowerBound = -.upperBound); this should be re-written with an - // algorithm that handles that case correctly, but this precondition - // is an acceptable short-term fix. - _precondition( - delta.isFinite, - "There is no uniform distribution on an infinite range" - ) - let rand: Self.RawSignificand - if Self.RawSignificand.bitWidth == Self.significandBitCount + 1 { - rand = generator.next() - let tmp: UInt8 = generator.next() & 1 - if rand == Self.RawSignificand.max && tmp == 1 { - return range.upperBound - } - } else { - let significandCount = Self.significandBitCount + 1 - let maxSignificand: Self.RawSignificand = 1 << significandCount - rand = generator.next(upperBound: maxSignificand + 1) - if rand == maxSignificand { - return range.upperBound - } - } - let unitRandom = Self.init(rand) * (Self.ulpOfOne / 2) - let randFloat = delta * unitRandom + range.lowerBound - return randFloat - } - - /// Returns a random value within the specified range. - /// - /// Use this method to generate a floating-point value within a specific - /// range. This example creates three new values in the range - /// `10.0 ... 20.0`. - /// - /// for _ in 1...3 { - /// print(Double.random(in: 10.0 ... 20.0)) - /// } - /// // Prints "18.1900709259179" - /// // Prints "14.2286325689993" - /// // Prints "13.1485686260762" - /// - /// The `random()` static method chooses a random value from a continuous - /// uniform distribution in `range`, and then converts that value to the - /// nearest representable value in this type. Depending on the size and span - /// of `range`, some concrete values may be represented more frequently than - /// others. - /// - /// This method is equivalent to calling `random(in:using:)`, passing in the - /// system's default random generator. - /// - /// - Parameter range: The range in which to create a random value. Must be finite. - /// - Returns: A random value within the bounds of `range`. - @inlinable - public static func random(in range: ClosedRange) -> Self { - var g = SystemRandomNumberGenerator() - return Self.random(in: range, using: &g) - } } diff --git a/stdlib/public/core/FloatingPointRandom.swift b/stdlib/public/core/FloatingPointRandom.swift new file mode 100644 index 0000000000000..8aeb16eb36030 --- /dev/null +++ b/stdlib/public/core/FloatingPointRandom.swift @@ -0,0 +1,215 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +extension BinaryFloatingPoint where Self.RawSignificand: FixedWidthInteger { + + /// Returns a random value within the specified range, using the given + /// generator as a source for randomness. + /// + /// Use this method to generate a floating-point value within a specific + /// range when you are using a custom random number generator. This example + /// creates three new values in the range `10.0 ..< 20.0`. + /// + /// for _ in 1...3 { + /// print(Double.random(in: 10.0 ..< 20.0, using: &myGenerator)) + /// } + /// // Prints "18.1900709259179" + /// // Prints "14.2286325689993" + /// // Prints "13.1485686260762" + /// + /// The `random(in:using:)` static method chooses a random value from a + /// continuous uniform distribution in `range`, and then converts that value + /// to the nearest representable value in this type. Depending on the size + /// and span of `range`, some concrete values may be represented more + /// frequently than others. + /// + /// - Note: The algorithm used to create random values may change in a future + /// version of Swift. If you're passing a generator that results in the + /// same sequence of floating-point values each time you run your program, + /// that sequence may change when your program is compiled using a + /// different version of Swift. + /// + /// - Parameters: + /// - range: The range in which to create a random value. + /// `range` must be finite and non-empty. + /// - generator: The random number generator to use when creating the + /// new random value. + /// - Returns: A random value within the bounds of `range`. + @inlinable + public static func random( + in range: Range, + using generator: inout T + ) -> Self { + _precondition( + !range.isEmpty, + "Can't get random value with an empty range" + ) + let delta = range.upperBound - range.lowerBound + // TODO: this still isn't quite right, because the computation of delta + // can overflow (e.g. if .upperBound = .maximumFiniteMagnitude and + // .lowerBound = -.upperBound); this should be re-written with an + // algorithm that handles that case correctly, but this precondition + // is an acceptable short-term fix. + _precondition( + delta.isFinite, + "There is no uniform distribution on an infinite range" + ) + let rand: Self.RawSignificand + if Self.RawSignificand.bitWidth == Self.significandBitCount + 1 { + rand = generator.next() + } else { + let significandCount = Self.significandBitCount + 1 + let maxSignificand: Self.RawSignificand = 1 << significandCount + // Rather than use .next(upperBound:), which has to work with arbitrary + // upper bounds, and therefore does extra work to avoid bias, we can take + // a shortcut because we know that maxSignificand is a power of two. + rand = generator.next() & (maxSignificand - 1) + } + let unitRandom = Self.init(rand) * (Self.ulpOfOne / 2) + let randFloat = delta * unitRandom + range.lowerBound + if randFloat == range.upperBound { + return Self.random(in: range, using: &generator) + } + return randFloat + } + + /// Returns a random value within the specified range. + /// + /// Use this method to generate a floating-point value within a specific + /// range. This example creates three new values in the range + /// `10.0 ..< 20.0`. + /// + /// for _ in 1...3 { + /// print(Double.random(in: 10.0 ..< 20.0)) + /// } + /// // Prints "18.1900709259179" + /// // Prints "14.2286325689993" + /// // Prints "13.1485686260762" + /// + /// The `random()` static method chooses a random value from a continuous + /// uniform distribution in `range`, and then converts that value to the + /// nearest representable value in this type. Depending on the size and span + /// of `range`, some concrete values may be represented more frequently than + /// others. + /// + /// This method is equivalent to calling `random(in:using:)`, passing in the + /// system's default random generator. + /// + /// - Parameter range: The range in which to create a random value. + /// `range` must be finite and non-empty. + /// - Returns: A random value within the bounds of `range`. + @inlinable + public static func random(in range: Range) -> Self { + var g = SystemRandomNumberGenerator() + return Self.random(in: range, using: &g) + } + + /// Returns a random value within the specified range, using the given + /// generator as a source for randomness. + /// + /// Use this method to generate a floating-point value within a specific + /// range when you are using a custom random number generator. This example + /// creates three new values in the range `10.0 ... 20.0`. + /// + /// for _ in 1...3 { + /// print(Double.random(in: 10.0 ... 20.0, using: &myGenerator)) + /// } + /// // Prints "18.1900709259179" + /// // Prints "14.2286325689993" + /// // Prints "13.1485686260762" + /// + /// The `random(in:using:)` static method chooses a random value from a + /// continuous uniform distribution in `range`, and then converts that value + /// to the nearest representable value in this type. Depending on the size + /// and span of `range`, some concrete values may be represented more + /// frequently than others. + /// + /// - Note: The algorithm used to create random values may change in a future + /// version of Swift. If you're passing a generator that results in the + /// same sequence of floating-point values each time you run your program, + /// that sequence may change when your program is compiled using a + /// different version of Swift. + /// + /// - Parameters: + /// - range: The range in which to create a random value. Must be finite. + /// - generator: The random number generator to use when creating the + /// new random value. + /// - Returns: A random value within the bounds of `range`. + @inlinable + public static func random( + in range: ClosedRange, + using generator: inout T + ) -> Self { + _precondition( + !range.isEmpty, + "Can't get random value with an empty range" + ) + let delta = range.upperBound - range.lowerBound + // TODO: this still isn't quite right, because the computation of delta + // can overflow (e.g. if .upperBound = .maximumFiniteMagnitude and + // .lowerBound = -.upperBound); this should be re-written with an + // algorithm that handles that case correctly, but this precondition + // is an acceptable short-term fix. + _precondition( + delta.isFinite, + "There is no uniform distribution on an infinite range" + ) + let rand: Self.RawSignificand + if Self.RawSignificand.bitWidth == Self.significandBitCount + 1 { + rand = generator.next() + let tmp: UInt8 = generator.next() & 1 + if rand == Self.RawSignificand.max && tmp == 1 { + return range.upperBound + } + } else { + let significandCount = Self.significandBitCount + 1 + let maxSignificand: Self.RawSignificand = 1 << significandCount + rand = generator.next(upperBound: maxSignificand + 1) + if rand == maxSignificand { + return range.upperBound + } + } + let unitRandom = Self.init(rand) * (Self.ulpOfOne / 2) + let randFloat = delta * unitRandom + range.lowerBound + return randFloat + } + + /// Returns a random value within the specified range. + /// + /// Use this method to generate a floating-point value within a specific + /// range. This example creates three new values in the range + /// `10.0 ... 20.0`. + /// + /// for _ in 1...3 { + /// print(Double.random(in: 10.0 ... 20.0)) + /// } + /// // Prints "18.1900709259179" + /// // Prints "14.2286325689993" + /// // Prints "13.1485686260762" + /// + /// The `random()` static method chooses a random value from a continuous + /// uniform distribution in `range`, and then converts that value to the + /// nearest representable value in this type. Depending on the size and span + /// of `range`, some concrete values may be represented more frequently than + /// others. + /// + /// This method is equivalent to calling `random(in:using:)`, passing in the + /// system's default random generator. + /// + /// - Parameter range: The range in which to create a random value. Must be finite. + /// - Returns: A random value within the bounds of `range`. + @inlinable + public static func random(in range: ClosedRange) -> Self { + var g = SystemRandomNumberGenerator() + return Self.random(in: range, using: &g) + } +} diff --git a/stdlib/public/core/GroupInfo.json b/stdlib/public/core/GroupInfo.json index 289703802610a..8b4fbcaae345f 100644 --- a/stdlib/public/core/GroupInfo.json +++ b/stdlib/public/core/GroupInfo.json @@ -169,7 +169,8 @@ "Floating": [ "FloatingPoint.swift", "FloatingPointParsing.swift", - "FloatingPointTypes.swift"], + "FloatingPointTypes.swift", + "FloatingPointRandom.swift"], "Vector": [ "SIMDVector.swift", "SIMDVectorTypes.swift"]} diff --git a/stdlib/public/core/UnicodeHelpers.swift b/stdlib/public/core/UnicodeHelpers.swift index 64e7ea189fd9f..1e538f9349d4b 100644 --- a/stdlib/public/core/UnicodeHelpers.swift +++ b/stdlib/public/core/UnicodeHelpers.swift @@ -397,12 +397,13 @@ extension _StringGuts { } // TODO(String performance): Stack buffer if small enough - var cus = Array(repeating: 0, count: count) - cus.withUnsafeMutableBufferPointer { + let cus = Array(unsafeUninitializedCapacity: count) { + buffer, initializedCapacity in _cocoaStringCopyCharacters( from: self._object.cocoaObject, range: start..getKind() == MetadataKind::Class + && targetType->getKind() == MetadataKind::Class) { + auto srcClassType = cast(srcType); + auto srcDescr = srcClassType->getDescription(); + if (srcDescr == &NOMINAL_TYPE_DESCR_SYM(s12__SwiftValueC)) { + auto srcValue = reinterpret_cast(&object); + void *result; + auto destLocation = reinterpret_cast(&result); + if (swift_unboxFromSwiftValueWithType(srcValue, destLocation, targetType)) { + swift_unknownObjectRelease(const_cast(object)); + return result; + } + } + } +#endif + return nullptr; } @@ -3262,3 +3289,30 @@ HeapObject *_swift_bridgeToObjectiveCUsingProtocolIfPossible( #define OVERRIDE_CASTING COMPATIBILITY_OVERRIDE #include "CompatibilityOverride.def" +// XXX TODO XXX REMOVE XXX TRANSITION SHIM XXX +// XXX TODO XXX REMOVE XXX TRANSITION SHIM XXX +// XXX TODO XXX REMOVE XXX TRANSITION SHIM XXX + +// A way for the new implementation to call the old one, so we +// can support switching between the two until the new one is +// fully settled. + +// XXX TODO XXX Once the new implementation is stable, remove the following, +// swift_dynamicCastImpl above, and all the other code above that only exists to +// support that. (Don't forget _dynamicCastToExistential!!) This file should +// be only ~1400 lines when you're done. + +extern "C" { + bool swift_dynamicCast_OLD(OpaqueValue *destLocation, + OpaqueValue *srcValue, + const Metadata *srcType, + const Metadata *destType, + DynamicCastFlags flags) + { + return swift_dynamicCastImpl(destLocation, srcValue, srcType, destType, flags); + } +} + +// XXX TODO XXX REMOVE XXX TRANSITION SHIM XXX +// XXX TODO XXX REMOVE XXX TRANSITION SHIM XXX +// XXX TODO XXX REMOVE XXX TRANSITION SHIM XXX diff --git a/stdlib/public/runtime/CompatibilityOverride.cpp b/stdlib/public/runtime/CompatibilityOverride.cpp index 8c5b3f747e4fd..8ebc72ee5e702 100644 --- a/stdlib/public/runtime/CompatibilityOverride.cpp +++ b/stdlib/public/runtime/CompatibilityOverride.cpp @@ -14,6 +14,8 @@ // //===----------------------------------------------------------------------===// +#ifndef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES + #include "CompatibilityOverride.h" #include "ImageInspection.h" @@ -73,3 +75,5 @@ static OverrideSection *getOverrideSectionPtr() { return Section->name; \ } #include "CompatibilityOverride.def" + +#endif // #ifndef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES diff --git a/stdlib/public/runtime/CompatibilityOverride.def b/stdlib/public/runtime/CompatibilityOverride.def index 06ee84685dc35..1489ee07e1eeb 100644 --- a/stdlib/public/runtime/CompatibilityOverride.def +++ b/stdlib/public/runtime/CompatibilityOverride.def @@ -40,6 +40,7 @@ #ifdef OVERRIDE # define OVERRIDE_METADATALOOKUP OVERRIDE # define OVERRIDE_CASTING OVERRIDE +# define OVERRIDE_DYNAMICCASTING OVERRIDE # define OVERRIDE_OBJC OVERRIDE # define OVERRIDE_FOREIGN OVERRIDE # define OVERRIDE_PROTOCOLCONFORMANCE OVERRIDE @@ -52,6 +53,9 @@ # ifndef OVERRIDE_CASTING # define OVERRIDE_CASTING(...) # endif +# ifndef OVERRIDE_DYNAMICCASTING +# define OVERRIDE_DYNAMICCASTING(...) +# endif # ifndef OVERRIDE_OBJC # define OVERRIDE_OBJC(...) # endif @@ -69,12 +73,12 @@ # endif #endif -OVERRIDE_CASTING(dynamicCast, bool, , , swift::, - (OpaqueValue *dest, OpaqueValue *src, - const Metadata *srcType, - const Metadata *targetType, - DynamicCastFlags flags), - (dest, src, srcType, targetType, flags)) +OVERRIDE_DYNAMICCASTING(dynamicCast, bool, , , swift::, + (OpaqueValue *dest, OpaqueValue *src, + const Metadata *srcType, + const Metadata *targetType, + DynamicCastFlags flags), + (dest, src, srcType, targetType, flags)) OVERRIDE_CASTING(dynamicCastClass, const void *, , , swift::, @@ -134,18 +138,11 @@ OVERRIDE_PROTOCOLCONFORMANCE(conformsToProtocol, const WitnessTable *, , , swift const ProtocolDescriptor *protocol), (type, protocol)) -OVERRIDE_PROTOCOLCONFORMANCE(conformsToSwiftProtocol, - const ProtocolConformanceDescriptor *, , , swift::, - (const Metadata * const type, - const ProtocolDescriptor *protocol, - StringRef moduleName), - (type, protocol, moduleName)) - OVERRIDE_KEYPATH(getKeyPath, const HeapObject *, , , swift::, (const void *pattern, const void *arguments), (pattern, arguments)) -OVERRIDE_METADATALOOKUP(getTypeByMangledNode, TypeInfo, , SWIFT_CC(swift), swift::, +OVERRIDE_METADATALOOKUP(getTypeByMangledNode, TypeLookupErrorOr, , SWIFT_CC(swift), swift::, (MetadataRequest request, Demangler &demangler, Demangle::NodePointer node, @@ -153,7 +150,7 @@ OVERRIDE_METADATALOOKUP(getTypeByMangledNode, TypeInfo, , SWIFT_CC(swift), swift SubstGenericParameterFn substGenericParam, SubstDependentWitnessTableFn substWitnessTable), (request, demangler, node, arguments, substGenericParam, substWitnessTable)) -OVERRIDE_METADATALOOKUP(getTypeByMangledName, TypeInfo, , SWIFT_CC(swift), swift::, +OVERRIDE_METADATALOOKUP(getTypeByMangledName, TypeLookupErrorOr, , SWIFT_CC(swift), swift::, (MetadataRequest request, StringRef typeName, const void * const *arguments, @@ -219,6 +216,7 @@ OVERRIDE_FOREIGN(dynamicCastForeignClassUnconditional, const void *, , , swift:: #undef OVERRIDE #undef OVERRIDE_METADATALOOKUP #undef OVERRIDE_CASTING +#undef OVERRIDE_DYNAMICCASTING #undef OVERRIDE_OBJC #undef OVERRIDE_FOREIGN #undef OVERRIDE_PROTOCOLCONFORMANCE diff --git a/stdlib/public/runtime/CompatibilityOverride.h b/stdlib/public/runtime/CompatibilityOverride.h index ad79a27273d51..25a3b1e3fc0ec 100644 --- a/stdlib/public/runtime/CompatibilityOverride.h +++ b/stdlib/public/runtime/CompatibilityOverride.h @@ -24,6 +24,15 @@ namespace swift { +#ifdef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES + +#define COMPATIBILITY_OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ + attrs ccAttrs ret namespace swift_ ## name typedArgs { \ + return swift_ ## name ## Impl namedArgs; \ + } + +#else // #ifdef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES + #define COMPATIBILITY_UNPAREN(...) __VA_ARGS__ #define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ @@ -70,6 +79,8 @@ namespace swift { } #endif +#endif // #else SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES + } /* end namespace swift */ #endif /* COMPATIBILITY_OVERRIDE_H */ diff --git a/stdlib/public/runtime/DynamicCast.cpp b/stdlib/public/runtime/DynamicCast.cpp new file mode 100644 index 0000000000000..fa628e296fb2a --- /dev/null +++ b/stdlib/public/runtime/DynamicCast.cpp @@ -0,0 +1,2197 @@ +//===--- DynamicCast.cpp - Swift Language Dynamic Casting Support ---------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// Implementations of the dynamic cast runtime functions. +// +//===----------------------------------------------------------------------===// + +#include "CompatibilityOverride.h" +#include "ErrorObject.h" +#include "Private.h" +#include "SwiftHashableSupport.h" +#include "swift/ABI/MetadataValues.h" +#include "swift/Basic/Lazy.h" +#include "swift/Runtime/Casting.h" +#include "swift/Runtime/Config.h" +#include "swift/Runtime/ExistentialContainer.h" +#include "swift/Runtime/HeapObject.h" +#if SWIFT_OBJC_INTEROP +#include "swift/Runtime/ObjCBridge.h" +#include "SwiftObject.h" +#include "SwiftValue.h" +#endif + +using namespace swift; +using namespace hashable_support; + +// +// The top-level driver code directly handles the most general cases +// (identity casts, _ObjectiveCBridgeable, _SwiftValue boxing) and +// recursively unwraps source and/or destination as appropriate. +// It calls "tryCastToXyz" functions to perform tailored operations +// for a particular destination type. +// +// For each kind of destination, there is a "tryCastToXyz" that +// accepts a source value and attempts to fit it into a destination +// storage location. This function should assume that: +// * The source and destination types are _not_ identical. +// * The destination is of the expected type. +// * The source is already fully unwrapped. If the source is an +// Existential or Optional that you cannot handle directly, do _not_ +// try to unwrap it. Just return failure and you will get called +// again with the unwrapped source. +// +// Each such function accepts the following arguments: +// * Destination location and type +// * Source value address and type +// * References to the types that will be used to report failure. +// The function can update these with specific failing types +// to improve the reported failure. +// * Bool indicating whether the compiler has asked us to "take" the +// value instead of copying. +// * Bool indicating whether it's okay to do type checks lazily on later +// access (this is permitted only for unconditional casts that will +// abort the program on failure anyway). +// +// The return value is one of the following: +// * Failure. In this case, the tryCastFunction should do nothing; your +// caller will either try another strategy or report the failure and +// do any necessary cleanup. +// * Success via "copy". You successfully copied the source value. +// * Success via "take". If "take" was requested and you can do so cheaply, +// perform the take and return SuccessViaTake. If "take" is not cheap, you +// should copy and return SuccessViaCopy. Top-level code will detect this +// and take care of destroying the source for you. +// +enum class DynamicCastResult { + Failure, /// The cast attempt "failed" (did nothing). + SuccessViaCopy, /// Cast succeeded, source is still valid. + SuccessViaTake, /// Cast succeeded, source is invalid +}; +static bool isSuccess(DynamicCastResult result) { + return result != DynamicCastResult::Failure; +} + +// All of our `tryCastXyz` functions have the following signature. +typedef DynamicCastResult (tryCastFunctionType)( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks +); + +// Forward-declare the main top-level `tryCast()` function +static tryCastFunctionType tryCast; + +/// Nominal type descriptor for Swift.AnyHashable +extern "C" const StructDescriptor STRUCT_TYPE_DESCR_SYM(s11AnyHashable); + +/// Nominal type descriptor for Swift.__SwiftValue +//extern "C" const StructDescriptor STRUCT_TYPE_DESCR_SYM(s12__SwiftValue); + +/// Nominal type descriptor for Swift.Array. +extern "C" const StructDescriptor NOMINAL_TYPE_DESCR_SYM(Sa); + +/// Nominal type descriptor for Swift.Dictionary. +extern "C" const StructDescriptor NOMINAL_TYPE_DESCR_SYM(SD); + +/// Nominal type descriptor for Swift.Set. +extern "C" const StructDescriptor NOMINAL_TYPE_DESCR_SYM(Sh); + +/// Nominal type descriptor for Swift.String. +extern "C" const StructDescriptor NOMINAL_TYPE_DESCR_SYM(SS); + +static HeapObject * getNonNullSrcObject(OpaqueValue *srcValue, + const Metadata *srcType, + const Metadata *destType) { + auto object = *reinterpret_cast(srcValue); + if (LLVM_LIKELY(object != nullptr)) { + return object; + } + + std::string srcTypeName = nameForMetadata(srcType); + std::string destTypeName = nameForMetadata(destType); + swift::fatalError(/* flags = */ 0, + "Found unexpected null pointer value" + " while trying to cast value of type '%s' (%p)" + " to '%s' (%p)\n", + srcTypeName.c_str(), srcType, + destTypeName.c_str(), destType); +} + +/******************************************************************************/ +/******************************* Bridge Helpers *******************************/ +/******************************************************************************/ + +#define _bridgeAnythingToObjectiveC \ + MANGLE_SYM(s27_bridgeAnythingToObjectiveCyyXlxlF) +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API +HeapObject *_bridgeAnythingToObjectiveC( + OpaqueValue *src, const Metadata *srcType); + +#if SWIFT_OBJC_INTEROP +SWIFT_RUNTIME_EXPORT +id swift_dynamicCastMetatypeToObjectConditional(const Metadata *metatype); +#endif + +// protocol _ObjectiveCBridgeable { +struct _ObjectiveCBridgeableWitnessTable : WitnessTable { + static_assert(WitnessTableFirstRequirementOffset == 1, + "Witness table layout changed"); + + // associatedtype _ObjectiveCType : class + void *_ObjectiveCType; + + // func _bridgeToObjectiveC() -> _ObjectiveCType + SWIFT_CC(swift) + HeapObject *(*bridgeToObjectiveC)( + SWIFT_CONTEXT OpaqueValue *self, const Metadata *Self, + const _ObjectiveCBridgeableWitnessTable *witnessTable); + + // class func _forceBridgeFromObjectiveC(x: _ObjectiveCType, + // inout result: Self?) + SWIFT_CC(swift) + void (*forceBridgeFromObjectiveC)( + HeapObject *sourceValue, + OpaqueValue *result, + SWIFT_CONTEXT const Metadata *self, + const Metadata *selfType, + const _ObjectiveCBridgeableWitnessTable *witnessTable); + + // class func _conditionallyBridgeFromObjectiveC(x: _ObjectiveCType, + // inout result: Self?) -> Bool + SWIFT_CC(swift) + bool (*conditionallyBridgeFromObjectiveC)( + HeapObject *sourceValue, + OpaqueValue *result, + SWIFT_CONTEXT const Metadata *self, + const Metadata *selfType, + const _ObjectiveCBridgeableWitnessTable *witnessTable); +}; +// } + +extern "C" const ProtocolDescriptor +PROTOCOL_DESCR_SYM(s21_ObjectiveCBridgeable); + +static const _ObjectiveCBridgeableWitnessTable * +findBridgeWitness(const Metadata *T) { + static const auto bridgeableProtocol + = &PROTOCOL_DESCR_SYM(s21_ObjectiveCBridgeable); + auto w = swift_conformsToProtocol(T, bridgeableProtocol); + return reinterpret_cast(w); +} + +/// Retrieve the bridged Objective-C type for the given type that +/// conforms to \c _ObjectiveCBridgeable. +MetadataResponse +_getBridgedObjectiveCType( + MetadataRequest request, + const Metadata *conformingType, + const _ObjectiveCBridgeableWitnessTable *wtable) +{ + // FIXME: Can we directly reference the descriptor somehow? + const ProtocolConformanceDescriptor *conformance = wtable->getDescription(); + const ProtocolDescriptor *protocol = conformance->getProtocol(); + auto assocTypeRequirement = protocol->getRequirements().begin(); + assert(assocTypeRequirement->Flags.getKind() == + ProtocolRequirementFlags::Kind::AssociatedTypeAccessFunction); + auto mutableWTable = (WitnessTable *)wtable; + return swift_getAssociatedTypeWitness( + request, mutableWTable, conformingType, + protocol->getRequirementBaseDescriptor(), + assocTypeRequirement); +} + +/// Dynamic cast from a class type to a value type that conforms to the +/// _ObjectiveCBridgeable, first by dynamic casting the object to the +/// class to which the value type is bridged, and then bridging +/// from that object to the value type via the witness table. +/// +/// Caveat: Despite the name, this is also used to bridge pure Swift +/// classes to Swift value types even when Obj-C is not being used. + +static DynamicCastResult +_tryCastFromClassToObjCBridgeable( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, void *srcObject, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks, + const _ObjectiveCBridgeableWitnessTable *destBridgeWitness, + const Metadata *targetBridgeClass) +{ + + // 2. Allocate a T? to receive the bridge result. + + // The extra byte is for the tag. + auto targetSize = destType->getValueWitnesses()->getSize() + 1; + auto targetAlignMask = destType->getValueWitnesses()->getAlignmentMask(); + + // Object that frees a buffer when it goes out of scope. + struct FreeBuffer { + void *Buffer = nullptr; + size_t size, alignMask; + FreeBuffer(size_t size, size_t alignMask) : + size(size), alignMask(alignMask) {} + + ~FreeBuffer() { + if (Buffer) + swift_slowDealloc(Buffer, size, alignMask); + } + } freeBuffer{targetSize, targetAlignMask}; + + // The extra byte is for the tag on the T? + const std::size_t inlineValueSize = 3 * sizeof(void*); + alignas(std::max_align_t) char inlineBuffer[inlineValueSize + 1]; + void *optDestBuffer; + if (destType->getValueWitnesses()->getStride() <= inlineValueSize) { + // Use the inline buffer. + optDestBuffer = inlineBuffer; + } else { + // Allocate a buffer. + optDestBuffer = swift_slowAlloc(targetSize, targetAlignMask); + freeBuffer.Buffer = optDestBuffer; + } + + // Initialize the buffer as an empty optional. + destType->vw_storeEnumTagSinglePayload((OpaqueValue *)optDestBuffer, + 1, 1); + + // 3. Bridge into the T? (Effectively a copy operation.) + bool success; + if (mayDeferChecks) { + destBridgeWitness->forceBridgeFromObjectiveC( + (HeapObject *)srcObject, (OpaqueValue *)optDestBuffer, + destType, destType, destBridgeWitness); + success = true; + } else { + success = destBridgeWitness->conditionallyBridgeFromObjectiveC( + (HeapObject *)srcObject, (OpaqueValue *)optDestBuffer, + destType, destType, destBridgeWitness); + } + + // If we succeeded, then take the value from the temp buffer. + if (success) { + destType->vw_initializeWithTake(destLocation, (OpaqueValue *)optDestBuffer); + // Bridge above is effectively a copy, so overall we're a copy. + return DynamicCastResult::SuccessViaCopy; + } + return DynamicCastResult::Failure; +} + +static DynamicCastResult +tryCastFromClassToObjCBridgeable( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + // We need the _ObjectiveCBridgeable conformance for the target + auto destBridgeWitness = findBridgeWitness(destType); + if (destBridgeWitness == nullptr) { + return DynamicCastResult::Failure; + } + + // 1. Sanity check whether the source object can cast to the + // type expected by the target. + + auto targetBridgedClass = + _getBridgedObjectiveCType(MetadataState::Complete, destType, + destBridgeWitness).Value; + void *srcObject = getNonNullSrcObject(srcValue, srcType, destType); + if (nullptr == swift_dynamicCastUnknownClass(srcObject, targetBridgedClass)) { + destFailureType = targetBridgedClass; + return DynamicCastResult::Failure; + } + + return _tryCastFromClassToObjCBridgeable( + destLocation, destType, + srcValue, srcType, srcObject, + destFailureType, srcFailureType, + takeOnSuccess, mayDeferChecks, + destBridgeWitness, targetBridgedClass); +} + +/// Dynamic cast from a value type that conforms to the +/// _ObjectiveCBridgeable protocol to a class type, first by bridging +/// the value to its Objective-C object representation and then by +/// dynamic casting that object to the resulting target type. +/// +/// Caveat: Despite the name, this is also used to bridge Swift value types +/// to Swift classes even when Obj-C is not being used. +static DynamicCastResult +tryCastFromObjCBridgeableToClass( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + auto srcBridgeWitness = findBridgeWitness(srcType); + if (srcBridgeWitness == nullptr) { + return DynamicCastResult::Failure; + } + + // Bridge the source value to an object. + auto srcBridgedObject = + srcBridgeWitness->bridgeToObjectiveC(srcValue, srcType, srcBridgeWitness); + + // Dynamic cast the object to the resulting class type. + if (auto cast = swift_dynamicCastUnknownClass(srcBridgedObject, destType)) { + *reinterpret_cast(destLocation) = cast; + return DynamicCastResult::SuccessViaCopy; + } else { + // We don't need the object anymore. + swift_unknownObjectRelease(srcBridgedObject); + return DynamicCastResult::Failure; + } +} + +/******************************************************************************/ +/****************************** SwiftValue Boxing *****************************/ +/******************************************************************************/ + +#if !SWIFT_OBJC_INTEROP // __SwiftValue is a native class +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +bool swift_unboxFromSwiftValueWithType(OpaqueValue *source, + OpaqueValue *result, + const Metadata *destinationType); + +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +bool swift_swiftValueConformsTo(const Metadata *, const Metadata *); +#endif + +#if SWIFT_OBJC_INTEROP +// Try unwrapping a source holding an Obj-C SwiftValue container and +// recursively casting the contents. +static DynamicCastResult +tryCastUnwrappingObjCSwiftValueSource( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + id srcObject; + memcpy(&srcObject, srcValue, sizeof(id)); + auto srcSwiftValue = getAsSwiftValue(srcObject); + + if (srcSwiftValue == nullptr) { + return DynamicCastResult::Failure; + } + + const Metadata *srcInnerType; + const OpaqueValue *srcInnerValue; + std::tie(srcInnerType, srcInnerValue) + = getValueFromSwiftValue(srcSwiftValue); + // Note: We never `take` the contents from a SwiftValue box as + // it might have other references. Instead, let our caller + // destroy the reference if necessary. + return tryCast( + destLocation, destType, + const_cast(srcInnerValue), srcInnerType, + destFailureType, srcFailureType, + /*takeOnSuccess=*/ false, mayDeferChecks); +} +#endif + +/******************************************************************************/ +/****************************** Class Destination *****************************/ +/******************************************************************************/ + +static DynamicCastResult +tryCastToSwiftClass( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Class); + + auto destClassType = cast(destType); + switch (srcType->getKind()) { + case MetadataKind::Class: // Swift class => Swift class + case MetadataKind::ObjCClassWrapper: { // Obj-C class => Swift class + void *object = getNonNullSrcObject(srcValue, srcType, destType); + if (auto t = swift_dynamicCastClass(object, destClassType)) { + auto castObject = const_cast(t); + *(reinterpret_cast(destLocation)) = castObject; + if (takeOnSuccess) { + return DynamicCastResult::SuccessViaTake; + } else { + swift_unknownObjectRetain(castObject); + return DynamicCastResult::SuccessViaCopy; + } + } else { + srcFailureType = srcType; + destFailureType = destType; + return DynamicCastResult::Failure; + } + } + + case MetadataKind::ForeignClass: // CF class => Swift class + // Top-level code will "unwrap" to an Obj-C class and try again. + return DynamicCastResult::Failure; + + default: + return DynamicCastResult::Failure; + } +} + +static DynamicCastResult +tryCastToObjectiveCClass( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::ObjCClassWrapper); +#if SWIFT_OBJC_INTEROP + auto destObjCType = cast(destType); + + switch (srcType->getKind()) { + case MetadataKind::Class: // Swift class => Obj-C class + case MetadataKind::ObjCClassWrapper: // Obj-C class => Obj-C class + case MetadataKind::ForeignClass: { // CF class => Obj-C class + auto srcObject = getNonNullSrcObject(srcValue, srcType, destType); + auto destObjCClass = destObjCType->Class; + if (auto resultObject + = swift_dynamicCastObjCClass(srcObject, destObjCClass)) { + *reinterpret_cast(destLocation) = resultObject; + if (takeOnSuccess) { + return DynamicCastResult::SuccessViaTake; + } else { + objc_retain((id)const_cast(resultObject)); + return DynamicCastResult::SuccessViaCopy; + } + } + break; + } + + default: + break; + } +#endif + + return DynamicCastResult::Failure; +} + +static DynamicCastResult +tryCastToForeignClass( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ +#if SWIFT_OBJC_INTEROP + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::ForeignClass); + auto destClassType = cast(destType); + + switch (srcType->getKind()) { + case MetadataKind::Class: // Swift class => CF class + case MetadataKind::ObjCClassWrapper: // Obj-C class => CF class + case MetadataKind::ForeignClass: { // CF class => CF class + auto srcObject = getNonNullSrcObject(srcValue, srcType, destType); + if (auto resultObject + = swift_dynamicCastForeignClass(srcObject, destClassType)) { + *reinterpret_cast(destLocation) = resultObject; + if (takeOnSuccess) { + return DynamicCastResult::SuccessViaTake; + } else { + objc_retain((id)const_cast(resultObject)); + return DynamicCastResult::SuccessViaCopy; + } + } + break; + } + default: + break; + } +#endif + + return DynamicCastResult::Failure; +} + +/******************************************************************************/ +/***************************** Enum Destination *******************************/ +/******************************************************************************/ + +static DynamicCastResult +tryCastToEnum( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + // Note: Optional is handled elsewhere + assert(destType->getKind() == MetadataKind::Enum); + + // Enum has no special cast support at present. + + return DynamicCastResult::Failure; +} + +/******************************************************************************/ +/**************************** Struct Destination ******************************/ +/******************************************************************************/ + +// internal func _arrayDownCastIndirect( +// _ source: UnsafePointer>, +// _ target: UnsafeMutablePointer>) +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +void _swift_arrayDownCastIndirect(OpaqueValue *destination, + OpaqueValue *source, + const Metadata *sourceValueType, + const Metadata *targetValueType); + +// internal func _arrayDownCastConditionalIndirect( +// _ source: UnsafePointer>, +// _ target: UnsafeMutablePointer> +// ) -> Bool +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +bool _swift_arrayDownCastConditionalIndirect(OpaqueValue *destination, + OpaqueValue *source, + const Metadata *sourceValueType, + const Metadata *targetValueType); + +// internal func _setDownCastIndirect( +// _ source: UnsafePointer>, +// _ target: UnsafeMutablePointer>) +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +void _swift_setDownCastIndirect(OpaqueValue *destination, + OpaqueValue *source, + const Metadata *sourceValueType, + const Metadata *targetValueType, + const void *sourceValueHashable, + const void *targetValueHashable); + +// internal func _setDownCastConditionalIndirect( +// _ source: UnsafePointer>, +// _ target: UnsafeMutablePointer> +// ) -> Bool +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +bool _swift_setDownCastConditionalIndirect(OpaqueValue *destination, + OpaqueValue *source, + const Metadata *sourceValueType, + const Metadata *targetValueType, + const void *sourceValueHashable, + const void *targetValueHashable); + +// internal func _dictionaryDownCastIndirect( +// _ source: UnsafePointer>, +// _ target: UnsafeMutablePointer>) +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +void _swift_dictionaryDownCastIndirect(OpaqueValue *destination, + OpaqueValue *source, + const Metadata *sourceKeyType, + const Metadata *sourceValueType, + const Metadata *targetKeyType, + const Metadata *targetValueType, + const void *sourceKeyHashable, + const void *targetKeyHashable); + +// internal func _dictionaryDownCastConditionalIndirect( +// _ source: UnsafePointer>, +// _ target: UnsafeMutablePointer> +// ) -> Bool +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +bool _swift_dictionaryDownCastConditionalIndirect(OpaqueValue *destination, + OpaqueValue *source, + const Metadata *sourceKeyType, + const Metadata *sourceValueType, + const Metadata *targetKeyType, + const Metadata *targetValueType, + const void *sourceKeyHashable, + const void *targetKeyHashable); + +#if SWIFT_OBJC_INTEROP +// Helper to memoize bridging conformance data for a particular +// Swift struct type. This is used to speed up the most common +// ObjC->Swift bridging conversions by eliminating repeeated +// protocol conformance lookups. + +// Currently used only for String, which may be the only +// type used often enough to justify the extra static memory. +struct ObjCBridgeMemo { +#if !NDEBUG + // Used in assert build to verify that we always get called with + // the same destType + const Metadata *destType; +#endif + const _ObjectiveCBridgeableWitnessTable *destBridgeWitness; + const Metadata *targetBridgedType; + Class targetBridgedObjCClass; + swift_once_t fetchWitnessOnce; + + DynamicCastResult tryBridge( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) + { + struct SetupData { + const Metadata *destType; + struct ObjCBridgeMemo *memo; + } setupData { destType, this }; + + swift_once(&fetchWitnessOnce, + [](void *data) { + struct SetupData *setupData = (struct SetupData *)data; + struct ObjCBridgeMemo *memo = setupData->memo; +#if !NDEBUG + memo->destType = setupData->destType; +#endif + memo->destBridgeWitness = findBridgeWitness(setupData->destType); + if (memo->destBridgeWitness == nullptr) { + memo->targetBridgedType = nullptr; + memo->targetBridgedObjCClass = nullptr; + } else { + memo->targetBridgedType = _getBridgedObjectiveCType( + MetadataState::Complete, setupData->destType, memo->destBridgeWitness).Value; + assert(memo->targetBridgedType->getKind() == MetadataKind::ObjCClassWrapper); + memo->targetBridgedObjCClass = memo->targetBridgedType->getObjCClassObject(); + assert(memo->targetBridgedObjCClass != nullptr); + } + }, (void *)&setupData); + + // Check that this always gets called with the same destType. + assert((destType == this->destType) && "ObjC casting memo used inconsistently"); + + // !! If bridging is not usable, stop here. + if (targetBridgedObjCClass == nullptr) { + return DynamicCastResult::Failure; + } + // Use the dynamic ISA type of the object always (Note that this + // also implicitly gives us the ObjC type for a CF object.) + void *srcObject = getNonNullSrcObject(srcValue, srcType, destType); + Class srcObjCType = object_getClass((id)srcObject); + // Fail if the ObjC object is not a subclass of the bridge class. + while (srcObjCType != targetBridgedObjCClass) { + srcObjCType = class_getSuperclass(srcObjCType); + if (srcObjCType == nullptr) { + return DynamicCastResult::Failure; + } + } + // The ObjC object is an acceptable type, so call the bridge function... + return _tryCastFromClassToObjCBridgeable( + destLocation, destType, srcValue, srcType, srcObject, + destFailureType, srcFailureType, + takeOnSuccess, mayDeferChecks, + destBridgeWitness, targetBridgedType); + } +}; +#endif + +static DynamicCastResult +tryCastToAnyHashable( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Struct); + assert(cast(destType)->Description + == &STRUCT_TYPE_DESCR_SYM(s11AnyHashable)); + + auto hashableConformance = reinterpret_cast( + swift_conformsToProtocol(srcType, &HashableProtocolDescriptor)); + if (hashableConformance) { + _swift_convertToAnyHashableIndirect(srcValue, destLocation, + srcType, hashableConformance); + return DynamicCastResult::SuccessViaCopy; + } else { + return DynamicCastResult::Failure; + } +} + +static DynamicCastResult +tryCastToArray( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Struct); + assert(cast(destType)->Description + == &NOMINAL_TYPE_DESCR_SYM(Sa)); + + switch (srcType->getKind()) { + case MetadataKind::Struct: { // Struct -> Array + const auto srcStructType = cast(srcType); + if (srcStructType->Description == &NOMINAL_TYPE_DESCR_SYM(Sa)) { // Array -> Array + auto sourceArgs = srcType->getGenericArgs(); + auto destArgs = destType->getGenericArgs(); + if (mayDeferChecks) { + _swift_arrayDownCastIndirect( + srcValue, destLocation, sourceArgs[0], destArgs[0]); + return DynamicCastResult::SuccessViaCopy; + } else { + auto result = _swift_arrayDownCastConditionalIndirect( + srcValue, destLocation, sourceArgs[0], destArgs[0]); + if (result) { + return DynamicCastResult::SuccessViaCopy; + } + } + } + break; + } + + default: + break; + } + + return DynamicCastResult::Failure; +} + +static DynamicCastResult +tryCastToDictionary( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Struct); + assert(cast(destType)->Description + == &NOMINAL_TYPE_DESCR_SYM(SD)); + + switch (srcType->getKind()) { + case MetadataKind::Struct: { // Struct -> Dictionary + const auto srcStructType = cast(srcType); + if (srcStructType->Description == &NOMINAL_TYPE_DESCR_SYM(SD)) { // Dictionary -> Dictionary + auto sourceArgs = srcType->getGenericArgs(); + auto destArgs = destType->getGenericArgs(); + if (mayDeferChecks) { + _swift_dictionaryDownCastIndirect( + srcValue, destLocation, sourceArgs[0], sourceArgs[1], + destArgs[0], destArgs[1], sourceArgs[2], destArgs[2]); + return DynamicCastResult::SuccessViaCopy; + } else { + auto result = _swift_dictionaryDownCastConditionalIndirect( + srcValue, destLocation, sourceArgs[0], sourceArgs[1], + destArgs[0], destArgs[1], sourceArgs[2], destArgs[2]); + if (result) { + return DynamicCastResult::SuccessViaCopy; + } + } + } + break; + } + + default: + break; + } + return DynamicCastResult::Failure; +} + +static DynamicCastResult +tryCastToSet( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Struct); + assert(cast(destType)->Description + == &NOMINAL_TYPE_DESCR_SYM(Sh)); + + switch (srcType->getKind()) { + + case MetadataKind::Struct: { // Struct -> Set + const auto srcStructType = cast(srcType); + if (srcStructType->Description == &NOMINAL_TYPE_DESCR_SYM(Sh)) { // Set -> Set + auto sourceArgs = srcType->getGenericArgs(); + auto destArgs = destType->getGenericArgs(); + if (mayDeferChecks) { + _swift_setDownCastIndirect(srcValue, destLocation, + sourceArgs[0], destArgs[0], sourceArgs[1], destArgs[1]); + return DynamicCastResult::SuccessViaCopy; + } else { + auto result = _swift_setDownCastConditionalIndirect( + srcValue, destLocation, + sourceArgs[0], destArgs[0], + sourceArgs[1], destArgs[1]); + if (result) { + return DynamicCastResult::SuccessViaCopy; + } + } + } + break; + } + + default: + break; + } + return DynamicCastResult::Failure; +} + +static DynamicCastResult +tryCastToString( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Struct); + assert(cast(destType)->Description + == &NOMINAL_TYPE_DESCR_SYM(SS)); + + switch (srcType->getKind()) { + case MetadataKind::ForeignClass: // CF -> String + case MetadataKind::ObjCClassWrapper: { // Obj-C -> String +#if SWIFT_OBJC_INTEROP + static ObjCBridgeMemo memo; + return memo.tryBridge( + destLocation, destType, srcValue, srcType, + destFailureType, srcFailureType, + takeOnSuccess, mayDeferChecks); +#endif + } + default: + return DynamicCastResult::Failure; + } + return DynamicCastResult::Failure; +} + +static DynamicCastResult +tryCastToStruct( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Struct); + + // There is no special cast handling at present for general Struct types. + + // Special logic for AnyHashable, Set, Dictionary, Array, and String + // is broken out above. See also selectCasterForDest() for the + // logic that chooses one of these functions. + + return DynamicCastResult::Failure; +} + +/******************************************************************************/ +/*************************** Optional Destination *****************************/ +/******************************************************************************/ + +static DynamicCastResult +tryCastToOptional( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Optional); + + // Nothing to do for the basic casting operation. + // Unwrapping is handled by top-level tryCast with assistance + // from utility functions below. + + return DynamicCastResult::Failure; +} + +// The nil value `T?.none` can be cast to any optional type. +// When the unwrapper sees a source value that is nil, it calls +// tryCastFromNil() to try to set the target optional to nil. +// +// This is complicated by the desire to preserve the nesting +// as far as possible. For example, we would like: +// Int?.none => Int??.some(.none) +// Int??.none => Any????.some(.some(.none)) +// Of course, if the target is shallower than the source, +// then we have to just set the outermost optional to nil. + +// This helper sets a nested optional to nil at a requested level: +static void +initializeToNilAtDepth(OpaqueValue *destLocation, const Metadata *destType, int depth) { + assert(destType->getKind() == MetadataKind::Optional); + auto destInnerType = cast(destType)->getGenericArgs()[0]; + if (depth > 0) { + initializeToNilAtDepth(destLocation, destInnerType, depth - 1); + // Set .some at each level as we unwind + destInnerType->vw_storeEnumTagSinglePayload( + destLocation, 0, 1); + } else { + // Set .none at the lowest level + destInnerType->vw_storeEnumTagSinglePayload( + destLocation, 1, 1); + } +} + +static void +copyNil(OpaqueValue *destLocation, const Metadata *destType, const Metadata *srcType) +{ + assert(srcType->getKind() == MetadataKind::Optional); + assert(destType->getKind() == MetadataKind::Optional); + + // Measure how deep the source nil is: Is it Int?.none or Int??.none or ... + auto srcInnerType = cast(srcType)->getGenericArgs()[0]; + int srcDepth = 1; + while (srcInnerType->getKind() == MetadataKind::Optional) { + srcInnerType = cast(srcInnerType)->getGenericArgs()[0]; + srcDepth += 1; + } + + // Measure how deep the destination optional is + auto destInnerType = cast(destType)->getGenericArgs()[0]; + int destDepth = 1; + while (destInnerType->getKind() == MetadataKind::Optional) { + destInnerType = cast(destInnerType)->getGenericArgs()[0]; + destDepth += 1; + } + + // Recursively set the destination to .some(.some(... .some(.none))) + auto targetDepth = std::max(destDepth - srcDepth, 0); + initializeToNilAtDepth(destLocation, destType, targetDepth); +} + +// Try unwrapping both source and dest optionals together. +// If the source is nil, then cast that to the destination. +static DynamicCastResult +tryCastUnwrappingOptionalBoth( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(destType->getKind() == MetadataKind::Optional); + assert(srcType->getKind() == MetadataKind::Optional); + + auto srcInnerType = cast(srcType)->getGenericArgs()[0]; + unsigned sourceEnumCase = srcInnerType->vw_getEnumTagSinglePayload( + srcValue, /*emptyCases=*/1); + auto sourceIsNil = (sourceEnumCase != 0); + if (sourceIsNil) { + copyNil(destLocation, destType, srcType); + return DynamicCastResult::SuccessViaCopy; // nil was essentially copied to dest + } else { + auto destEnumType = cast(destType); + const Metadata *destInnerType = destEnumType->getGenericArgs()[0]; + auto destInnerLocation = destLocation; // Single-payload enum layout + auto subcastResult = tryCast( + destInnerLocation, destInnerType, srcValue, srcInnerType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + if (isSuccess(subcastResult)) { + destInnerType->vw_storeEnumTagSinglePayload( + destLocation, /*case*/ 0, /*emptyCases*/ 1); + } + return subcastResult; + } + return DynamicCastResult::Failure; +} + +// Try unwrapping just the destination optional. +// Note we do this even if both src and dest are optional. +// For example, Int -> Any? requires unwrapping the destination +// in order to inject the Int into the existential. +static DynamicCastResult +tryCastUnwrappingOptionalDestination( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(destType->getKind() == MetadataKind::Optional); + + auto destEnumType = cast(destType); + const Metadata *destInnerType = destEnumType->getGenericArgs()[0]; + auto destInnerLocation = destLocation; // Single-payload enum layout + auto subcastResult = tryCast( + destInnerLocation, destInnerType, srcValue, srcType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + if (isSuccess(subcastResult)) { + destInnerType->vw_storeEnumTagSinglePayload( + destLocation, /*case*/ 0, /*emptyCases*/ 1); + } + return subcastResult; +} + +// Try unwrapping just the source optional. +// Note we do this even if both target and dest are optional. +// For example, this is used when extracting the contents of +// an Optional. +static DynamicCastResult +tryCastUnwrappingOptionalSource( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType->getKind() == MetadataKind::Optional); + + auto srcInnerType = cast(srcType)->getGenericArgs()[0]; + unsigned sourceEnumCase = srcInnerType->vw_getEnumTagSinglePayload( + srcValue, /*emptyCases=*/1); + auto nonNil = (sourceEnumCase == 0); + if (nonNil) { + // Recurse with unwrapped source + return tryCast(destLocation, destType, srcValue, srcInnerType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + } + return DynamicCastResult::Failure; +} + +/******************************************************************************/ +/***************************** Tuple Destination ******************************/ +/******************************************************************************/ + +// The only thing that can be legally cast to a tuple is another tuple. +// Most of the logic below is required to handle element-wise casts of +// tuples that are compatible but not of the same type. + +static DynamicCastResult +tryCastToTuple( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Tuple); + const auto destTupleType = cast(destType); + + srcFailureType = srcType; + destFailureType = destType; + + // We cannot cast non-tuple data to a tuple + if (srcType->getKind() != MetadataKind::Tuple) { + return DynamicCastResult::Failure; + } + const auto srcTupleType = cast(srcType); + + // Tuples must have same number of elements + if (srcTupleType->NumElements != destTupleType->NumElements) { + return DynamicCastResult::Failure; + } + + // Common labels must match + const char *srcLabels = srcTupleType->Labels; + const char *destLabels = destTupleType->Labels; + while (srcLabels != nullptr + && destLabels != nullptr + && srcLabels != destLabels) + { + const char *srcSpace = strchr(srcLabels, ' '); + const char *destSpace = strchr(destLabels, ' '); + + // If we've reached the end of either label string, we're done. + if (srcSpace == nullptr || destSpace == nullptr) { + break; + } + + // If both labels are non-empty, and the labels mismatch, we fail. + if (srcSpace != srcLabels && destSpace != destLabels) { + unsigned srcLen = srcSpace - srcLabels; + unsigned destLen = destSpace - destLabels; + if (srcLen != destLen || + strncmp(srcLabels, destLabels, srcLen) != 0) + return DynamicCastResult::Failure; + } + + srcLabels = srcSpace + 1; + destLabels = destSpace + 1; + } + + // Compare the element types to see if they all match. + bool typesMatch = true; + auto numElements = srcTupleType->NumElements; + for (unsigned i = 0; typesMatch && i != numElements; ++i) { + if (srcTupleType->getElement(i).Type != destTupleType->getElement(i).Type) { + typesMatch = false; + } + } + + if (typesMatch) { + // The actual element types are identical, so we can use the + // fast value-witness machinery for the whole tuple. + if (takeOnSuccess) { + srcType->vw_initializeWithTake(destLocation, srcValue); + return DynamicCastResult::SuccessViaTake; + } else { + srcType->vw_initializeWithCopy(destLocation, srcValue); + return DynamicCastResult::SuccessViaCopy; + } + } else { + // Slow path casts each item separately. + for (unsigned j = 0, n = srcTupleType->NumElements; j != n; ++j) { + const auto &srcElt = srcTupleType->getElement(j); + const auto &destElt = destTupleType->getElement(j); + auto subcastResult = tryCast(destElt.findIn(destLocation), destElt.Type, + srcElt.findIn(srcValue), srcElt.Type, + destFailureType, srcFailureType, + false, mayDeferChecks); + if (subcastResult == DynamicCastResult::Failure) { + for (unsigned k = 0; k != j; ++k) { + const auto &elt = destTupleType->getElement(k); + elt.Type->vw_destroy(elt.findIn(destLocation)); + } + return DynamicCastResult::Failure; + } + } + // We succeeded by casting each item. + return DynamicCastResult::SuccessViaCopy; + } + +} + +/******************************************************************************/ +/**************************** Function Destination ****************************/ +/******************************************************************************/ + +// The only thing that can be legally cast to a function is another function. + +static DynamicCastResult +tryCastToFunction( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Function); + const auto destFuncType = cast(destType); + + // Function casts succeed on exact matches, or if the target type is + // throwier than the source type. + // + // TODO: We could also allow ABI-compatible variance, such as casting + // a dynamic Base -> Derived to Derived -> Base. We wouldn't be able to + // perform a dynamic cast that required any ABI adjustment without a JIT + // though. + + if (srcType->getKind() != MetadataKind::Function) { + return DynamicCastResult::Failure; + } + auto srcFuncType = cast(srcType); + + // Check that argument counts and convention match (but ignore + // "throws" for now). + if (srcFuncType->Flags.withThrows(false) + != destFuncType->Flags.withThrows(false)) { + return DynamicCastResult::Failure; + } + + // If the target type can't throw, neither can the source. + if (srcFuncType->isThrowing() && !destFuncType->isThrowing()) + return DynamicCastResult::Failure; + + // The result and argument types must match. + if (srcFuncType->ResultType != destFuncType->ResultType) + return DynamicCastResult::Failure; + if (srcFuncType->getNumParameters() != destFuncType->getNumParameters()) + return DynamicCastResult::Failure; + if (srcFuncType->hasParameterFlags() != destFuncType->hasParameterFlags()) + return DynamicCastResult::Failure; + for (unsigned i = 0, e = srcFuncType->getNumParameters(); i < e; ++i) { + if (srcFuncType->getParameter(i) != destFuncType->getParameter(i) || + srcFuncType->getParameterFlags(i) != destFuncType->getParameterFlags(i)) + return DynamicCastResult::Failure; + } + + // Everything matches, so we can take/copy the function reference. + if (takeOnSuccess) { + srcType->vw_initializeWithTake(destLocation, srcValue); + return DynamicCastResult::SuccessViaTake; + } else { + srcType->vw_initializeWithCopy(destLocation, srcValue); + return DynamicCastResult::SuccessViaCopy; + } +} + +/******************************************************************************/ +/************************** Existential Destination ***************************/ +/******************************************************************************/ + +/// Check whether a type conforms to the given protocols, filling in a +/// list of conformances. +static bool _conformsToProtocols(const OpaqueValue *value, + const Metadata *type, + const ExistentialTypeMetadata *existentialType, + const WitnessTable **conformances) { + if (auto *superclass = existentialType->getSuperclassConstraint()) { + if (!swift_dynamicCastMetatype(type, superclass)) + return false; + } + + if (existentialType->isClassBounded()) { + if (!Metadata::isAnyKindOfClass(type->getKind())) + return false; + } + + for (auto protocol : existentialType->getProtocols()) { + if (!swift::_conformsToProtocol(value, type, protocol, conformances)) + return false; + if (conformances != nullptr && protocol.needsWitnessTable()) { + assert(*conformances != nullptr); + ++conformances; + } + } + + return true; +} + +// Cast to unconstrained `Any` +static DynamicCastResult +tryCastToUnconstrainedOpaqueExistential( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Existential); + assert(cast(destType)->getRepresentation() + == ExistentialTypeRepresentation::Opaque); + auto destExistential + = reinterpret_cast(destLocation); + + // Fill in the type and value. + destExistential->Type = srcType; + auto *destBox = srcType->allocateBoxForExistentialIn(&destExistential->Buffer); + if (takeOnSuccess) { + srcType->vw_initializeWithTake(destBox, srcValue); + return DynamicCastResult::SuccessViaTake; + } else { + srcType->vw_initializeWithCopy(destBox, srcValue); + return DynamicCastResult::SuccessViaCopy; + } +} + +// Cast to constrained `Any` +static DynamicCastResult +tryCastToConstrainedOpaqueExistential( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Existential); + auto destExistentialType = cast(destType); + assert(destExistentialType->getRepresentation() + == ExistentialTypeRepresentation::Opaque); + auto destExistential + = reinterpret_cast(destLocation); + + // Check for protocol conformances and fill in the witness tables. + // TODO (rdar://17033499) If the source is an existential, we should + // be able to compare the protocol constraints more efficiently than this. + if (_conformsToProtocols(srcValue, srcType, destExistentialType, + destExistential->getWitnessTables())) { + return tryCastToUnconstrainedOpaqueExistential( + destLocation, destType, srcValue, srcType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + } else { + return DynamicCastResult::Failure; + } +} + +static DynamicCastResult +tryCastToClassExistential( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Existential); + auto destExistentialType = cast(destType); + assert(destExistentialType->getRepresentation() + == ExistentialTypeRepresentation::Class); + auto destExistentialLocation + = reinterpret_cast(destLocation); + + MetadataKind srcKind = srcType->getKind(); + switch (srcKind) { + + case MetadataKind::Metatype: { +#if SWIFT_OBJC_INTEROP + // Get an object reference to the metatype and try fitting that into + // the existential... + auto metatypePtr = reinterpret_cast(srcValue); + auto metatype = *metatypePtr; + if (auto tmp = swift_dynamicCastMetatypeToObjectConditional(metatype)) { + auto value = reinterpret_cast(&tmp); + auto type = reinterpret_cast(tmp); + if (_conformsToProtocols(value, type, destExistentialType, + destExistentialLocation->getWitnessTables())) { + auto object = *(reinterpret_cast(value)); + destExistentialLocation->Value = object; + if (takeOnSuccess) { + // We copied the pointer without retain, so the source is no + // longer valid... + return DynamicCastResult::SuccessViaTake; + } else { + swift_unknownObjectRetain(object); + return DynamicCastResult::SuccessViaCopy; + } + } else { + // We didn't assign to destination, so the source reference + // is still valid and the reference count is still correct. + } + } +#endif + return DynamicCastResult::Failure; + } + + case MetadataKind::ObjCClassWrapper: + case MetadataKind::Class: + case MetadataKind::ForeignClass: { + auto object = getNonNullSrcObject(srcValue, srcType, destType); + if (_conformsToProtocols(srcValue, srcType, + destExistentialType, + destExistentialLocation->getWitnessTables())) { + destExistentialLocation->Value = object; + if (takeOnSuccess) { + return DynamicCastResult::SuccessViaTake; + } else { + swift_unknownObjectRetain(object); + return DynamicCastResult::SuccessViaCopy; + } + } + return DynamicCastResult::Failure; + } + + default: + return DynamicCastResult::Failure; + } + + return DynamicCastResult::Failure; +} + +// SwiftValue boxing is a failsafe that we only want to invoke +// after other approaches have failed. This is why it's not +// integrated into tryCastToClassExistential() above. +static DynamicCastResult +tryCastToClassExistentialViaSwiftValue( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Existential); + auto destExistentialType = cast(destType); + assert(destExistentialType->getRepresentation() + == ExistentialTypeRepresentation::Class); + auto destExistentialLocation + = reinterpret_cast(destLocation); + + // Fail if the target has constraints that make it unsuitable for + // a __SwiftValue box. + // FIXME: We should not have different checks here for + // Obj-C vs non-Obj-C. The _SwiftValue boxes should conform + // to the exact same protocols on both platforms. + bool destIsConstrained = destExistentialType->NumProtocols != 0; + if (destIsConstrained) { +#if SWIFT_OBJC_INTEROP // __SwiftValue is an Obj-C class + if (!findSwiftValueConformances( + destExistentialType, destExistentialLocation->getWitnessTables())) { + return DynamicCastResult::Failure; + } +#else // __SwiftValue is a native class + if (!swift_swiftValueConformsTo(destType, destType)) { + return DynamicCastResult::Failure; + } +#endif + } + +#if SWIFT_OBJC_INTEROP + auto object = bridgeAnythingToSwiftValueObject( + srcValue, srcType, takeOnSuccess); + destExistentialLocation->Value = object; + if (takeOnSuccess) { + return DynamicCastResult::SuccessViaTake; + } else { + return DynamicCastResult::SuccessViaCopy; + } +# else + // Note: Code below works correctly on both Obj-C and non-Obj-C platforms, + // but the code above is slightly faster on Obj-C platforms. + auto object = _bridgeAnythingToObjectiveC(srcValue, srcType); + destExistentialLocation->Value = object; + return DynamicCastResult::SuccessViaCopy; +#endif +} + +static DynamicCastResult +tryCastToErrorExistential( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Existential); + auto destExistentialType = cast(destType); + assert(destExistentialType->getRepresentation() + == ExistentialTypeRepresentation::Error); + auto destBoxAddr = reinterpret_cast(destLocation); + + MetadataKind srcKind = srcType->getKind(); + switch (srcKind) { + case MetadataKind::ForeignClass: // CF object => Error + case MetadataKind::ObjCClassWrapper: // Obj-C object => Error + case MetadataKind::Struct: // Struct => Error + case MetadataKind::Enum: // Enum => Error + case MetadataKind::Class: { // Class => Error + assert(destExistentialType->NumProtocols == 1); + const WitnessTable *errorWitness; + if (_conformsToProtocols( + srcValue, srcType, destExistentialType, &errorWitness)) { +#if SWIFT_OBJC_INTEROP + // If it already holds an NSError, just use that. + if (auto embedded = getErrorEmbeddedNSErrorIndirect( + srcValue, srcType, errorWitness)) { + *destBoxAddr = reinterpret_cast(embedded); + return DynamicCastResult::SuccessViaCopy; + } +#endif + + BoxPair destBox = swift_allocError( + srcType, errorWitness, srcValue, takeOnSuccess); + *destBoxAddr = reinterpret_cast(destBox.object); + if (takeOnSuccess) { + return DynamicCastResult::SuccessViaTake; + } else { + return DynamicCastResult::SuccessViaCopy; + } + } + return DynamicCastResult::Failure; + } + + default: + return DynamicCastResult::Failure; + } +} + +static DynamicCastResult +tryCastUnwrappingExistentialSource( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + auto srcExistentialType = cast(srcType); + + // Unpack the existential content + const Metadata *srcInnerType; + OpaqueValue *srcInnerValue; + switch (srcExistentialType->getRepresentation()) { + case ExistentialTypeRepresentation::Class: { + auto classContainer + = reinterpret_cast(srcValue); + srcInnerType = swift_getObjectType((HeapObject *)classContainer->Value); + srcInnerValue = reinterpret_cast(&classContainer->Value); + break; + } + case ExistentialTypeRepresentation::Opaque: { + auto opaqueContainer + = reinterpret_cast(srcValue); + srcInnerType = opaqueContainer->Type; + srcInnerValue = srcExistentialType->projectValue(srcValue); + break; + } + case ExistentialTypeRepresentation::Error: { + const SwiftError *errorBox + = *reinterpret_cast(srcValue); + auto srcErrorValue + = errorBox->isPureNSError() ? srcValue : errorBox->getValue(); + srcInnerType = errorBox->getType(); + srcInnerValue = const_cast(srcErrorValue); + break; + } + } + + srcFailureType = srcInnerType; + return tryCast(destLocation, destType, + srcInnerValue, srcInnerType, + destFailureType, srcFailureType, + takeOnSuccess & (srcInnerValue == srcValue), + mayDeferChecks); +} + +/******************************************************************************/ +/**************************** Opaque Destination ******************************/ +/******************************************************************************/ + +static DynamicCastResult +tryCastToOpaque( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Opaque); + + // There's nothing special we can do here, but we have to have this + // empty function in order for the general casting logic to run + // for these types. + + return DynamicCastResult::Failure; +} + +/******************************************************************************/ +/**************************** Metatype Destination ****************************/ +/******************************************************************************/ + +#if SWIFT_OBJC_INTEROP +/// Check whether an unknown class instance is actually a type/metatype object. +static const Metadata *_getUnknownClassAsMetatype(void *object) { + // Objective-C class metadata are objects, so an AnyObject (or + // NSObject) may refer to a class object. + + // Test whether the object's isa is a metaclass, which indicates that + // the object is a class. + + Class isa = object_getClass((id)object); + if (class_isMetaClass(isa)) { + return swift_getObjCClassMetadata((const ClassMetadata *)object); + } + + return nullptr; +} +#endif + +static DynamicCastResult +tryCastToMetatype( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::Metatype); + + const MetatypeMetadata *destMetatypeType = cast(destType); + MetadataKind srcKind = srcType->getKind(); + switch (srcKind) { + case MetadataKind::Metatype: + case MetadataKind::ExistentialMetatype: { + const Metadata *srcMetatype = *(const Metadata * const *) srcValue; + if (auto result = swift_dynamicCastMetatype( + srcMetatype, destMetatypeType->InstanceType)) { + *((const Metadata **) destLocation) = result; + return DynamicCastResult::SuccessViaCopy; + } + return DynamicCastResult::Failure; + } + + case MetadataKind::Class: + case MetadataKind::ObjCClassWrapper: { +#if SWIFT_OBJC_INTEROP + // Some classes are actually metatypes + void *object = getNonNullSrcObject(srcValue, srcType, destType); + if (auto metatype = _getUnknownClassAsMetatype(object)) { + auto srcInnerValue = reinterpret_cast(&metatype); + auto srcInnerType = swift_getMetatypeMetadata(metatype); + return tryCast(destLocation, destType, srcInnerValue, srcInnerType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + } +#endif + return DynamicCastResult::Failure; + } + + default: + return DynamicCastResult::Failure; + } +} + +/// Perform a dynamic cast of a metatype to an existential metatype type. +static DynamicCastResult +_dynamicCastMetatypeToExistentialMetatype( + OpaqueValue *destLocation, const ExistentialMetatypeMetadata *destType, + const Metadata *srcMetatype, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + // The instance type of an existential metatype must be either an + // existential or an existential metatype. + auto destMetatype + = reinterpret_cast(destLocation); + + // If it's an existential, we need to check for conformances. + auto targetInstanceType = destType->InstanceType; + if (auto targetInstanceTypeAsExistential = + dyn_cast(targetInstanceType)) { + // Check for conformance to all the protocols. + // TODO: collect the witness tables. + const WitnessTable **conformance + = destMetatype ? destMetatype->getWitnessTables() : nullptr; + if (!_conformsToProtocols(nullptr, srcMetatype, + targetInstanceTypeAsExistential, + conformance)) { + return DynamicCastResult::Failure; + } + + if (destMetatype) + destMetatype->Value = srcMetatype; + return DynamicCastResult::SuccessViaCopy; + } + + // Otherwise, we're casting to SomeProtocol.Type.Type. + auto targetInstanceTypeAsMetatype = + cast(targetInstanceType); + + // If the source type isn't a metatype, the cast fails. + auto srcMetatypeMetatype = dyn_cast(srcMetatype); + if (!srcMetatypeMetatype) { + return DynamicCastResult::Failure; + } + + // The representation of an existential metatype remains consistent + // arbitrarily deep: a metatype, followed by some protocols. The + // protocols are the same at every level, so we can just set the + // metatype correctly and then recurse, letting the recursive call + // fill in the conformance information correctly. + + // Proactively set the destination metatype so that we can tail-recur, + // unless we've already done so. There's no harm in doing this even if + // the cast fails. + if (destLocation) + *((const Metadata **) destLocation) = srcMetatype; + + // Recurse. + auto srcInstanceType = srcMetatypeMetatype->InstanceType; + return _dynamicCastMetatypeToExistentialMetatype( + nullptr, + targetInstanceTypeAsMetatype, + srcInstanceType, + destFailureType, + srcFailureType, + takeOnSuccess, mayDeferChecks); +} + +// "ExistentialMetatype" is the metatype for an existential type. +static DynamicCastResult +tryCastToExistentialMetatype( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + assert(srcType != destType); + assert(destType->getKind() == MetadataKind::ExistentialMetatype); + + auto destExistentialMetatypeType + = cast(destType); + MetadataKind srcKind = srcType->getKind(); + switch (srcKind) { + case MetadataKind::Metatype: // Metatype => ExistentialMetatype + case MetadataKind::ExistentialMetatype: { // ExistentialMetatype => ExistentialMetatype + const Metadata *srcMetatype = *(const Metadata * const *) srcValue; + return _dynamicCastMetatypeToExistentialMetatype( + destLocation, + destExistentialMetatypeType, + srcMetatype, + destFailureType, + srcFailureType, + takeOnSuccess, mayDeferChecks); + } + + case MetadataKind::ObjCClassWrapper: { + // Some Obj-C classes are actually metatypes +#if SWIFT_OBJC_INTEROP + void *srcObject = getNonNullSrcObject(srcValue, srcType, destType); + if (auto metatype = _getUnknownClassAsMetatype(srcObject)) { + return _dynamicCastMetatypeToExistentialMetatype( + destLocation, + destExistentialMetatypeType, + metatype, + destFailureType, + srcFailureType, + takeOnSuccess, mayDeferChecks); + } +#endif + return DynamicCastResult::Failure; + } + + default: + return DynamicCastResult::Failure; + } +} + +/******************************************************************************/ +/********************************** Dispatch **********************************/ +/******************************************************************************/ + +// A layer of functions that evaluate the source and/or destination types +// in order to invoke a tailored casting operation above. +// +// This layer also deals with general issues of unwrapping box types +// and invoking bridging conversions defined via the _ObjectiveCBridgeable +// protocol. +// +// Most of the caster functions above should be fairly simple: +// * They should deal with a single target type, +// * They should assume the source is fully unwrapped, +// * They should not try to report or cleanup failure, +// * If they can take, they should report the source was destroyed. + +// Based on the destination type alone, select a targeted casting function. +// This design avoids some redundant inspection of the destination type +// data, for example, when we unwrap source boxes. +static tryCastFunctionType *selectCasterForDest(const Metadata *destType) { + auto destKind = destType->getKind(); + switch (destKind) { + case MetadataKind::Class: + return tryCastToSwiftClass; + case MetadataKind::Struct: { + const auto targetDescriptor = cast(destType)->Description; + if (targetDescriptor == &NOMINAL_TYPE_DESCR_SYM(SS)) { + return tryCastToString; + } + if (targetDescriptor == &STRUCT_TYPE_DESCR_SYM(s11AnyHashable)) { + return tryCastToAnyHashable; + } + if (targetDescriptor == &NOMINAL_TYPE_DESCR_SYM(Sa)) { + return tryCastToArray; + } + if (targetDescriptor == &NOMINAL_TYPE_DESCR_SYM(SD)) { + return tryCastToDictionary; + } + if (targetDescriptor == &NOMINAL_TYPE_DESCR_SYM(Sh)) { + return tryCastToSet; + } + return tryCastToStruct; + } + case MetadataKind::Enum: + return tryCastToEnum; + case MetadataKind::Optional: + return tryCastToOptional; + case MetadataKind::ForeignClass: + return tryCastToForeignClass; + case MetadataKind::Opaque: + return tryCastToOpaque; + case MetadataKind::Tuple: + return tryCastToTuple; + case MetadataKind::Function: + return tryCastToFunction; + case MetadataKind::Existential: { + auto existentialType = cast(destType); + switch (existentialType->getRepresentation()) { + case ExistentialTypeRepresentation::Opaque: + if (existentialType->NumProtocols == 0) { + return tryCastToUnconstrainedOpaqueExistential; // => Unconstrained Any + } else { + return tryCastToConstrainedOpaqueExistential; // => Non-class-constrained protocol + } + case ExistentialTypeRepresentation::Class: + return tryCastToClassExistential; // => AnyObject, with or without protocol constraints + case ExistentialTypeRepresentation::Error: // => Error existential + return tryCastToErrorExistential; + } + swift_runtime_unreachable( + "Unknown existential type representation in dynamic cast dispatch"); + } + case MetadataKind::Metatype: + return tryCastToMetatype; + case MetadataKind::ObjCClassWrapper: + return tryCastToObjectiveCClass; + case MetadataKind::ExistentialMetatype: + return tryCastToExistentialMetatype; + case MetadataKind::HeapLocalVariable: + case MetadataKind::HeapGenericLocalVariable: + case MetadataKind::ErrorObject: + // These are internal details of runtime-only structures, + // so will never appear in compiler-generated types. + // As such, they don't need support here. + swift_runtime_unreachable( + "Unexpected MetadataKind in dynamic cast dispatch"); + return nullptr; + default: + // If you see this message, then there is a new MetadataKind that I didn't + // know about when I wrote this code. Please figure out what it is, how to + // handle it, and add a case for it. + swift_runtime_unreachable( + "Unknown MetadataKind in dynamic cast dispatch"); + } +} + +// This top-level driver provides the general flow for all casting +// operations. It recursively unwraps source and destination as it +// searches for a suitable conversion. +static DynamicCastResult +tryCast( + OpaqueValue *destLocation, const Metadata *destType, + OpaqueValue *srcValue, const Metadata *srcType, + const Metadata *&destFailureType, const Metadata *&srcFailureType, + bool takeOnSuccess, bool mayDeferChecks) +{ + destFailureType = destType; + srcFailureType = srcType; + + //////////////////////////////////////////////////////////////////////// + // + // 1. If types match exactly, we can just move/copy the data. + // (The tryCastToXyz functions never see this trivial case.) + // + if (srcType == destType) { + if (takeOnSuccess) { + destType->vw_initializeWithTake(destLocation, srcValue); + return DynamicCastResult::SuccessViaTake; + } else { + destType->vw_initializeWithCopy(destLocation, srcValue); + return DynamicCastResult::SuccessViaCopy; + } + } + + auto destKind = destType->getKind(); + auto srcKind = srcType->getKind(); + + //////////////////////////////////////////////////////////////////////// + // + // 2. Try directly casting the current srcValue to the target type. + // (If the dynamic type is different, try that too.) + // + auto tryCastToDestType = selectCasterForDest(destType); + if (tryCastToDestType == nullptr) { + return DynamicCastResult::Failure; + } + auto castResult = tryCastToDestType(destLocation, destType, srcValue, + srcType, destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + if (isSuccess(castResult)) { + return castResult; + } + if (srcKind == MetadataKind::Class + || srcKind == MetadataKind::ObjCClassWrapper + || srcKind == MetadataKind::ForeignClass) { + auto srcObject = getNonNullSrcObject(srcValue, srcType, destType); + auto srcDynamicType = swift_getObjectType(srcObject); + if (srcDynamicType != srcType) { + srcFailureType = srcDynamicType; + auto castResult = tryCastToDestType( + destLocation, destType, srcValue, srcDynamicType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + if (isSuccess(castResult)) { + return castResult; + } + } + } + + //////////////////////////////////////////////////////////////////////// + // + // 3. Try recursively unwrapping _source_ boxes, including + // existentials, AnyHashable, SwiftValue, and Error. + // + switch (srcKind) { + + case MetadataKind::Class: { +#if !SWIFT_OBJC_INTEROP + // Try unwrapping native __SwiftValue implementation + if (swift_unboxFromSwiftValueWithType(srcValue, destLocation, destType)) { + return DynamicCastResult::SuccessViaCopy; + } +#endif + break; + } + + case MetadataKind::ObjCClassWrapper: { +#if SWIFT_OBJC_INTEROP + // Try unwrapping Obj-C __SwiftValue implementation + auto subcastResult = tryCastUnwrappingObjCSwiftValueSource( + destLocation, destType, srcValue, srcType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + if (isSuccess(subcastResult)) { + return subcastResult; + } +#endif + +#if SWIFT_OBJC_INTEROP + // Try unwrapping Obj-C NSError container + auto innerFlags = DynamicCastFlags::Default; + if (tryDynamicCastNSErrorToValue( + destLocation, srcValue, srcType, destType, innerFlags)) { + return DynamicCastResult::SuccessViaCopy; + } +#endif + break; + } + + case MetadataKind::Struct: { + auto srcStructType = cast(srcType); + auto srcStructDescription = srcStructType->getDescription(); + + // Try unwrapping AnyHashable container + if (srcStructDescription == &STRUCT_TYPE_DESCR_SYM(s11AnyHashable)) { + if (_swift_anyHashableDownCastConditionalIndirect( + srcValue, destLocation, destType)) { + return DynamicCastResult::SuccessViaCopy; + } + } + break; + } + + case MetadataKind::Existential: { + auto subcastResult = tryCastUnwrappingExistentialSource( + destLocation, destType, srcValue, srcType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + if (isSuccess(subcastResult)) { + return subcastResult; + } + break; + } + + default: + break; + } + + //////////////////////////////////////////////////////////////////////// + // + // 4. Try recursively unwrapping Optionals. First try jointly unwrapping + // both source and destination, then just destination, then just source. + // Note that if both are optional, we try all three of these! + // For example, consider casting an Optional to + // Optional. If T conforms, we need to + // unwrap both. But if it doesn't, we unwrap just the destination + // in order to cast Optional to the protocol directly. + // + if (destKind == MetadataKind::Optional) { + if (srcKind == MetadataKind::Optional) { + auto subcastResult = tryCastUnwrappingOptionalBoth( + destLocation, destType, srcValue, srcType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + if (isSuccess(subcastResult)) { + return subcastResult; + } + } + auto subcastResult = tryCastUnwrappingOptionalDestination( + destLocation, destType, srcValue, srcType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + if (isSuccess(subcastResult)) { + return subcastResult; + } + } + + if (srcKind == MetadataKind::Optional) { + auto subcastResult = tryCastUnwrappingOptionalSource( + destLocation, destType, srcValue, srcType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + if (isSuccess(subcastResult)) { + return subcastResult; + } + } + + //////////////////////////////////////////////////////////////////////// + // + // 5. Finally, explore bridging conversions via ObjectiveCBridgeable, + // Error, and __SwiftValue boxing. + // + switch (destKind) { + + case MetadataKind::Optional: { + // Optional supports _ObjectiveCBridgeable from an unconstrained AnyObject + if (srcType->getKind() == MetadataKind::Existential) { + auto srcExistentialType = cast(srcType); + if ((srcExistentialType->getRepresentation() == ExistentialTypeRepresentation::Class) + && (srcExistentialType->NumProtocols == 0) + && (srcExistentialType->getSuperclassConstraint() == nullptr) + && (srcExistentialType->isClassBounded())) { + auto toObjCResult = tryCastFromClassToObjCBridgeable( + destLocation, destType, srcValue, srcType, + destFailureType, srcFailureType, takeOnSuccess, false); + if (isSuccess(toObjCResult)) { + return toObjCResult; + } + } + } + + break; + } + + case MetadataKind::Existential: { + // Try general machinery for stuffing values into AnyObject: + auto destExistentialType = cast(destType); + if (destExistentialType->getRepresentation() == ExistentialTypeRepresentation::Class) { + // Some types have custom Objective-C bridging support... + auto subcastResult = tryCastFromObjCBridgeableToClass( + destLocation, destType, srcValue, srcType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + if (isSuccess(subcastResult)) { + return subcastResult; + } + + // Other types can be boxed into a __SwiftValue container... + auto swiftValueCastResult = tryCastToClassExistentialViaSwiftValue( + destLocation, destType, srcValue, srcType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + if (isSuccess(swiftValueCastResult)) { + return swiftValueCastResult; + } + } + break; + } + + case MetadataKind::Class: + case MetadataKind::ObjCClassWrapper: + case MetadataKind::ForeignClass: { + // Try _ObjectiveCBridgeable to bridge _to_ a class type _from_ a + // struct/enum type. Note: Despite the name, this is used for both + // Swift-Swift and Swift-ObjC bridging + if (srcKind == MetadataKind::Struct || srcKind == MetadataKind::Enum) { + auto subcastResult = tryCastFromObjCBridgeableToClass( + destLocation, destType, srcValue, srcType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + if (isSuccess(subcastResult)) { + return subcastResult; + } + } + +#if SWIFT_OBJC_INTEROP + if (destKind == MetadataKind::ObjCClassWrapper) { + // If the destination type is an NSError or NSObject, and the source type + // is an Error, then the cast might succeed by NSError bridging. + if (auto srcErrorWitness = findErrorWitness(srcType)) { + if (destType == getNSErrorMetadata() + || destType == getNSObjectMetadata()) { + auto flags = DynamicCastFlags::Default; + auto error = dynamicCastValueToNSError(srcValue, srcType, + srcErrorWitness, flags); + *reinterpret_cast(destLocation) = error; + return DynamicCastResult::SuccessViaCopy; + } + } + } +#endif + + break; + } + + case MetadataKind::Struct: + case MetadataKind::Enum: { + // Use _ObjectiveCBridgeable to bridge _from_ a class type _to_ a + // struct/enum type. Note: Despite the name, this is used for both + // Swift-Swift and ObjC-Swift bridging + if (srcKind == MetadataKind::Class + || srcKind == MetadataKind::ObjCClassWrapper + || srcKind == MetadataKind::ForeignClass) { + auto subcastResult = tryCastFromClassToObjCBridgeable( + destLocation, destType, srcValue, srcType, + destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks); + if (isSuccess(subcastResult)) { + return subcastResult; + } + } + + // Note: In theory, if src and dest are both struct/enum types, we could see + // if the ObjC bridgeable class types matched and then do a two-step + // conversion from src -> bridge class -> dest. Such ambitious conversions + // might cause more harm than good, though. In particular, it could + // undermine code that uses a series of `as?` to quickly determine how to + // handle a particular object. + break; + } + + default: + break; + } + + return DynamicCastResult::Failure; +} + +/******************************************************************************/ +/****************************** Main Entrypoint *******************************/ +/******************************************************************************/ + +// XXX REMOVE ME XXX TODO XXX +// Declare the old entrypoint +SWIFT_RUNTIME_EXPORT +bool +swift_dynamicCast_OLD(OpaqueValue *destLocation, + OpaqueValue *srcValue, + const Metadata *srcType, + const Metadata *destType, + DynamicCastFlags flags); +// XXX REMOVE ME XXX TODO XXX + +/// ABI: Perform a dynamic cast to an arbitrary type. +static bool +swift_dynamicCastImpl(OpaqueValue *destLocation, + OpaqueValue *srcValue, + const Metadata *srcType, + const Metadata *destType, + DynamicCastFlags flags) +{ + // XXX REMOVE ME XXX TODO XXX TRANSITION SHIM + // XXX REMOVE ME XXX TODO XXX TRANSITION SHIM + // Support switching to the old implementation while the new one + // is still settling. Once the new implementation is stable, + // I'll rip the old one entirely out. + static bool useOldImplementation = false; // Default: NEW Implementation + static swift_once_t Predicate; + swift_once( + &Predicate, + [](void *) { + // Define SWIFT_OLD_DYNAMIC_CAST_RUNTIME=1 to use the old runtime + // dynamic cast logic. + auto useOld = getenv("SWIFT_OLD_DYNAMIC_CAST_RUNTIME"); + if (useOld) { + useOldImplementation = true; + } + }, nullptr); + if (useOldImplementation) { + return swift_dynamicCast_OLD(destLocation, srcValue, + srcType, destType, flags); + } + // XXX REMOVE ME XXX TODO XXX TRANSITION SHIM + // XXX REMOVE ME XXX TODO XXX TRANSITION SHIM + + // If the compiler has asked for a "take", we can + // move pointers without ref-counting overhead. + bool takeOnSuccess = flags & DynamicCastFlags::TakeOnSuccess; + // Unconditional casts are allowed to crash the program on failure. + // We can exploit that for performance: return a partial conversion + // immediately and do additional checks lazily when the results are + // actually accessed. + bool mayDeferChecks = flags & DynamicCastFlags::Unconditional; + + // Attempt the cast... + const Metadata *destFailureType = destType; + const Metadata *srcFailureType = srcType; + auto result = tryCast( + destLocation, destType, + srcValue, srcType, + destFailureType, srcFailureType, + takeOnSuccess, mayDeferChecks); + + switch (result) { + case DynamicCastResult::Failure: + if (flags & DynamicCastFlags::Unconditional) { + swift_dynamicCastFailure(srcFailureType, destFailureType); + } + if (flags & DynamicCastFlags::DestroyOnFailure) { + srcType->vw_destroy(srcValue); + } + return false; + case DynamicCastResult::SuccessViaCopy: + if (takeOnSuccess) { // We copied, but compiler asked for take. + srcType->vw_destroy(srcValue); + } + return true; + case DynamicCastResult::SuccessViaTake: + return true; + } +} + +#define OVERRIDE_DYNAMICCASTING COMPATIBILITY_OVERRIDE +#include "CompatibilityOverride.def" diff --git a/stdlib/public/runtime/Errors.cpp b/stdlib/public/runtime/Errors.cpp index 6e0dd53758bc9..b5a5e467388cb 100644 --- a/stdlib/public/runtime/Errors.cpp +++ b/stdlib/public/runtime/Errors.cpp @@ -137,7 +137,7 @@ static bool getSymbolNameAddr(llvm::StringRef libraryName, void swift::dumpStackTraceEntry(unsigned index, void *framePC, bool shortOutput) { -#if SWIFT_SUPPORTS_BACKTRACE_REPORTING +#if SWIFT_SUPPORTS_BACKTRACE_REPORTING && !defined(SWIFT_RUNTIME_MACHO_NO_DYLD) SymbolInfo syminfo; // 0 is failure for lookupSymbol diff --git a/stdlib/public/runtime/Exclusivity.cpp b/stdlib/public/runtime/Exclusivity.cpp index f2a6a6e98522b..13ace8a514835 100644 --- a/stdlib/public/runtime/Exclusivity.cpp +++ b/stdlib/public/runtime/Exclusivity.cpp @@ -252,7 +252,14 @@ class SwiftTLSContext { // Each of these cases should define a function with this prototype: // AccessSets &getAllSets(); -#if SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + +static SwiftTLSContext &getTLSContext() { + static SwiftTLSContext TLSContext; + return TLSContext; +} + +#elif SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC // Use the reserved TSD key if possible. static SwiftTLSContext &getTLSContext() { diff --git a/stdlib/public/runtime/HeapObject.cpp b/stdlib/public/runtime/HeapObject.cpp index 50177c633e933..246ac6aa0b14b 100644 --- a/stdlib/public/runtime/HeapObject.cpp +++ b/stdlib/public/runtime/HeapObject.cpp @@ -344,7 +344,11 @@ static HeapObject *_swift_retain_(HeapObject *object) { } HeapObject *swift::swift_retain(HeapObject *object) { +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + return swift_nonatomic_retain(object); +#else CALL_IMPL(swift_retain, (object)); +#endif } SWIFT_RUNTIME_EXPORT @@ -366,7 +370,11 @@ static HeapObject *_swift_retain_n_(HeapObject *object, uint32_t n) { } HeapObject *swift::swift_retain_n(HeapObject *object, uint32_t n) { +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + return swift_nonatomic_retain_n(object, n); +#else CALL_IMPL(swift_retain_n, (object, n)); +#endif } SWIFT_RUNTIME_EXPORT @@ -387,7 +395,11 @@ static void _swift_release_(HeapObject *object) { } void swift::swift_release(HeapObject *object) { +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + swift_nonatomic_release(object); +#else CALL_IMPL(swift_release, (object)); +#endif } SWIFT_RUNTIME_EXPORT @@ -407,7 +419,11 @@ static void _swift_release_n_(HeapObject *object, uint32_t n) { } void swift::swift_release_n(HeapObject *object, uint32_t n) { +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + swift_nonatomic_release_n(object, n); +#else CALL_IMPL(swift_release_n, (object, n)); +#endif } SWIFT_RUNTIME_EXPORT @@ -438,15 +454,22 @@ size_t swift::swift_weakRetainCount(HeapObject *object) { } HeapObject *swift::swift_unownedRetain(HeapObject *object) { +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + return static_cast(swift_nonatomic_unownedRetain(object)); +#else SWIFT_RT_TRACK_INVOCATION(object, swift_unownedRetain); if (!isValidPointerForNativeRetain(object)) return object; object->refCounts.incrementUnowned(1); return object; +#endif } void swift::swift_unownedRelease(HeapObject *object) { +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + swift_nonatomic_unownedRelease(object); +#else SWIFT_RT_TRACK_INVOCATION(object, swift_unownedRelease); if (!isValidPointerForNativeRetain(object)) return; @@ -461,6 +484,7 @@ void swift::swift_unownedRelease(HeapObject *object) { swift_slowDealloc(object, classMetadata->getInstanceSize(), classMetadata->getInstanceAlignMask()); } +#endif } void *swift::swift_nonatomic_unownedRetain(HeapObject *object) { @@ -490,15 +514,22 @@ void swift::swift_nonatomic_unownedRelease(HeapObject *object) { } HeapObject *swift::swift_unownedRetain_n(HeapObject *object, int n) { +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + return swift_nonatomic_unownedRetain_n(object, n); +#else SWIFT_RT_TRACK_INVOCATION(object, swift_unownedRetain_n); if (!isValidPointerForNativeRetain(object)) return object; object->refCounts.incrementUnowned(n); return object; +#endif } void swift::swift_unownedRelease_n(HeapObject *object, int n) { +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + swift_nonatomic_unownedRelease_n(object, n); +#else SWIFT_RT_TRACK_INVOCATION(object, swift_unownedRelease_n); if (!isValidPointerForNativeRetain(object)) return; @@ -512,6 +543,7 @@ void swift::swift_unownedRelease_n(HeapObject *object, int n) { swift_slowDealloc(object, classMetadata->getInstanceSize(), classMetadata->getInstanceAlignMask()); } +#endif } HeapObject *swift::swift_nonatomic_unownedRetain_n(HeapObject *object, int n) { @@ -544,8 +576,13 @@ static HeapObject *_swift_tryRetain_(HeapObject *object) { if (!isValidPointerForNativeRetain(object)) return nullptr; +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + if (object->refCounts.tryIncrementNonAtomic()) return object; + else return nullptr; +#else if (object->refCounts.tryIncrement()) return object; else return nullptr; +#endif } HeapObject *swift::swift_tryRetain(HeapObject *object) { @@ -568,6 +605,9 @@ void swift::swift_setDeallocating(HeapObject *object) { } HeapObject *swift::swift_unownedRetainStrong(HeapObject *object) { +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + return swift_nonatomic_unownedRetainStrong(object); +#else SWIFT_RT_TRACK_INVOCATION(object, swift_unownedRetainStrong); if (!isValidPointerForNativeRetain(object)) return object; @@ -577,6 +617,7 @@ HeapObject *swift::swift_unownedRetainStrong(HeapObject *object) { if (! object->refCounts.tryIncrement()) swift::swift_abortRetainUnowned(object); return object; +#endif } HeapObject *swift::swift_nonatomic_unownedRetainStrong(HeapObject *object) { @@ -592,6 +633,9 @@ HeapObject *swift::swift_nonatomic_unownedRetainStrong(HeapObject *object) { } void swift::swift_unownedRetainStrongAndRelease(HeapObject *object) { +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + swift_nonatomic_unownedRetainStrongAndRelease(object); +#else SWIFT_RT_TRACK_INVOCATION(object, swift_unownedRetainStrongAndRelease); if (!isValidPointerForNativeRetain(object)) return; @@ -605,6 +649,7 @@ void swift::swift_unownedRetainStrongAndRelease(HeapObject *object) { bool dealloc = object->refCounts.decrementUnownedShouldFree(1); assert(!dealloc && "retain-strong-and-release caused dealloc?"); (void) dealloc; +#endif } void swift::swift_nonatomic_unownedRetainStrongAndRelease(HeapObject *object) { diff --git a/stdlib/public/runtime/ImageInspectionCommon.h b/stdlib/public/runtime/ImageInspectionCommon.h index c2004270b3969..eae0ef0f39df5 100644 --- a/stdlib/public/runtime/ImageInspectionCommon.h +++ b/stdlib/public/runtime/ImageInspectionCommon.h @@ -19,7 +19,27 @@ #ifndef SWIFT_RUNTIME_IMAGEINSPECTIONCOMMON_H #define SWIFT_RUNTIME_IMAGEINSPECTIONCOMMON_H -#if !defined(__MACH__) +#if defined(__MACH__) + +#include + +/// The Mach-O section name for the section containing protocol descriptor +/// references. This lives within SEG_TEXT. +#define MachOProtocolsSection "__swift5_protos" +/// The Mach-O section name for the section containing protocol conformances. +/// This lives within SEG_TEXT. +#define MachOProtocolConformancesSection "__swift5_proto" +/// The Mach-O section name for the section containing type references. +/// This lives within SEG_TEXT. +#define MachOTypeMetadataRecordSection "__swift5_types" +/// The Mach-O section name for the section containing dynamic replacements. +/// This lives within SEG_TEXT. +#define MachODynamicReplacementSection "__swift5_replace" +#define MachODynamicReplacementSomeSection "__swift5_replac2" + +#define MachOTextSegment "__TEXT" + +#else #if defined(__ELF__) || defined(__wasm__) #define SWIFT_REFLECTION_METADATA_ELF_NOTE_MAGIC_STRING "swift_reflection_metadata_magic_string" diff --git a/stdlib/public/runtime/ImageInspectionMachO.cpp b/stdlib/public/runtime/ImageInspectionMachO.cpp index 81ee6ed3079da..54c4d17a52a5e 100644 --- a/stdlib/public/runtime/ImageInspectionMachO.cpp +++ b/stdlib/public/runtime/ImageInspectionMachO.cpp @@ -18,9 +18,12 @@ /// //===----------------------------------------------------------------------===// -#if defined(__APPLE__) && defined(__MACH__) +#if defined(__APPLE__) && defined(__MACH__) && \ + !defined(SWIFT_RUNTIME_MACHO_NO_DYLD) #include "ImageInspection.h" +#include "ImageInspectionCommon.h" +#include "swift/Runtime/Config.h" #include #include #include @@ -30,21 +33,17 @@ using namespace swift; namespace { -/// The Mach-O section name for the section containing protocol descriptor -/// references. This lives within SEG_TEXT. -constexpr const char ProtocolsSection[] = "__swift5_protos"; -/// The Mach-O section name for the section containing protocol conformances. -/// This lives within SEG_TEXT. -constexpr const char ProtocolConformancesSection[] = "__swift5_proto"; -/// The Mach-O section name for the section containing type references. -/// This lives within SEG_TEXT. -constexpr const char TypeMetadataRecordSection[] = "__swift5_types"; -/// The Mach-O section name for the section containing dynamic replacements. -/// This lives within SEG_TEXT. -constexpr const char DynamicReplacementSection[] = "__swift5_replace"; -constexpr const char DynamicReplacementSomeSection[] = "__swift5_replac2"; - -constexpr const char TextSegment[] = SEG_TEXT; + +constexpr const char ProtocolsSection[] = MachOProtocolsSection; +constexpr const char ProtocolConformancesSection[] = + MachOProtocolConformancesSection; +constexpr const char TypeMetadataRecordSection[] = + MachOTypeMetadataRecordSection; +constexpr const char DynamicReplacementSection[] = + MachODynamicReplacementSection; +constexpr const char DynamicReplacementSomeSection[] = + MachODynamicReplacementSomeSection; +constexpr const char TextSegment[] = MachOTextSegment; #if __POINTER_WIDTH__ == 64 using mach_header_platform = mach_header_64; @@ -121,7 +120,7 @@ void addImageCallback2Sections(const mach_header *mh, intptr_t vmaddr_slide) { } // end anonymous namespace -#if OBJC_ADDLOADIMAGEFUNC_DEFINED +#if OBJC_ADDLOADIMAGEFUNC_DEFINED && SWIFT_OBJC_INTEROP #define REGISTER_FUNC(...) \ if (__builtin_available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)) { \ objc_addLoadImageFunc(__VA_ARGS__); \ @@ -168,6 +167,8 @@ int swift::lookupSymbol(const void *address, SymbolInfo *info) { return 1; } +#ifndef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES + void *swift::lookupSection(const char *segment, const char *section, size_t *outSize) { unsigned long size; auto *executableHeader = static_cast(_NSGetMachExecuteHeader()); @@ -177,4 +178,7 @@ void *swift::lookupSection(const char *segment, const char *section, size_t *out return static_cast(data); } -#endif // defined(__APPLE__) && defined(__MACH__) +#endif // #ifndef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES + +#endif // defined(__APPLE__) && defined(__MACH__) && + // !defined(SWIFT_RUNTIME_MACHO_NO_DYLD) diff --git a/stdlib/public/runtime/ImageInspectionStatic.cpp b/stdlib/public/runtime/ImageInspectionStatic.cpp new file mode 100644 index 0000000000000..8b95ca01d38b4 --- /dev/null +++ b/stdlib/public/runtime/ImageInspectionStatic.cpp @@ -0,0 +1,78 @@ +//===--- ImageInspectionStatic.cpp - image inspection for static stdlib ---===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// +/// Implementation of ImageInspection for static stdlib (no dynamic loader +/// present) environments. Assumes that only a single image exists in memory. +/// +//===----------------------------------------------------------------------===// + +#if defined(__MACH__) && defined(SWIFT_RUNTIME_MACHO_NO_DYLD) + +#include "ImageInspection.h" +#include "ImageInspectionCommon.h" + +using namespace swift; + +#define GET_SECTION_START_AND_SIZE(start, size, _seg, _sec) \ + extern void *__s##_seg##_sec __asm("section$start$" _seg "$" _sec); \ + extern void *__e##_seg##_sec __asm("section$end$" _seg "$" _sec); \ + start = &__s##_seg##_sec; \ + size = (char *)&__e##_seg##_sec - (char *)&__s##_seg##_sec; + +void swift::initializeProtocolLookup() { + void *start; + uintptr_t size; + GET_SECTION_START_AND_SIZE(start, size, MachOTextSegment, + MachOProtocolsSection); + if (start == nullptr || size == 0) + return; + addImageProtocolsBlockCallbackUnsafe(start, size); +} + +void swift::initializeProtocolConformanceLookup() { + void *start; + uintptr_t size; + GET_SECTION_START_AND_SIZE(start, size, MachOTextSegment, + MachOProtocolConformancesSection); + if (start == nullptr || size == 0) + return; + addImageProtocolConformanceBlockCallbackUnsafe(start, size); +} +void swift::initializeTypeMetadataRecordLookup() { + void *start; + uintptr_t size; + GET_SECTION_START_AND_SIZE(start, size, MachOTextSegment, + MachOTypeMetadataRecordSection); + if (start == nullptr || size == 0) + return; + addImageTypeMetadataRecordBlockCallbackUnsafe(start, size); +} + +void swift::initializeDynamicReplacementLookup() { + void *start1; + uintptr_t size1; + GET_SECTION_START_AND_SIZE(start1, size1, MachOTextSegment, + MachODynamicReplacementSection); + if (start1 == nullptr || size1 == 0) + return; + void *start2; + uintptr_t size2; + GET_SECTION_START_AND_SIZE(start2, size2, MachOTextSegment, + MachODynamicReplacementSection); + if (start2 == nullptr || size2 == 0) + return; + addImageDynamicReplacementBlockCallback(start1, size1, start2, size2); +} + +#endif // defined(__MACH__) && defined(SWIFT_RUNTIME_MACHO_NO_DYLD) diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index a756dc847d56d..a8e9f2a1b81eb 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -49,6 +49,8 @@ #endif #if SWIFT_PTRAUTH #include +#endif +#if SWIFT_OBJC_INTEROP extern "C" void _objc_setClassCopyFixupHandler(void (* _Nonnull newFixupHandler) (Class _Nonnull oldClass, Class _Nonnull newClass)); #endif @@ -395,7 +397,7 @@ static GenericMetadataCache &unsafeGetInitializedCache( return lazyCache->unsafeGetAlreadyInitialized(); } -#if SWIFT_PTRAUTH +#if SWIFT_PTRAUTH && SWIFT_OBJC_INTEROP static void swift_objc_classCopyFixupHandler(Class oldClass, Class newClass) { auto oldClassMetadata = reinterpret_cast(oldClass); @@ -720,26 +722,89 @@ MetadataResponse swift::swift_getCanonicalSpecializedMetadata( auto &cache = getCache(*description); assert(description->getFullGenericContextHeader().Base.NumKeyArguments == cache.NumKeyParameters + cache.NumWitnessTables); + if (auto *classDescription = dyn_cast(description)) { + auto canonicalMetadataAccessors = classDescription->getCanonicalMetadataPrespecializationAccessors(); + for (auto &canonicalMetadataAccessorPtr : canonicalMetadataAccessors) { + auto *canonicalMetadataAccessor = canonicalMetadataAccessorPtr.get(); + auto response = canonicalMetadataAccessor(request); + auto *canonicalMetadata = response.Value; + const void *const *arguments = + reinterpret_cast(canonicalMetadata->getGenericArgs()); + auto key = MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables, + arguments); + auto result = cache.getOrInsert(key, MetadataRequest(MetadataState::Complete, /*isNonBlocking*/true), canonicalMetadata); + assert(result.second.Value == canonicalMetadata); + } + } else { + auto canonicalMetadatas = description->getCanonicicalMetadataPrespecializations(); + for (auto &canonicalMetadataPtr : canonicalMetadatas) { + Metadata *canonicalMetadata = canonicalMetadataPtr.get(); + const void *const *arguments = + reinterpret_cast(canonicalMetadata->getGenericArgs()); + auto key = MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables, + arguments); + auto result = cache.getOrInsert(key, MetadataRequest(MetadataState::Complete, /*isNonBlocking*/true), canonicalMetadata); + assert(result.second.Value == canonicalMetadata); + } + } const void *const *arguments = reinterpret_cast(candidate->getGenericArgs()); auto key = MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables, arguments); auto result = cache.getOrInsert(key, request, candidate); - assert( - !result.second.Value->isCanonicalStaticallySpecializedGenericMetadata()); - cachedMetadataAddr->store(result.second.Value, std::memory_order_release); return result.second; } +// Look into the canonical prespecialized metadata attached to the type +// descriptor and return matching records, if any. +static Metadata * +findCanonicalSpecializedMetadata(MetadataRequest request, + const void *const *arguments, + const TypeContextDescriptor *description) { + auto &cache = getCache(*description); + auto key = MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables, + arguments); + auto prespecializedMetadatas = + description->getCanonicicalMetadataPrespecializations(); + int index = 0; + for (auto &prespecializedMetadataPtr : prespecializedMetadatas) { + Metadata *prespecializationMetadata = prespecializedMetadataPtr.get(); + const void *const *prespecializationArguments = + reinterpret_cast( + prespecializationMetadata->getGenericArgs()); + auto prespecializationKey = + MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables, + prespecializationArguments); + if (key == prespecializationKey) { + if (auto *classDescription = dyn_cast(description)) { + auto canonicalMetadataAccessors = + classDescription->getCanonicalMetadataPrespecializationAccessors(); + auto &canonicalMetadataAccessorPtr = canonicalMetadataAccessors[index]; + auto *canonicalMetadataAccessor = canonicalMetadataAccessorPtr.get(); + auto response = canonicalMetadataAccessor(request); + return const_cast(response.Value); + } else { + return prespecializationMetadata; + } + } + ++index; + } + return nullptr; +} + /// The primary entrypoint. MetadataResponse swift::swift_getGenericMetadata(MetadataRequest request, const void * const *arguments, const TypeContextDescriptor *description) { description = swift_auth_data_non_address(description, SpecialPointerAuthDiscriminators::TypeDescriptor); + if (auto *prespecialization = + findCanonicalSpecializedMetadata(request, arguments, description)) { + return {prespecialization, MetadataState::Complete}; + } auto &cache = getCache(*description); assert(description->getFullGenericContextHeader().Base.NumKeyArguments == cache.NumKeyParameters + cache.NumWitnessTables); @@ -2851,24 +2916,22 @@ getSuperclassMetadata(MetadataRequest request, const ClassMetadata *self) { StringRef superclassName = Demangle::makeSymbolicMangledNameStringRef(superclassNameBase); SubstGenericParametersFromMetadata substitutions(self); - MetadataResponse response = - swift_getTypeByMangledName(request, superclassName, - substitutions.getGenericArgs(), + auto result = swift_getTypeByMangledName( + request, superclassName, substitutions.getGenericArgs(), [&substitutions](unsigned depth, unsigned index) { return substitutions.getMetadata(depth, index); }, [&substitutions](const Metadata *type, unsigned index) { return substitutions.getWitnessTable(type, index); - }).getResponse(); - auto superclass = response.Value; - if (!superclass) { - fatalError(0, - "failed to demangle superclass of %s from mangled name '%s'\n", - self->getDescription()->Name.get(), - superclassName.str().c_str()); + }); + if (auto *error = result.getError()) { + fatalError( + 0, "failed to demangle superclass of %s from mangled name '%s': %s\n", + self->getDescription()->Name.get(), superclassName.str().c_str(), + error->copyErrorString()); } - return response; + return result.getType().getResponse(); } else { return MetadataResponse(); } @@ -4863,12 +4926,12 @@ swift_getAssociatedTypeWitnessSlowImpl( Demangle::makeSymbolicMangledNameStringRef(mangledNameBase); // Demangle the associated type. - MetadataResponse response; + TypeLookupErrorOr result = TypeInfo(); if (inProtocolContext) { // The protocol's Self is the only generic parameter that can occur in the // type. - response = - swift_getTypeByMangledName(request, mangledName, nullptr, + result = swift_getTypeByMangledName( + request, mangledName, nullptr, [conformingType](unsigned depth, unsigned index) -> const Metadata * { if (depth == 0 && index == 0) return conformingType; @@ -4885,7 +4948,7 @@ swift_getAssociatedTypeWitnessSlowImpl( return swift_getAssociatedConformanceWitness(wtable, conformingType, type, reqBase, dependentDescriptor); - }).getResponse(); + }); } else { // The generic parameters in the associated type name are those of the // conforming type. @@ -4895,29 +4958,30 @@ swift_getAssociatedTypeWitnessSlowImpl( auto originalConformingType = findConformingSuperclass(conformingType, conformance); SubstGenericParametersFromMetadata substitutions(originalConformingType); - response = swift_getTypeByMangledName(request, mangledName, - substitutions.getGenericArgs(), - [&substitutions](unsigned depth, unsigned index) { - return substitutions.getMetadata(depth, index); - }, - [&substitutions](const Metadata *type, unsigned index) { - return substitutions.getWitnessTable(type, index); - }).getResponse(); + result = swift_getTypeByMangledName( + request, mangledName, substitutions.getGenericArgs(), + [&substitutions](unsigned depth, unsigned index) { + return substitutions.getMetadata(depth, index); + }, + [&substitutions](const Metadata *type, unsigned index) { + return substitutions.getWitnessTable(type, index); + }); } + auto *error = result.getError(); + MetadataResponse response = result.getType().getResponse(); auto assocTypeMetadata = response.Value; - - if (!assocTypeMetadata) { + if (error || !assocTypeMetadata) { + const char *errStr = error ? error->copyErrorString() + : "NULL metadata but no error was provided"; auto conformingTypeNameInfo = swift_getTypeName(conformingType, true); StringRef conformingTypeName(conformingTypeNameInfo.data, conformingTypeNameInfo.length); StringRef assocTypeName = findAssociatedTypeName(protocol, assocType); fatalError(0, "failed to demangle witness for associated type '%s' in " - "conformance '%s: %s' from mangled name '%s'\n", - assocTypeName.str().c_str(), - conformingTypeName.str().c_str(), - protocol->Name.get(), - mangledName.str().c_str()); + "conformance '%s: %s' from mangled name '%s' - %s\n", + assocTypeName.str().c_str(), conformingTypeName.str().c_str(), + protocol->Name.get(), mangledName.str().c_str(), errStr); } assert((uintptr_t(assocTypeMetadata) & @@ -5870,7 +5934,7 @@ void swift::verifyMangledNameRoundtrip(const Metadata *metadata) { nullptr, [](unsigned, unsigned){ return nullptr; }, [](const Metadata *, unsigned) { return nullptr; }) - .getMetadata(); + .getType().getMetadata(); if (metadata != result) swift::warning(RuntimeErrorFlagNone, "Metadata mangled name failed to roundtrip: %p -> %s -> %p\n", diff --git a/stdlib/public/runtime/MetadataCache.h b/stdlib/public/runtime/MetadataCache.h index 6e471273e4702..d6f188f971e3c 100644 --- a/stdlib/public/runtime/MetadataCache.h +++ b/stdlib/public/runtime/MetadataCache.h @@ -775,10 +775,22 @@ class MetadataCacheEntryBase using super::asImpl; private: + #ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + using ThreadID = int; + static ThreadID CurrentThreadID() { + return 0; + } + #else + using ThreadID = std::thread::id; + static ThreadID CurrentThreadID() { + return std::this_thread::get_id(); + } + #endif + /// Additional storage that is only ever accessed under the lock. union LockedStorage_t { /// The thread that is allocating the entry. - std::thread::id AllocatingThread; + ThreadID AllocatingThread; /// The completion queue. MetadataCompletionQueueEntry *CompletionQueue; @@ -837,7 +849,7 @@ class MetadataCacheEntryBase MetadataCacheEntryBase() : LockedStorageKind(LSK::AllocatingThread), TrackingInfo(PrivateMetadataTrackingInfo::initial().getRawValue()) { - LockedStorage.AllocatingThread = std::this_thread::get_id(); + LockedStorage.AllocatingThread = CurrentThreadID(); } // Note that having an explicit destructor here is important to make this @@ -850,7 +862,7 @@ class MetadataCacheEntryBase bool isBeingAllocatedByCurrentThread() const { return LockedStorageKind == LSK::AllocatingThread && - LockedStorage.AllocatingThread == std::this_thread::get_id(); + LockedStorage.AllocatingThread == CurrentThreadID(); } /// Given that this thread doesn't own the right to initialize the diff --git a/stdlib/public/runtime/MetadataImpl.h b/stdlib/public/runtime/MetadataImpl.h index 1b12fc1000f26..ac455a8cc9938 100644 --- a/stdlib/public/runtime/MetadataImpl.h +++ b/stdlib/public/runtime/MetadataImpl.h @@ -136,7 +136,7 @@ template struct RetainableBoxBase { static constexpr size_t stride = sizeof(T); static constexpr bool isPOD = false; static constexpr bool isBitwiseTakable = true; -#ifdef SWIFT_STDLIB_USE_NONATOMIC_RC +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME static constexpr bool isAtomic = false; #else static constexpr bool isAtomic = true; diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp index 93ed4227928eb..c0c2f7c0c4c9d 100644 --- a/stdlib/public/runtime/MetadataLookup.cpp +++ b/stdlib/public/runtime/MetadataLookup.cpp @@ -961,13 +961,54 @@ getLocalGenericParams(const ContextDescriptor *context) { return genericContext->getGenericParams().slice(startParamIndex); } -static bool +static llvm::Optional _gatherGenericParameters(const ContextDescriptor *context, llvm::ArrayRef genericArgs, const Metadata *parent, llvm::SmallVectorImpl &genericParamCounts, llvm::SmallVectorImpl &allGenericArgsVec, Demangler &demangler) { + auto makeCommonErrorStringGetter = [&] { + auto metadataVector = genericArgs.vec(); + return [=] { + std::string str; + + str += "_gatherGenericParameters: context: "; + + SymbolInfo contextInfo; + if (lookupSymbol(context, &contextInfo)) { + str += contextInfo.symbolName.get(); + str += " "; + } + + char *contextStr; + swift_asprintf(&contextStr, "%p", context); + str += contextStr; + free(contextStr); + + str += " <"; + + bool first = true; + for (const Metadata *metadata : genericArgs) { + if (!first) + str += ", "; + first = false; + str += nameForMetadata(metadata); + } + + str += "> "; + + str += "parent: "; + if (parent) + str += nameForMetadata(parent); + else + str += ""; + str += " - "; + + return str; + }; + }; + // Figure out the various levels of generic parameters we have in // this type. (void)_gatherGenericParameterCounts(context, @@ -981,7 +1022,15 @@ _gatherGenericParameters(const ContextDescriptor *context, } else if (genericArgs.size() == numTotalGenericParams && !parent) { // Okay: genericArgs is the complete set of generic arguments. } else { - return false; + auto commonString = makeCommonErrorStringGetter(); + auto genericArgsSize = genericArgs.size(); + return TypeLookupError([=] { + return commonString() + "incorrect number of generic args (" + + std::to_string(genericArgsSize) + "), " + + std::to_string(getLocalGenericParams(context).size()) + + " local params, " + std::to_string(numTotalGenericParams) + + " total params"; + }); } // If there are generic parameters at any level, check the generic @@ -1008,15 +1057,30 @@ _gatherGenericParameters(const ContextDescriptor *context, auto genericParams = generics->getGenericParams(); unsigned n = genericParams.size(); if (allGenericArgs.size() != n) { - return false; + auto commonString = makeCommonErrorStringGetter(); + auto argsVecSize = allGenericArgsVec.size(); + return TypeLookupError([=] { + return commonString() + "have " + std::to_string(argsVecSize) + + "generic args, expected " + std::to_string(n); + }); } for (unsigned i = 0; i != n; ++i) { const auto ¶m = genericParams[i]; - if (param.getKind() != GenericParamKind::Type) - return false; - if (param.hasExtraArgument()) - return false; - + if (param.getKind() != GenericParamKind::Type) { + auto commonString = makeCommonErrorStringGetter(); + return TypeLookupError([=] { + return commonString() + "param " + std::to_string(i) + + " has unexpected kind " + + std::to_string(static_cast(param.getKind())); + }); + } + if (param.hasExtraArgument()) { + auto commonString = makeCommonErrorStringGetter(); + return TypeLookupError([=] { + return commonString() + "param " + std::to_string(i) + + "has extra argument"; + }); + } if (param.hasKeyArgument()) allGenericArgsVec.push_back(allGenericArgs[i]); } @@ -1028,26 +1092,33 @@ _gatherGenericParameters(const ContextDescriptor *context, // any extra arguments we need for the instantiation function. SubstGenericParametersFromWrittenArgs substitutions(allGenericArgs, genericParamCounts); - bool failed = - _checkGenericRequirements(generics->getGenericRequirements(), - allGenericArgsVec, + auto error = _checkGenericRequirements( + generics->getGenericRequirements(), allGenericArgsVec, [&substitutions](unsigned depth, unsigned index) { return substitutions.getMetadata(depth, index); }, [&substitutions](const Metadata *type, unsigned index) { return substitutions.getWitnessTable(type, index); }); - if (failed) - return false; + if (error) + return *error; // If we still have the wrong number of generic arguments, this is // some kind of metadata mismatch. if (generics->getGenericContextHeader().getNumArguments() != - allGenericArgsVec.size()) - return false; + allGenericArgsVec.size()) { + auto commonString = makeCommonErrorStringGetter(); + auto argsVecSize = allGenericArgsVec.size(); + return TypeLookupError([=] { + return commonString() + "generic argument count mismatch, expected " + + std::to_string( + generics->getGenericContextHeader().getNumArguments()) + + ", have " + std::to_string(argsVecSize); + }); + } } - return true; + return llvm::None; } namespace { @@ -1175,7 +1246,7 @@ class DecodedMetadataBuilder { Demangle::NodeFactory &getNodeFactory() { return demangler; } - BuiltType + TypeLookupErrorOr resolveOpaqueType(NodePointer opaqueDecl, llvm::ArrayRef> genericArgs, unsigned ordinal) { @@ -1193,12 +1264,10 @@ class DecodedMetadataBuilder { llvm::SmallVector genericParamCounts; llvm::SmallVector allGenericArgsVec; - if (!_gatherGenericParameters(outerContext, - allGenericArgs, - BuiltType(), /* no parent */ - genericParamCounts, allGenericArgsVec, - demangler)) - return BuiltType(); + if (auto error = _gatherGenericParameters( + outerContext, allGenericArgs, BuiltType(), /* no parent */ + genericParamCounts, allGenericArgsVec, demangler)) + return *error; auto mangledName = descriptor->getUnderlyingTypeArgument(ordinal); SubstGenericParametersFromMetadata substitutions(descriptor, @@ -1210,7 +1279,7 @@ class DecodedMetadataBuilder { }, [&substitutions](const Metadata *type, unsigned index) { return substitutions.getWitnessTable(type, index); - }).getMetadata(); + }).getType().getMetadata(); } BuiltTypeDecl createTypeDecl(NodePointer node, @@ -1245,8 +1314,9 @@ class DecodedMetadataBuilder { return ProtocolDescriptorRef(); #endif } - - BuiltType createObjCClassType(const std::string &mangledName) const { + + TypeLookupErrorOr + createObjCClassType(const std::string &mangledName) const { #if SWIFT_OBJC_INTEROP auto objcClass = objc_getClass(mangledName.c_str()); return swift_getObjCClassMetadata((const ClassMetadata *)objcClass); @@ -1255,7 +1325,7 @@ class DecodedMetadataBuilder { #endif } - BuiltType + TypeLookupErrorOr createBoundGenericObjCClassType(const std::string &mangledName, llvm::ArrayRef args) const { // Generic arguments of lightweight Objective-C generic classes are not @@ -1263,24 +1333,25 @@ class DecodedMetadataBuilder { return createObjCClassType(mangledName); } - BuiltType createNominalType(BuiltTypeDecl metadataOrTypeDecl, - BuiltType parent) const { + TypeLookupErrorOr + createNominalType(BuiltTypeDecl metadataOrTypeDecl, BuiltType parent) const { // Treat nominal type creation the same way as generic type creation, // but with no generic arguments at this level. return createBoundGenericType(metadataOrTypeDecl, { }, parent); } - BuiltType createTypeAliasType(BuiltTypeDecl typeAliasDecl, - BuiltType parent) const { + TypeLookupErrorOr createTypeAliasType(BuiltTypeDecl typeAliasDecl, + BuiltType parent) const { // We can't support sugared types here since we have no way to // resolve the underlying type of the type alias. However, some // CF types are mangled as type aliases. return createNominalType(typeAliasDecl, parent); } - BuiltType createBoundGenericType(BuiltTypeDecl anyTypeDecl, - llvm::ArrayRef genericArgs, - BuiltType parent) const { + TypeLookupErrorOr + createBoundGenericType(BuiltTypeDecl anyTypeDecl, + llvm::ArrayRef genericArgs, + BuiltType parent) const { auto typeDecl = dyn_cast(anyTypeDecl); if (!typeDecl) { if (auto protocol = dyn_cast(anyTypeDecl)) @@ -1294,13 +1365,11 @@ class DecodedMetadataBuilder { llvm::SmallVector genericParamCounts; llvm::SmallVector allGenericArgsVec; - if (!_gatherGenericParameters(typeDecl, - genericArgs, - parent, - genericParamCounts, allGenericArgsVec, - demangler)) - return BuiltType(); - + if (auto error = _gatherGenericParameters(typeDecl, genericArgs, parent, + genericParamCounts, + allGenericArgsVec, demangler)) + return *error; + // Call the access function. auto accessFunction = typeDecl->getAccessFunction(); if (!accessFunction) return BuiltType(); @@ -1308,8 +1377,8 @@ class DecodedMetadataBuilder { return accessFunction(MetadataState::Abstract, allGenericArgsVec).Value; } - BuiltType createBuiltinType(StringRef builtinName, - StringRef mangledName) const { + TypeLookupErrorOr createBuiltinType(StringRef builtinName, + StringRef mangledName) const { #define BUILTIN_TYPE(Symbol, _) \ if (mangledName.equals(#Symbol)) \ return &METADATA_SYM(Symbol).base; @@ -1317,19 +1386,19 @@ class DecodedMetadataBuilder { return BuiltType(); } - BuiltType createMetatypeType( + TypeLookupErrorOr createMetatypeType( BuiltType instance, llvm::Optional repr = None) const { return swift_getMetatypeMetadata(instance); } - BuiltType createExistentialMetatypeType( + TypeLookupErrorOr createExistentialMetatypeType( BuiltType instance, llvm::Optional repr = None) const { return swift_getExistentialMetatypeMetadata(instance); } - BuiltType + TypeLookupErrorOr createProtocolCompositionType(llvm::ArrayRef protocols, BuiltType superclass, bool isClassBound) const { // Determine whether we have a class bound. @@ -1349,13 +1418,13 @@ class DecodedMetadataBuilder { protocols.size(), protocols.data()); } - BuiltType createDynamicSelfType(BuiltType selfType) const { + TypeLookupErrorOr createDynamicSelfType(BuiltType selfType) const { // Free-standing mangled type strings should not contain DynamicSelfType. return BuiltType(); } - BuiltType createGenericTypeParameterType(unsigned depth, - unsigned index) const { + TypeLookupErrorOr + createGenericTypeParameterType(unsigned depth, unsigned index) const { // Use the callback, when provided. if (substGenericParameter) return substGenericParameter(depth, index); @@ -1363,7 +1432,7 @@ class DecodedMetadataBuilder { return BuiltType(); } - BuiltType + TypeLookupErrorOr createFunctionType(llvm::ArrayRef> params, BuiltType result, FunctionTypeFlags flags) const { llvm::SmallVector paramTypes; @@ -1386,7 +1455,7 @@ class DecodedMetadataBuilder { result); } - BuiltType createImplFunctionType( + TypeLookupErrorOr createImplFunctionType( Demangle::ImplParameterConvention calleeConvention, llvm::ArrayRef> params, llvm::ArrayRef> results, @@ -1396,8 +1465,9 @@ class DecodedMetadataBuilder { return BuiltType(); } - BuiltType createTupleType(llvm::ArrayRef elements, - std::string labels) const { + TypeLookupErrorOr + createTupleType(llvm::ArrayRef elements, + std::string labels) const { auto flags = TupleTypeFlags().withNumElements(elements.size()); if (!labels.empty()) flags = flags.withNonConstantLabels(true); @@ -1408,13 +1478,15 @@ class DecodedMetadataBuilder { .Value; } - BuiltType createDependentMemberType(StringRef name, BuiltType base) const { + TypeLookupErrorOr createDependentMemberType(StringRef name, + BuiltType base) const { // Should not have unresolved dependent member types here. return BuiltType(); } - BuiltType createDependentMemberType(StringRef name, BuiltType base, - BuiltProtocolDecl protocol) const { + TypeLookupErrorOr + createDependentMemberType(StringRef name, BuiltType base, + BuiltProtocolDecl protocol) const { #if SWIFT_OBJC_INTEROP if (protocol.isObjC()) return BuiltType(); @@ -1438,14 +1510,14 @@ class DecodedMetadataBuilder { *assocType).Value; } -#define REF_STORAGE(Name, ...) \ - BuiltType create##Name##StorageType(BuiltType base) { \ - ReferenceOwnership.set##Name(); \ - return base; \ +#define REF_STORAGE(Name, ...) \ + TypeLookupErrorOr create##Name##StorageType(BuiltType base) { \ + ReferenceOwnership.set##Name(); \ + return base; \ } #include "swift/AST/ReferenceStorage.def" - BuiltType createSILBoxType(BuiltType base) const { + TypeLookupErrorOr createSILBoxType(BuiltType base) const { // FIXME: Implement. return BuiltType(); } @@ -1454,22 +1526,23 @@ class DecodedMetadataBuilder { return ReferenceOwnership; } - BuiltType createOptionalType(BuiltType base) { + TypeLookupErrorOr createOptionalType(BuiltType base) { // Mangled types for building metadata don't contain sugared types return BuiltType(); } - BuiltType createArrayType(BuiltType base) { + TypeLookupErrorOr createArrayType(BuiltType base) { // Mangled types for building metadata don't contain sugared types return BuiltType(); } - BuiltType createDictionaryType(BuiltType key, BuiltType value) { + TypeLookupErrorOr createDictionaryType(BuiltType key, + BuiltType value) { // Mangled types for building metadata don't contain sugared types return BuiltType(); } - BuiltType createParenType(BuiltType base) { + TypeLookupErrorOr createParenType(BuiltType base) { // Mangled types for building metadata don't contain sugared types return BuiltType(); } @@ -1478,13 +1551,12 @@ class DecodedMetadataBuilder { } SWIFT_CC(swift) -static TypeInfo swift_getTypeByMangledNodeImpl( - MetadataRequest request, - Demangler &demangler, - Demangle::NodePointer node, - const void * const *origArgumentVector, - SubstGenericParameterFn substGenericParam, - SubstDependentWitnessTableFn substWitnessTable) { +static TypeLookupErrorOr +swift_getTypeByMangledNodeImpl(MetadataRequest request, Demangler &demangler, + Demangle::NodePointer node, + const void *const *origArgumentVector, + SubstGenericParameterFn substGenericParam, + SubstDependentWitnessTableFn substWitnessTable) { // Simply call an accessor function if that's all we got. if (node->getKind() == Node::Kind::AccessorFunctionReference) { // The accessor function is passed the pointer to the original argument @@ -1504,22 +1576,23 @@ static TypeInfo swift_getTypeByMangledNodeImpl( DecodedMetadataBuilder builder(demangler, substGenericParam, substWitnessTable); auto type = Demangle::decodeMangledType(builder, node); - if (!type) { - return {MetadataResponse{nullptr, MetadataState::Complete}, - TypeReferenceOwnership()}; + if (type.isError()) { + return *type.getError(); + } + if (!type.getType()) { + return TypeLookupError("NULL type but no error provided"); } - return {swift_checkMetadataState(request, type), - builder.getReferenceOwnership()}; + return TypeInfo{swift_checkMetadataState(request, type.getType()), + builder.getReferenceOwnership()}; } SWIFT_CC(swift) -static TypeInfo swift_getTypeByMangledNameImpl( - MetadataRequest request, - StringRef typeName, - const void * const *origArgumentVector, - SubstGenericParameterFn substGenericParam, - SubstDependentWitnessTableFn substWitnessTable) { +static TypeLookupErrorOr +swift_getTypeByMangledNameImpl(MetadataRequest request, StringRef typeName, + const void *const *origArgumentVector, + SubstGenericParameterFn substGenericParam, + SubstDependentWitnessTableFn substWitnessTable) { DemanglerForRuntimeTypeResolution> demangler; NodePointer node; @@ -1587,7 +1660,7 @@ swift_getTypeByMangledNameInEnvironment( }, [&substitutions](const Metadata *type, unsigned index) { return substitutions.getWitnessTable(type, index); - }).getMetadata(); + }).getType().getMetadata(); } SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT @@ -1607,7 +1680,7 @@ swift_getTypeByMangledNameInEnvironmentInMetadataState( }, [&substitutions](const Metadata *type, unsigned index) { return substitutions.getWitnessTable(type, index); - }).getMetadata(); + }).getType().getMetadata(); } SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT @@ -1626,7 +1699,7 @@ swift_getTypeByMangledNameInContext( }, [&substitutions](const Metadata *type, unsigned index) { return substitutions.getWitnessTable(type, index); - }).getMetadata(); + }).getType().getMetadata(); } SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT @@ -1646,7 +1719,7 @@ swift_getTypeByMangledNameInContextInMetadataState( }, [&substitutions](const Metadata *type, unsigned index) { return substitutions.getWitnessTable(type, index); - }).getMetadata(); + }).getType().getMetadata(); } /// Demangle a mangled name, but don't allow symbolic references. @@ -1661,7 +1734,7 @@ swift_stdlib_getTypeByMangledNameUntrusted(const char *typeNameStart, } return swift_getTypeByMangledName(MetadataState::Complete, typeName, nullptr, - {}, {}).getMetadata(); + {}, {}).getType().getMetadata(); } SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT @@ -1680,7 +1753,7 @@ swift_getOpaqueTypeMetadata(MetadataRequest request, }, [&substitutions](const Metadata *type, unsigned index) { return substitutions.getWitnessTable(type, index); - }).getResponse(); + }).getType().getResponse(); } SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT @@ -1735,7 +1808,7 @@ getObjCClassByMangledName(const char * _Nonnull typeName, }, [&](const Metadata *type, unsigned index) { return nullptr; - }).getMetadata(); + }).getType().getMetadata(); } else { metadata = swift_stdlib_getTypeByMangledNameUntrusted(typeStr.data(), typeStr.size()); @@ -2068,7 +2141,7 @@ void swift::gatherWrittenGenericArgs( }, [&substitutions](const Metadata *type, unsigned index) { return substitutions.getWitnessTable(type, index); - }).getMetadata(); + }).getType().getMetadata(); continue; } diff --git a/stdlib/public/runtime/MutexPThread.cpp b/stdlib/public/runtime/MutexPThread.cpp index 92db58226cd09..ac7f93a5a0ed8 100644 --- a/stdlib/public/runtime/MutexPThread.cpp +++ b/stdlib/public/runtime/MutexPThread.cpp @@ -15,7 +15,11 @@ // //===----------------------------------------------------------------------===// -#if !defined(_WIN32) && !defined(__wasi__) +#if __has_include() +#include +#endif + +#if defined(_POSIX_THREADS) && !defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME) #include "swift/Runtime/Mutex.h" #include "swift/Runtime/Debug.h" diff --git a/stdlib/public/runtime/MutexWASI.cpp b/stdlib/public/runtime/MutexWASI.cpp index 6288ecce03449..e62f54c107483 100644 --- a/stdlib/public/runtime/MutexWASI.cpp +++ b/stdlib/public/runtime/MutexWASI.cpp @@ -20,6 +20,6 @@ using namespace swift; -void ConditionPlatformHelper::wait(void* &condition, - void* &mutex) {} +void ConditionPlatformHelper::wait(ConditionHandle &condition, + MutexHandle &mutex) {} #endif diff --git a/stdlib/public/runtime/Once.cpp b/stdlib/public/runtime/Once.cpp index 7554d5d4ae751..84403f7825586 100644 --- a/stdlib/public/runtime/Once.cpp +++ b/stdlib/public/runtime/Once.cpp @@ -21,7 +21,11 @@ using namespace swift; -#ifdef __APPLE__ +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + +// No dependencies on single-threaded environments. + +#elif defined(__APPLE__) // On macOS and iOS, swift_once is implemented using GCD. // The compiler emits an inline check matching the barrier-free inline fast @@ -48,7 +52,12 @@ static_assert(sizeof(swift_once_t) <= sizeof(void*), /// extent of type swift_once_t. void swift::swift_once(swift_once_t *predicate, void (*fn)(void *), void *context) { -#if defined(__APPLE__) +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + if (! *predicate) { + *predicate = true; + fn(context); + } +#elif defined(__APPLE__) dispatch_once_f(predicate, context, fn); #elif defined(__CYGWIN__) _swift_once_f(predicate, context, fn); diff --git a/stdlib/public/runtime/Private.h b/stdlib/public/runtime/Private.h index 4be3fb6bdb025..2f5e7232cc55d 100644 --- a/stdlib/public/runtime/Private.h +++ b/stdlib/public/runtime/Private.h @@ -17,7 +17,10 @@ #ifndef SWIFT_RUNTIME_PRIVATE_H #define SWIFT_RUNTIME_PRIVATE_H +#include + #include "swift/Demangling/Demangler.h" +#include "swift/Demangling/TypeLookupError.h" #include "swift/Runtime/Config.h" #include "swift/Runtime/Metadata.h" @@ -77,6 +80,8 @@ class TypeInfo { const Metadata *getMetadata() const { return Response.Value; } MetadataResponse getResponse() const { return Response; } + operator bool() const { return getMetadata(); } + #define REF_STORAGE(Name, ...) \ bool is##Name() const { return ReferenceOwnership.is##Name(); } #include "swift/AST/ReferenceStorage.def" @@ -211,7 +216,7 @@ class TypeInfo { static inline bool objectUsesNativeSwiftReferenceCounting(const void *object) { assert(!isObjCTaggedPointerOrNull(object)); -#if SWIFT_HAS_OPAQUE_ISAS +#if SWIFT_OBJC_INTEROP && SWIFT_HAS_OPAQUE_ISAS // Fast path for opaque ISAs. We don't want to call // _swift_getClassOfAllocated as that will call object_getClass. // Instead we can look at the bits in the ISA and tell if its a @@ -369,7 +374,7 @@ class TypeInfo { /// \p substWitnessTable Function that provides witness tables given a /// particular dependent conformance index. SWIFT_CC(swift) - TypeInfo swift_getTypeByMangledNode( + TypeLookupErrorOr swift_getTypeByMangledNode( MetadataRequest request, Demangler &demangler, Demangle::NodePointer node, @@ -384,7 +389,7 @@ class TypeInfo { /// \p substWitnessTable Function that provides witness tables given a /// particular dependent conformance index. SWIFT_CC(swift) - TypeInfo swift_getTypeByMangledName( + TypeLookupErrorOr swift_getTypeByMangledName( MetadataRequest request, StringRef typeName, const void * const *arguments, @@ -447,12 +452,12 @@ class TypeInfo { /// generic requirements (e.g., those that need to be /// passed to an instantiation function) will be added to this vector. /// - /// \returns true if an error occurred, false otherwise. - bool _checkGenericRequirements( - llvm::ArrayRef requirements, - llvm::SmallVectorImpl &extraArguments, - SubstGenericParameterFn substGenericParam, - SubstDependentWitnessTableFn substWitnessTable); + /// \returns the error if an error occurred, None otherwise. + llvm::Optional _checkGenericRequirements( + llvm::ArrayRef requirements, + llvm::SmallVectorImpl &extraArguments, + SubstGenericParameterFn substGenericParam, + SubstDependentWitnessTableFn substWitnessTable); /// A helper function which avoids performing a store if the destination /// address already contains the source value. This is useful when diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp index 1a80b2e08e039..c434011faea85 100644 --- a/stdlib/public/runtime/ProtocolConformance.cpp +++ b/stdlib/public/runtime/ProtocolConformance.cpp @@ -165,15 +165,16 @@ ProtocolConformanceDescriptor::getWitnessTable(const Metadata *type) const { llvm::SmallVector conditionalArgs; if (hasConditionalRequirements()) { SubstGenericParametersFromMetadata substitutions(type); - bool failed = - _checkGenericRequirements(getConditionalRequirements(), conditionalArgs, + auto error = _checkGenericRequirements( + getConditionalRequirements(), conditionalArgs, [&substitutions](unsigned depth, unsigned index) { return substitutions.getMetadata(depth, index); }, [&substitutions](const Metadata *type, unsigned index) { return substitutions.getWitnessTable(type, index); }); - if (failed) return nullptr; + if (error) + return nullptr; } return swift_getWitnessTable(this, type, conditionalArgs.data()); @@ -198,31 +199,27 @@ namespace { : Type(type), Proto(proto) { assert(type); } + + friend llvm::hash_code hash_value(const ConformanceCacheKey &key) { + return llvm::hash_combine(key.Type, key.Proto); + } }; struct ConformanceCacheEntry { private: - const Metadata *Type; - const ProtocolDescriptor *Proto; - std::atomic Description; - std::atomic FailureGeneration; + ConformanceCacheKey Key; + const WitnessTable *Witness; public: - ConformanceCacheEntry(ConformanceCacheKey key, - const ProtocolConformanceDescriptor *description, - size_t failureGeneration) - : Type(key.Type), Proto(key.Proto), Description(description), - FailureGeneration(failureGeneration) { + ConformanceCacheEntry(ConformanceCacheKey key, const WitnessTable *witness) + : Key(key), Witness(witness) {} + + bool matchesKey(const ConformanceCacheKey &key) const { + return Key.Type == key.Type && Key.Proto == key.Proto; } - int compareWithKey(const ConformanceCacheKey &key) const { - if (key.Type != Type) { - return (uintptr_t(key.Type) < uintptr_t(Type) ? -1 : 1); - } else if (key.Proto != Proto) { - return (uintptr_t(key.Proto) < uintptr_t(Proto) ? -1 : 1); - } else { - return 0; - } + friend llvm::hash_code hash_value(const ConformanceCacheEntry &entry) { + return hash_value(entry.Key); } template @@ -230,69 +227,54 @@ namespace { return 0; } - bool isSuccessful() const { - return Description.load(std::memory_order_relaxed) != nullptr; - } - - void makeSuccessful(const ProtocolConformanceDescriptor *description) { - Description.store(description, std::memory_order_release); - } - - void updateFailureGeneration(size_t failureGeneration) { - assert(!isSuccessful()); - FailureGeneration.store(failureGeneration, std::memory_order_relaxed); - } - - /// Get the cached conformance descriptor, if successful. - const ProtocolConformanceDescriptor *getDescription() const { - assert(isSuccessful()); - return Description.load(std::memory_order_acquire); - } - - /// Get the generation in which this lookup failed. - size_t getFailureGeneration() const { - assert(!isSuccessful()); - return FailureGeneration.load(std::memory_order_relaxed); + /// Get the cached witness table, or null if we cached failure. + const WitnessTable *getWitnessTable() const { + return Witness; } }; } // end anonymous namespace // Conformance Cache. struct ConformanceState { - ConcurrentMap Cache; + ConcurrentReadableHashMap Cache; ConcurrentReadableArray SectionsToScan; ConformanceState() { initializeProtocolConformanceLookup(); } - void cacheSuccess(const Metadata *type, const ProtocolDescriptor *proto, - const ProtocolConformanceDescriptor *description) { - auto result = Cache.getOrInsert(ConformanceCacheKey(type, proto), - description, 0); - - // If the entry was already present, we may need to update it. - if (!result.second) { - result.first->makeSuccessful(description); - } - } - - void cacheFailure(const Metadata *type, const ProtocolDescriptor *proto, - size_t failureGeneration) { - auto result = - Cache.getOrInsert(ConformanceCacheKey(type, proto), - (const ProtocolConformanceDescriptor *) nullptr, - failureGeneration); - - // If the entry was already present, we may need to update it. - if (!result.second) { - result.first->updateFailureGeneration(failureGeneration); - } - } - - ConformanceCacheEntry *findCached(const Metadata *type, - const ProtocolDescriptor *proto) { - return Cache.find(ConformanceCacheKey(type, proto)); + void cacheResult(const Metadata *type, const ProtocolDescriptor *proto, + const WitnessTable *witness, size_t sectionsCount) { + Cache.getOrInsert(ConformanceCacheKey(type, proto), + [&](ConformanceCacheEntry *entry, bool created) { + // Create the entry if needed. If it already exists, + // we're done. + if (!created) + return false; + + // Check the current sections count against what was + // passed in. If a section count was passed in and they + // don't match, then this is not an authoritative entry + // and it may have been obsoleted, because the new + // sections could contain a conformance in a more + // specific type. + // + // If they DO match, then we can safely add. Another + // thread might be adding new sections at this point, + // but we will not race with them. That other thread + // will add the new sections, then clear the cache. When + // it clears the cache, it will block waiting for this + // code to complete and relinquish Cache's writer lock. + // If we cache a stale entry, it will be immediately + // cleared. + if (sectionsCount > 0 && + SectionsToScan.snapshot().count() != sectionsCount) + return false; // abandon the new entry + + new (entry) ConformanceCacheEntry( + ConformanceCacheKey(type, proto), witness); + return true; // keep the new entry + }); } #ifndef NDEBUG @@ -323,6 +305,10 @@ _registerProtocolConformances(ConformanceState &C, const ProtocolConformanceRecord *begin, const ProtocolConformanceRecord *end) { C.SectionsToScan.push_back(ConformanceSection{begin, end}); + + // Blow away the conformances cache to get rid of any negative entries that + // may now be obsolete. + C.Cache.clear(); } void swift::addImageProtocolConformanceBlockCallbackUnsafe( @@ -357,98 +343,29 @@ swift::swift_registerProtocolConformances(const ProtocolConformanceRecord *begin _registerProtocolConformances(C, begin, end); } - -struct ConformanceCacheResult { - // true if description is an authoritative result as-is. - // false if more searching is required (for example, because a cached - // failure was returned in failureEntry but it is out-of-date. - bool isAuthoritative; - - // The matching conformance descriptor, or null if no cached conformance - // was found. - const ProtocolConformanceDescriptor *description; - - // If the search fails, this may be the negative cache entry for the - // queried type itself. This entry may be null or out-of-date. - ConformanceCacheEntry *failureEntry; - - static ConformanceCacheResult - cachedSuccess(const ProtocolConformanceDescriptor *description) { - return ConformanceCacheResult { true, description, nullptr }; - } - - static ConformanceCacheResult - cachedFailure(ConformanceCacheEntry *entry, bool auth) { - return ConformanceCacheResult { auth, nullptr, entry }; - } - - static ConformanceCacheResult - cacheMiss() { - return ConformanceCacheResult { false, nullptr, nullptr }; - } -}; - /// Search for a conformance descriptor in the ConformanceCache. -static -ConformanceCacheResult +/// First element of the return value is `true` if the result is authoritative +/// i.e. the result is for the type itself and not a superclass. If `false` +/// then we cached a conformance on a superclass, but that may be overridden. +/// A return value of `{ false, nullptr }` indicates nothing was cached. +static std::pair searchInConformanceCache(const Metadata *type, const ProtocolDescriptor *protocol) { auto &C = Conformances.get(); auto origType = type; - ConformanceCacheEntry *failureEntry = nullptr; - -recur: - { - // Try the specific type first. - if (auto *Value = C.findCached(type, protocol)) { - if (Value->isSuccessful()) { - // Found a conformance on the type or some superclass. Return it. - return ConformanceCacheResult::cachedSuccess(Value->getDescription()); - } - - // Found a negative cache entry. - - bool isAuthoritative; - if (type == origType) { - // This negative cache entry is for the original query type. - // Remember it so it can be returned later. - failureEntry = Value; - // An up-to-date entry for the original type is authoritative. - isAuthoritative = true; - } else { - // An up-to-date cached failure for a superclass of the type is not - // authoritative: there may be a still-undiscovered conformance - // for the original query type. - isAuthoritative = false; - } + auto snapshot = C.Cache.snapshot(); - // Check if the negative cache entry is up-to-date. - if (Value->getFailureGeneration() == C.SectionsToScan.snapshot().count()) { - // Negative cache entry is up-to-date. Return failure along with - // the original query type's own cache entry, if we found one. - // (That entry may be out of date but the caller still has use for it.) - return ConformanceCacheResult::cachedFailure(failureEntry, - isAuthoritative); - } - - // Negative cache entry is out-of-date. - // Continue searching for a better result. + while (type) { + if (auto *Value = snapshot.find(ConformanceCacheKey(type, protocol))) { + return {type == origType, Value->getWitnessTable()}; } - } - // If there is a superclass, look there. - if (auto superclass = _swift_class_getSuperclass(type)) { - type = superclass; - goto recur; + // If there is a superclass, look there. + type = _swift_class_getSuperclass(type); } - // We did not find an up-to-date cache entry. - // If we found an out-of-date entry for the original query type then - // return it (non-authoritatively). Otherwise return a cache miss. - if (failureEntry) - return ConformanceCacheResult::cachedFailure(failureEntry, false); - else - return ConformanceCacheResult::cacheMiss(); + // We did not find a cache entry. + return {false, nullptr}; } namespace { @@ -477,14 +394,6 @@ namespace { } } - /// Retrieve the conforming type as metadata, or NULL if the candidate's - /// conforming type is described in another way (e.g., a nominal type - /// descriptor). - const Metadata *getConformingTypeAsMetadata() const { - return candidateIsMetadata ? static_cast(candidate) - : nullptr; - } - const ContextDescriptor * getContextDescriptor(const Metadata *conformingType) const { const auto *description = conformingType->getTypeContextDescriptor(); @@ -544,40 +453,21 @@ namespace { }; } -static const ProtocolConformanceDescriptor * -swift_conformsToSwiftProtocolImpl(const Metadata * const type, - const ProtocolDescriptor *protocol, - StringRef module) { +static const WitnessTable * +swift_conformsToProtocolImpl(const Metadata *const type, + const ProtocolDescriptor *protocol) { auto &C = Conformances.get(); - // See if we have a cached conformance. The ConcurrentMap data structure - // allows us to insert and search the map concurrently without locking. - auto FoundConformance = searchInConformanceCache(type, protocol); - // If the result (positive or negative) is authoritative, return it. - if (FoundConformance.isAuthoritative) - return FoundConformance.description; - - auto failureEntry = FoundConformance.failureEntry; + // See if we have an authoritative cached conformance. The + // ConcurrentReadableHashMap data structure allows us to search the map + // concurrently without locking. + auto found = searchInConformanceCache(type, protocol); + if (found.first) + return found.second; - // Prepare to scan conformance records. + // Scan conformance records. auto snapshot = C.SectionsToScan.snapshot(); - - // Scan only sections that were not scanned yet. - // If we found an out-of-date negative cache entry, - // we need not to re-scan the sections that it covers. - auto startIndex = failureEntry ? failureEntry->getFailureGeneration() : 0; - auto endIndex = snapshot.count(); - - // If there are no unscanned sections outstanding - // then we can cache failure and give up now. - if (startIndex == endIndex) { - C.cacheFailure(type, protocol, snapshot.count()); - return nullptr; - } - - // Really scan conformance records. - for (size_t i = startIndex; i < endIndex; ++i) { - auto §ion = snapshot.Start[i]; + for (auto §ion : snapshot) { // Eagerly pull records for nondependent witnesses into our cache. for (const auto &record : section) { auto &descriptor = *record.get(); @@ -586,40 +476,25 @@ swift_conformsToSwiftProtocolImpl(const Metadata * const type, if (descriptor.getProtocol() != protocol) continue; - // If there's a matching type, record the positive result. + // If there's a matching type, record the positive result and return it. + // The matching type is exact, so they can't go stale, and we should + // always cache them. ConformanceCandidate candidate(descriptor); - if (candidate.getMatchingType(type)) { - const Metadata *matchingType = candidate.getConformingTypeAsMetadata(); - if (!matchingType) - matchingType = type; - - C.cacheSuccess(matchingType, protocol, &descriptor); + if (auto *matchingType = candidate.getMatchingType(type)) { + auto witness = descriptor.getWitnessTable(matchingType); + C.cacheResult(matchingType, protocol, witness, /*always cache*/ 0); } } } - - // Conformance scan is complete. - - // Search the cache once more, and this time update the cache if necessary. - FoundConformance = searchInConformanceCache(type, protocol); - if (FoundConformance.isAuthoritative) { - return FoundConformance.description; - } else { - C.cacheFailure(type, protocol, snapshot.count()); - return nullptr; - } -} -static const WitnessTable * -swift_conformsToProtocolImpl(const Metadata * const type, - const ProtocolDescriptor *protocol) { - auto description = - swift_conformsToSwiftProtocol(type, protocol, StringRef()); - if (!description) - return nullptr; + // Try the search again to look for the most specific cached conformance. + found = searchInConformanceCache(type, protocol); + + // If it's not authoritative, then add an authoritative entry for this type. + if (!found.first) + C.cacheResult(type, protocol, found.second, snapshot.count()); - return description->getWitnessTable( - findConformingSuperclass(type, description)); + return found.second; } const ContextDescriptor * @@ -768,31 +643,36 @@ static bool isSubclass(const Metadata *subclass, const Metadata *superclass) { }); } -bool swift::_checkGenericRequirements( - llvm::ArrayRef requirements, - llvm::SmallVectorImpl &extraArguments, - SubstGenericParameterFn substGenericParam, - SubstDependentWitnessTableFn substWitnessTable) { +llvm::Optional swift::_checkGenericRequirements( + llvm::ArrayRef requirements, + llvm::SmallVectorImpl &extraArguments, + SubstGenericParameterFn substGenericParam, + SubstDependentWitnessTableFn substWitnessTable) { for (const auto &req : requirements) { // Make sure we understand the requirement we're dealing with. - if (!req.hasKnownKind()) return true; + if (!req.hasKnownKind()) + return TypeLookupError("unknown kind"); // Resolve the subject generic parameter. - const Metadata *subjectType = - swift_getTypeByMangledName(MetadataState::Abstract, - req.getParam(), - extraArguments.data(), - substGenericParam, substWitnessTable).getMetadata(); - if (!subjectType) - return true; + auto result = swift_getTypeByMangledName( + MetadataState::Abstract, req.getParam(), extraArguments.data(), + substGenericParam, substWitnessTable); + if (result.getError()) + return *result.getError(); + const Metadata *subjectType = result.getType().getMetadata(); // Check the requirement. switch (req.getKind()) { case GenericRequirementKind::Protocol: { const WitnessTable *witnessTable = nullptr; if (!_conformsToProtocol(nullptr, subjectType, req.getProtocol(), - &witnessTable)) - return true; + &witnessTable)) { + const char *protoName = + req.getProtocol() ? req.getProtocol().getName() : ""; + return TypeLookupError( + "subject type %s does not conform to protocol %s", req.getParam(), + protoName); + } // If we need a witness table, add it. if (req.getProtocol().needsWitnessTable()) { @@ -805,17 +685,19 @@ bool swift::_checkGenericRequirements( case GenericRequirementKind::SameType: { // Demangle the second type under the given substitutions. - auto otherType = - swift_getTypeByMangledName(MetadataState::Abstract, - req.getMangledTypeName(), - extraArguments.data(), - substGenericParam, substWitnessTable).getMetadata(); - if (!otherType) return true; + auto result = swift_getTypeByMangledName( + MetadataState::Abstract, req.getMangledTypeName(), + extraArguments.data(), substGenericParam, substWitnessTable); + if (result.getError()) + return *result.getError(); + auto otherType = result.getType().getMetadata(); assert(!req.getFlags().hasExtraArgument()); // Check that the types are equivalent. - if (subjectType != otherType) return true; + if (subjectType != otherType) + return TypeLookupError("subject type %s does not match %s", + req.getParam(), req.getMangledTypeName()); continue; } @@ -824,22 +706,24 @@ bool swift::_checkGenericRequirements( switch (req.getLayout()) { case GenericRequirementLayoutKind::Class: if (!subjectType->satisfiesClassConstraint()) - return true; + return TypeLookupError( + "subject type %s does not satisfy class constraint", + req.getParam()); continue; } // Unknown layout. - return true; + return TypeLookupError("unknown layout kind %u", req.getLayout()); } case GenericRequirementKind::BaseClass: { // Demangle the base type under the given substitutions. - auto baseType = - swift_getTypeByMangledName(MetadataState::Abstract, - req.getMangledTypeName(), - extraArguments.data(), - substGenericParam, substWitnessTable).getMetadata(); - if (!baseType) return true; + auto result = swift_getTypeByMangledName( + MetadataState::Abstract, req.getMangledTypeName(), + extraArguments.data(), substGenericParam, substWitnessTable); + if (result.getError()) + return *result.getError(); + auto baseType = result.getType().getMetadata(); // If the type which is constrained to a base class is an existential // type, and if that existential type includes a superclass constraint, @@ -851,7 +735,8 @@ bool swift::_checkGenericRequirements( } if (!isSubclass(subjectType, baseType)) - return true; + return TypeLookupError("%s is not subclass of %s", req.getParam(), + req.getMangledTypeName()); continue; } @@ -863,11 +748,12 @@ bool swift::_checkGenericRequirements( } // Unknown generic requirement kind. - return true; + return TypeLookupError("unknown generic requirement kind %u", + req.getKind()); } // Success! - return false; + return llvm::None; } const Metadata *swift::findConformingSuperclass( diff --git a/stdlib/public/runtime/ReflectionMirror.mm b/stdlib/public/runtime/ReflectionMirror.mm index 61593760d31fd..0206237d2b44b 100644 --- a/stdlib/public/runtime/ReflectionMirror.mm +++ b/stdlib/public/runtime/ReflectionMirror.mm @@ -247,16 +247,16 @@ virtual const FieldType recursiveChildMetadata(intptr_t index, // Implementation for tuples. struct TupleImpl : ReflectionMirrorImpl { - char displayStyle() { + char displayStyle() override { return 't'; } - intptr_t count() { + intptr_t count() override { auto *Tuple = static_cast(type); return Tuple->NumElements; } - intptr_t childOffset(intptr_t i) { + intptr_t childOffset(intptr_t i) override { auto *Tuple = static_cast(type); if (i < 0 || (size_t)i > Tuple->NumElements) @@ -268,7 +268,7 @@ intptr_t childOffset(intptr_t i) { } const FieldType childMetadata(intptr_t i, const char **outName, - void (**outFreeFunc)(const char *)) { + void (**outFreeFunc)(const char *)) override { auto *Tuple = static_cast(type); if (i < 0 || (size_t)i > Tuple->NumElements) @@ -306,7 +306,7 @@ const FieldType childMetadata(intptr_t i, const char **outName, } AnyReturn subscript(intptr_t i, const char **outName, - void (**outFreeFunc)(const char *)) { + void (**outFreeFunc)(const char *)) override { auto eltOffset = childOffset(i); auto fieldType = childMetadata(i, outName, outFreeFunc); @@ -400,27 +400,33 @@ static bool _shouldReportMissingReflectionMetadataWarnings() { auto typeName = field.getMangledTypeName(); SubstGenericParametersFromMetadata substitutions(base); - auto typeInfo = swift_getTypeByMangledName(MetadataState::Complete, - typeName, - substitutions.getGenericArgs(), - [&substitutions](unsigned depth, unsigned index) { - return substitutions.getMetadata(depth, index); - }, - [&substitutions](const Metadata *type, unsigned index) { - return substitutions.getWitnessTable(type, index); - }); + auto result = swift_getTypeByMangledName( + MetadataState::Complete, typeName, substitutions.getGenericArgs(), + [&substitutions](unsigned depth, unsigned index) { + return substitutions.getMetadata(depth, index); + }, + [&substitutions](const Metadata *type, unsigned index) { + return substitutions.getWitnessTable(type, index); + }); // If demangling the type failed, pretend it's an empty type instead with // a log message. - if (!typeInfo.getMetadata()) { + TypeInfo typeInfo; + if (result.isError()) { typeInfo = TypeInfo({&METADATA_SYM(EMPTY_TUPLE_MANGLING), MetadataState::Complete}, {}); + + auto *error = result.getError(); + char *str = error->copyErrorString(); missing_reflection_metadata_warning( - "warning: the Swift runtime was unable to demangle the type " - "of field '%*s'. the mangled type name is '%*s'. this field will " - "show up as an empty tuple in Mirrors\n", - (int)name.size(), name.data(), - (int)typeName.size(), typeName.data()); + "warning: the Swift runtime was unable to demangle the type " + "of field '%*s'. the mangled type name is '%*s': %s. this field will " + "show up as an empty tuple in Mirrors\n", + (int)name.size(), name.data(), (int)typeName.size(), typeName.data(), + str); + error->freeErrorString(str); + } else { + typeInfo = result.getType(); } auto fieldType = FieldType(typeInfo.getMetadata()); @@ -437,11 +443,11 @@ bool isReflectable() { return Description->isReflectable(); } - char displayStyle() { + char displayStyle() override { return 's'; } - intptr_t count() { + intptr_t count() override { if (!isReflectable()) { return 0; } @@ -450,7 +456,7 @@ intptr_t count() { return Struct->getDescription()->NumFields; } - intptr_t childOffset(intptr_t i) { + intptr_t childOffset(intptr_t i) override { auto *Struct = static_cast(type); if (i < 0 || (size_t)i > Struct->getDescription()->NumFields) @@ -461,7 +467,7 @@ intptr_t childOffset(intptr_t i) { } const FieldType childMetadata(intptr_t i, const char **outName, - void (**outFreeFunc)(const char *)) { + void (**outFreeFunc)(const char *)) override { StringRef name; FieldType fieldInfo; std::tie(name, fieldInfo) = getFieldAt(type, i); @@ -474,7 +480,7 @@ const FieldType childMetadata(intptr_t i, const char **outName, } AnyReturn subscript(intptr_t i, const char **outName, - void (**outFreeFunc)(const char *)) { + void (**outFreeFunc)(const char *)) override { auto fieldInfo = childMetadata(i, outName, outFreeFunc); auto *bytes = reinterpret_cast(value); @@ -516,11 +522,11 @@ bool isReflectable() { return name.data(); } - char displayStyle() { + char displayStyle() override { return 'e'; } - intptr_t count() { + intptr_t count() override { if (!isReflectable()) { return 0; } @@ -535,17 +541,17 @@ intptr_t count() { return (payloadType != nullptr) ? 1 : 0; } - intptr_t childOffset(intptr_t i) { + intptr_t childOffset(intptr_t i) override { return 0; } const FieldType childMetadata(intptr_t i, const char **outName, - void (**outFreeFunc)(const char *)) { + void (**outFreeFunc)(const char *)) override { return FieldType(); } AnyReturn subscript(intptr_t i, const char **outName, - void (**outFreeFunc)(const char *)) { + void (**outFreeFunc)(const char *)) override { unsigned tag; const Metadata *payloadType; bool indirect; @@ -589,7 +595,7 @@ AnyReturn subscript(intptr_t i, const char **outName, return AnyReturn(result); } - const char *enumCaseName() { + const char *enumCaseName() override { if (!isReflectable()) { return nullptr; } @@ -607,7 +613,7 @@ bool isReflectable() { return Description->isReflectable(); } - char displayStyle() { + char displayStyle() override { return 'c'; } @@ -635,7 +641,7 @@ ClassImpl superclassMirror() { swift::crash("No superclass mirror found"); } - intptr_t count() { + intptr_t count() override { if (!isReflectable()) return 0; @@ -646,7 +652,7 @@ intptr_t count() { return count; } - intptr_t recursiveCount() { + intptr_t recursiveCount() override { if (hasSuperclassMirror()) { return superclassMirror().recursiveCount() + count(); } @@ -654,7 +660,7 @@ intptr_t recursiveCount() { return count(); } - intptr_t childOffset(intptr_t i) { + intptr_t childOffset(intptr_t i) override { auto *Clas = static_cast(type); auto description = Clas->getDescription(); @@ -679,7 +685,7 @@ intptr_t childOffset(intptr_t i) { return (intptr_t)fieldOffset; } - intptr_t recursiveChildOffset(intptr_t i) { + intptr_t recursiveChildOffset(intptr_t i) override { if (hasSuperclassMirror()) { auto superMirror = superclassMirror(); auto superclassFieldCount = superMirror.recursiveCount(); @@ -695,7 +701,7 @@ intptr_t recursiveChildOffset(intptr_t i) { } const FieldType childMetadata(intptr_t i, const char **outName, - void (**outFreeFunc)(const char *)) { + void (**outFreeFunc)(const char *)) override { StringRef name; FieldType fieldInfo; std::tie(name, fieldInfo) = getFieldAt(type, i); @@ -709,8 +715,7 @@ const FieldType childMetadata(intptr_t i, const char **outName, const FieldType recursiveChildMetadata(intptr_t i, const char **outName, - void (**outFreeFunc)(const char *)) - { + void (**outFreeFunc)(const char *)) override { if (hasSuperclassMirror()) { auto superMirror = superclassMirror(); auto superclassFieldCount = superMirror.recursiveCount(); @@ -726,7 +731,7 @@ const FieldType recursiveChildMetadata(intptr_t i, } AnyReturn subscript(intptr_t i, const char **outName, - void (**outFreeFunc)(const char *)) { + void (**outFreeFunc)(const char *)) override { auto fieldInfo = childMetadata(i, outName, outFreeFunc); auto *bytes = *reinterpret_cast(value); @@ -794,25 +799,25 @@ virtual const FieldType recursiveChildMetadata(intptr_t index, // Implementation for metatypes. struct MetatypeImpl : ReflectionMirrorImpl { - char displayStyle() { + char displayStyle() override { return '\0'; } - intptr_t count() { + intptr_t count() override { return 0; } - intptr_t childOffset(intptr_t i) { + intptr_t childOffset(intptr_t i) override { swift::crash("Metatypes have no children."); } const FieldType childMetadata(intptr_t i, const char **outName, - void (**outFreeFunc)(const char *)) { + void (**outFreeFunc)(const char *)) override { swift::crash("Metatypes have no children."); } AnyReturn subscript(intptr_t i, const char **outName, - void (**outFreeFunc)(const char *)) { + void (**outFreeFunc)(const char *)) override { swift::crash("Metatypes have no children."); } }; @@ -820,25 +825,25 @@ AnyReturn subscript(intptr_t i, const char **outName, // Implementation for opaque types. struct OpaqueImpl : ReflectionMirrorImpl { - char displayStyle() { + char displayStyle() override { return '\0'; } - intptr_t count() { + intptr_t count() override { return 0; } - intptr_t childOffset(intptr_t i) { + intptr_t childOffset(intptr_t i) override { swift::crash("Opaque types have no children."); } const FieldType childMetadata(intptr_t i, const char **outName, - void (**outFreeFunc)(const char *)) { + void (**outFreeFunc)(const char *)) override { swift::crash("Opaque types have no children."); } AnyReturn subscript(intptr_t i, const char **outName, - void (**outFreeFunc)(const char *)) { + void (**outFreeFunc)(const char *)) override { swift::crash("Opaque types have no children."); } }; diff --git a/stdlib/public/runtime/SwiftObject.mm b/stdlib/public/runtime/SwiftObject.mm index f377a77d6f106..ba33dd19abd69 100644 --- a/stdlib/public/runtime/SwiftObject.mm +++ b/stdlib/public/runtime/SwiftObject.mm @@ -26,11 +26,13 @@ #include "llvm/ADT/StringRef.h" #include "swift/Basic/Lazy.h" #include "swift/Runtime/Casting.h" +#include "swift/Runtime/Debug.h" #include "swift/Runtime/EnvironmentVariables.h" #include "swift/Runtime/Heap.h" #include "swift/Runtime/HeapObject.h" #include "swift/Runtime/Metadata.h" #include "swift/Runtime/ObjCBridge.h" +#include "swift/Runtime/Portability.h" #include "swift/Strings.h" #include "../SwiftShims/RuntimeShims.h" #include "../SwiftShims/AssertionReporting.h" @@ -39,7 +41,6 @@ #include "Private.h" #include "SwiftObject.h" #include "WeakReference.h" -#include "swift/Runtime/Debug.h" #if SWIFT_OBJC_INTEROP #include #endif diff --git a/stdlib/public/stubs/Assert.cpp b/stdlib/public/stubs/Assert.cpp index 62135b2312b1c..fa0169a5ad6b8 100644 --- a/stdlib/public/stubs/Assert.cpp +++ b/stdlib/public/stubs/Assert.cpp @@ -12,6 +12,7 @@ #include "swift/Runtime/Config.h" #include "swift/Runtime/Debug.h" +#include "swift/Runtime/Portability.h" #include "../SwiftShims/AssertionReporting.h" #include #include diff --git a/stdlib/public/stubs/Stubs.cpp b/stdlib/public/stubs/Stubs.cpp index 949dca892d81f..15338277fb1d2 100644 --- a/stdlib/public/stubs/Stubs.cpp +++ b/stdlib/public/stubs/Stubs.cpp @@ -510,5 +510,9 @@ int _swift_stdlib_putc_stderr(int C) { } size_t _swift_stdlib_getHardwareConcurrency() { +#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME + return 1; +#else return std::thread::hardware_concurrency(); +#endif } diff --git a/stdlib/public/stubs/ThreadLocalStorage.cpp b/stdlib/public/stubs/ThreadLocalStorage.cpp index 1238504a2b6af..c520b08bc2df4 100644 --- a/stdlib/public/stubs/ThreadLocalStorage.cpp +++ b/stdlib/public/stubs/ThreadLocalStorage.cpp @@ -88,9 +88,19 @@ static inline int _stdlib_thread_setspecific(__swift_thread_key_t key, const voi return 0; } -#endif +#elif defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME) + +SWIFT_RUNTIME_STDLIB_INTERNAL +void * +_swift_stdlib_threadLocalStorageGet(void) { + static void *value; + if (!value) { + value = _stdlib_createTLS(); + } + return value; +} -#if SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC +#elif SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC SWIFT_RUNTIME_STDLIB_INTERNAL void * diff --git a/stdlib/toolchain/Compatibility50/CompatibilityOverride.def b/stdlib/toolchain/Compatibility50/CompatibilityOverride.def new file mode 100644 index 0000000000000..06ee84685dc35 --- /dev/null +++ b/stdlib/toolchain/Compatibility50/CompatibilityOverride.def @@ -0,0 +1,226 @@ +//===--- CompatibilityOverrides.def - Compatibility Overrides Database -*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This file defines x-macros used for metaprogramming with the set of +// compatibility override functions. +// +//===----------------------------------------------------------------------===// + +/// #define OVERRIDE(name, ret, attrs, namespace, typedArgs, namedArgs) +/// Provides information about an overridable function. +/// - name is the name of the function, without any leading swift_ or +/// namespace. +/// - ret is the return type of the function. +/// - attrs is the attributes, if any, applied to the function definition. +/// - namespace is the namespace, if any, the function is in, including a +/// trailing :: +/// - typedArgs is the argument list, including types, surrounded by +/// parentheses +/// - namedArgs is the list of argument names, with no types, surrounded by +/// parentheses +/// +/// The entries are organized by group. A user may define OVERRIDE to get all +/// entries, or define one or more of OVERRIDE_METADATALOOKUP, OVERRIDE_CASTING, +/// OVERRIDE_OBJC, OVERRIDE_FOREIGN, OVERRIDE_PROTOCOLCONFORMANCE, +/// and OVERRIDE_KEYPATH to get only those entries. + +// NOTE: this file is used to build the definition of OverrideSection in +// CompatibilityOverride.cpp, which is part of the ABI. Do not move or remove entries +// in this file after ABI stability. Additional entries can be added to the end. + +#ifdef OVERRIDE +# define OVERRIDE_METADATALOOKUP OVERRIDE +# define OVERRIDE_CASTING OVERRIDE +# define OVERRIDE_OBJC OVERRIDE +# define OVERRIDE_FOREIGN OVERRIDE +# define OVERRIDE_PROTOCOLCONFORMANCE OVERRIDE +# define OVERRIDE_KEYPATH OVERRIDE +# define OVERRIDE_WITNESSTABLE OVERRIDE +#else +# ifndef OVERRIDE_METADATALOOKUP +# define OVERRIDE_METADATALOOKUP(...) +# endif +# ifndef OVERRIDE_CASTING +# define OVERRIDE_CASTING(...) +# endif +# ifndef OVERRIDE_OBJC +# define OVERRIDE_OBJC(...) +# endif +# ifndef OVERRIDE_FOREIGN +# define OVERRIDE_FOREIGN(...) +# endif +# ifndef OVERRIDE_PROTOCOLCONFORMANCE +# define OVERRIDE_PROTOCOLCONFORMANCE(...) +# endif +# ifndef OVERRIDE_KEYPATH +# define OVERRIDE_KEYPATH(...) +# endif +# ifndef OVERRIDE_WITNESSTABLE +# define OVERRIDE_WITNESSTABLE(...) +# endif +#endif + +OVERRIDE_CASTING(dynamicCast, bool, , , swift::, + (OpaqueValue *dest, OpaqueValue *src, + const Metadata *srcType, + const Metadata *targetType, + DynamicCastFlags flags), + (dest, src, srcType, targetType, flags)) + + +OVERRIDE_CASTING(dynamicCastClass, const void *, , , swift::, + (const void *object, + const ClassMetadata *targetType), + (object, targetType)) + + +OVERRIDE_CASTING(dynamicCastClassUnconditional, const void *, , , swift::, + (const void *object, + const ClassMetadata *targetType, + const char *file, unsigned line, unsigned column), + (object, targetType, file, line, column)) + + + +OVERRIDE_CASTING(dynamicCastUnknownClass, const void *, , , swift::, + (const void *object, const Metadata *targetType), + (object, targetType)) + + +OVERRIDE_CASTING(dynamicCastUnknownClassUnconditional, const void *, , , swift::, + (const void *object, const Metadata *targetType, + const char *file, unsigned line, unsigned column), + (object, targetType, file, line, column)) + + +OVERRIDE_CASTING(dynamicCastMetatype, const Metadata *, , , swift::, + (const Metadata *sourceType, + const Metadata *targetType), + (sourceType, targetType)) + + +OVERRIDE_CASTING(dynamicCastMetatypeUnconditional, const Metadata *, , , swift::, + (const Metadata *sourceType, + const Metadata *targetType, + const char *file, unsigned line, unsigned column), + (sourceType, targetType, file, line, column)) + + +OVERRIDE_FOREIGN(dynamicCastForeignClassMetatype, const ClassMetadata *, , , swift::, + (const ClassMetadata *sourceType, + const ClassMetadata *targetType), + (sourceType, targetType)) + + +OVERRIDE_FOREIGN(dynamicCastForeignClassMetatypeUnconditional, + const ClassMetadata *, , , swift::, + (const ClassMetadata *sourceType, + const ClassMetadata *targetType, + const char *file, unsigned line, unsigned column), + (sourceType, targetType, file, line, column)) + + +OVERRIDE_PROTOCOLCONFORMANCE(conformsToProtocol, const WitnessTable *, , , swift::, + (const Metadata * const type, + const ProtocolDescriptor *protocol), + (type, protocol)) + +OVERRIDE_PROTOCOLCONFORMANCE(conformsToSwiftProtocol, + const ProtocolConformanceDescriptor *, , , swift::, + (const Metadata * const type, + const ProtocolDescriptor *protocol, + StringRef moduleName), + (type, protocol, moduleName)) + +OVERRIDE_KEYPATH(getKeyPath, const HeapObject *, , , swift::, + (const void *pattern, const void *arguments), + (pattern, arguments)) + +OVERRIDE_METADATALOOKUP(getTypeByMangledNode, TypeInfo, , SWIFT_CC(swift), swift::, + (MetadataRequest request, + Demangler &demangler, + Demangle::NodePointer node, + const void * const *arguments, + SubstGenericParameterFn substGenericParam, + SubstDependentWitnessTableFn substWitnessTable), + (request, demangler, node, arguments, substGenericParam, substWitnessTable)) +OVERRIDE_METADATALOOKUP(getTypeByMangledName, TypeInfo, , SWIFT_CC(swift), swift::, + (MetadataRequest request, + StringRef typeName, + const void * const *arguments, + SubstGenericParameterFn substGenericParam, + SubstDependentWitnessTableFn substWitnessTable), + (request, typeName, arguments, substGenericParam, substWitnessTable)) + +OVERRIDE_WITNESSTABLE(getAssociatedTypeWitnessSlow, MetadataResponse, + SWIFT_RUNTIME_STDLIB_INTERNAL, SWIFT_CC(swift), swift::, + (MetadataRequest request, WitnessTable *wtable, + const Metadata *conformingType, + const ProtocolRequirement *reqBase, + const ProtocolRequirement *assocType), + (request, wtable, conformingType, reqBase, assocType)) + +OVERRIDE_WITNESSTABLE(getAssociatedConformanceWitnessSlow, const WitnessTable *, + SWIFT_RUNTIME_STDLIB_INTERNAL, SWIFT_CC(swift), swift::, + (WitnessTable *wtable, const Metadata *conformingType, + const Metadata *assocType, + const ProtocolRequirement *reqBase, + const ProtocolRequirement *assocConformance), + (wtable, conformingType, assocType, reqBase, + assocConformance)) +#if SWIFT_OBJC_INTEROP + +OVERRIDE_OBJC(dynamicCastObjCClass, const void *, , , swift::, + (const void *object, + const ClassMetadata *targetType), + (object, targetType)) + + +OVERRIDE_OBJC(dynamicCastObjCClassUnconditional, const void *, , , swift::, + (const void *object, + const ClassMetadata *targetType, + const char *file, unsigned line, unsigned column), + (object, targetType, file, line, column)) + +OVERRIDE_OBJC(dynamicCastObjCClassMetatype, const ClassMetadata *, , , swift::, + (const ClassMetadata *sourceType, + const ClassMetadata *targetType), + (sourceType, targetType)) + + +OVERRIDE_OBJC(dynamicCastObjCClassMetatypeUnconditional, const ClassMetadata *, , , swift::, + (const ClassMetadata *sourceType, const ClassMetadata *targetType, + const char *file, unsigned line, unsigned column), + (sourceType, targetType, file, line, column)) + + +OVERRIDE_FOREIGN(dynamicCastForeignClass, const void *, , , swift::, + (const void *object, + const ForeignClassMetadata *targetType), + (object, targetType)) + + +OVERRIDE_FOREIGN(dynamicCastForeignClassUnconditional, const void *, , , swift::, + (const void *object, const ForeignClassMetadata *targetType, + const char *file, unsigned line, unsigned column), + (object, targetType, file, line, column)) + +#endif + +#undef OVERRIDE +#undef OVERRIDE_METADATALOOKUP +#undef OVERRIDE_CASTING +#undef OVERRIDE_OBJC +#undef OVERRIDE_FOREIGN +#undef OVERRIDE_PROTOCOLCONFORMANCE +#undef OVERRIDE_KEYPATH +#undef OVERRIDE_WITNESSTABLE diff --git a/stdlib/toolchain/Compatibility50/CompatibilityOverride.h b/stdlib/toolchain/Compatibility50/CompatibilityOverride.h new file mode 100644 index 0000000000000..e726e41958f50 --- /dev/null +++ b/stdlib/toolchain/Compatibility50/CompatibilityOverride.h @@ -0,0 +1,61 @@ +//===--- CompatibiltyOverride.h - Back-deploying compatibility fixes --*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2018 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 +// +//===----------------------------------------------------------------------===// +// +// Support back-deploying compatibility fixes for newer apps running on older runtimes. +// +//===----------------------------------------------------------------------===// + +#ifndef COMPATIBILITY_OVERRIDE_H +#define COMPATIBILITY_OVERRIDE_H + +#include "../../public/runtime/Private.h" +#include "swift/Runtime/Metadata.h" +#include "swift/Runtime/Once.h" +#include + +namespace swift { + +#define COMPATIBILITY_UNPAREN(...) __VA_ARGS__ + +#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ + ccAttrs typedef ret (*Original_ ## name) typedArgs; +#include "CompatibilityOverride.def" + +#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ + ccAttrs typedef ret (*Override_ ## name)(COMPATIBILITY_UNPAREN typedArgs, \ + Original_ ## name originalImpl); +#include "CompatibilityOverride.def" + +#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ + Override_ ## name getOverride_ ## name(); +#include "CompatibilityOverride.def" + + +/// Used to define an override point. The override point #defines the appropriate +/// OVERRIDE macro from CompatibilityOverride.def to this macro, then includes +/// the file to generate the override points. The original implementation of the +/// functionality must be available as swift_funcNameHereImpl. +#define COMPATIBILITY_OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ + attrs ccAttrs ret namespace swift_ ## name typedArgs { \ + static Override_ ## name Override; \ + static swift_once_t Predicate; \ + swift_once(&Predicate, [](void *) { \ + Override = getOverride_ ## name(); \ + }, nullptr); \ + if (Override != nullptr) \ + return Override(COMPATIBILITY_UNPAREN namedArgs, swift_ ## name ## Impl); \ + return swift_ ## name ## Impl namedArgs; \ + } + +} /* end namespace swift */ + +#endif /* COMPATIBILITY_OVERRIDE_H */ diff --git a/stdlib/toolchain/Compatibility50/Overrides.cpp b/stdlib/toolchain/Compatibility50/Overrides.cpp index bc6f88625256b..fcaccf3b0fb4d 100644 --- a/stdlib/toolchain/Compatibility50/Overrides.cpp +++ b/stdlib/toolchain/Compatibility50/Overrides.cpp @@ -16,7 +16,7 @@ #include "Overrides.h" #include "../Compatibility51/Overrides.h" -#include "../../public/runtime/CompatibilityOverride.h" +#include "CompatibilityOverride.h" #include #include @@ -28,7 +28,7 @@ struct OverrideSection { uintptr_t version; #define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ Override_ ## name name; -#include "../../public/runtime/CompatibilityOverride.def" +#include "CompatibilityOverride.def" }; OverrideSection Swift50Overrides diff --git a/stdlib/toolchain/Compatibility51/CompatibilityOverride.def b/stdlib/toolchain/Compatibility51/CompatibilityOverride.def new file mode 100644 index 0000000000000..06ee84685dc35 --- /dev/null +++ b/stdlib/toolchain/Compatibility51/CompatibilityOverride.def @@ -0,0 +1,226 @@ +//===--- CompatibilityOverrides.def - Compatibility Overrides Database -*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This file defines x-macros used for metaprogramming with the set of +// compatibility override functions. +// +//===----------------------------------------------------------------------===// + +/// #define OVERRIDE(name, ret, attrs, namespace, typedArgs, namedArgs) +/// Provides information about an overridable function. +/// - name is the name of the function, without any leading swift_ or +/// namespace. +/// - ret is the return type of the function. +/// - attrs is the attributes, if any, applied to the function definition. +/// - namespace is the namespace, if any, the function is in, including a +/// trailing :: +/// - typedArgs is the argument list, including types, surrounded by +/// parentheses +/// - namedArgs is the list of argument names, with no types, surrounded by +/// parentheses +/// +/// The entries are organized by group. A user may define OVERRIDE to get all +/// entries, or define one or more of OVERRIDE_METADATALOOKUP, OVERRIDE_CASTING, +/// OVERRIDE_OBJC, OVERRIDE_FOREIGN, OVERRIDE_PROTOCOLCONFORMANCE, +/// and OVERRIDE_KEYPATH to get only those entries. + +// NOTE: this file is used to build the definition of OverrideSection in +// CompatibilityOverride.cpp, which is part of the ABI. Do not move or remove entries +// in this file after ABI stability. Additional entries can be added to the end. + +#ifdef OVERRIDE +# define OVERRIDE_METADATALOOKUP OVERRIDE +# define OVERRIDE_CASTING OVERRIDE +# define OVERRIDE_OBJC OVERRIDE +# define OVERRIDE_FOREIGN OVERRIDE +# define OVERRIDE_PROTOCOLCONFORMANCE OVERRIDE +# define OVERRIDE_KEYPATH OVERRIDE +# define OVERRIDE_WITNESSTABLE OVERRIDE +#else +# ifndef OVERRIDE_METADATALOOKUP +# define OVERRIDE_METADATALOOKUP(...) +# endif +# ifndef OVERRIDE_CASTING +# define OVERRIDE_CASTING(...) +# endif +# ifndef OVERRIDE_OBJC +# define OVERRIDE_OBJC(...) +# endif +# ifndef OVERRIDE_FOREIGN +# define OVERRIDE_FOREIGN(...) +# endif +# ifndef OVERRIDE_PROTOCOLCONFORMANCE +# define OVERRIDE_PROTOCOLCONFORMANCE(...) +# endif +# ifndef OVERRIDE_KEYPATH +# define OVERRIDE_KEYPATH(...) +# endif +# ifndef OVERRIDE_WITNESSTABLE +# define OVERRIDE_WITNESSTABLE(...) +# endif +#endif + +OVERRIDE_CASTING(dynamicCast, bool, , , swift::, + (OpaqueValue *dest, OpaqueValue *src, + const Metadata *srcType, + const Metadata *targetType, + DynamicCastFlags flags), + (dest, src, srcType, targetType, flags)) + + +OVERRIDE_CASTING(dynamicCastClass, const void *, , , swift::, + (const void *object, + const ClassMetadata *targetType), + (object, targetType)) + + +OVERRIDE_CASTING(dynamicCastClassUnconditional, const void *, , , swift::, + (const void *object, + const ClassMetadata *targetType, + const char *file, unsigned line, unsigned column), + (object, targetType, file, line, column)) + + + +OVERRIDE_CASTING(dynamicCastUnknownClass, const void *, , , swift::, + (const void *object, const Metadata *targetType), + (object, targetType)) + + +OVERRIDE_CASTING(dynamicCastUnknownClassUnconditional, const void *, , , swift::, + (const void *object, const Metadata *targetType, + const char *file, unsigned line, unsigned column), + (object, targetType, file, line, column)) + + +OVERRIDE_CASTING(dynamicCastMetatype, const Metadata *, , , swift::, + (const Metadata *sourceType, + const Metadata *targetType), + (sourceType, targetType)) + + +OVERRIDE_CASTING(dynamicCastMetatypeUnconditional, const Metadata *, , , swift::, + (const Metadata *sourceType, + const Metadata *targetType, + const char *file, unsigned line, unsigned column), + (sourceType, targetType, file, line, column)) + + +OVERRIDE_FOREIGN(dynamicCastForeignClassMetatype, const ClassMetadata *, , , swift::, + (const ClassMetadata *sourceType, + const ClassMetadata *targetType), + (sourceType, targetType)) + + +OVERRIDE_FOREIGN(dynamicCastForeignClassMetatypeUnconditional, + const ClassMetadata *, , , swift::, + (const ClassMetadata *sourceType, + const ClassMetadata *targetType, + const char *file, unsigned line, unsigned column), + (sourceType, targetType, file, line, column)) + + +OVERRIDE_PROTOCOLCONFORMANCE(conformsToProtocol, const WitnessTable *, , , swift::, + (const Metadata * const type, + const ProtocolDescriptor *protocol), + (type, protocol)) + +OVERRIDE_PROTOCOLCONFORMANCE(conformsToSwiftProtocol, + const ProtocolConformanceDescriptor *, , , swift::, + (const Metadata * const type, + const ProtocolDescriptor *protocol, + StringRef moduleName), + (type, protocol, moduleName)) + +OVERRIDE_KEYPATH(getKeyPath, const HeapObject *, , , swift::, + (const void *pattern, const void *arguments), + (pattern, arguments)) + +OVERRIDE_METADATALOOKUP(getTypeByMangledNode, TypeInfo, , SWIFT_CC(swift), swift::, + (MetadataRequest request, + Demangler &demangler, + Demangle::NodePointer node, + const void * const *arguments, + SubstGenericParameterFn substGenericParam, + SubstDependentWitnessTableFn substWitnessTable), + (request, demangler, node, arguments, substGenericParam, substWitnessTable)) +OVERRIDE_METADATALOOKUP(getTypeByMangledName, TypeInfo, , SWIFT_CC(swift), swift::, + (MetadataRequest request, + StringRef typeName, + const void * const *arguments, + SubstGenericParameterFn substGenericParam, + SubstDependentWitnessTableFn substWitnessTable), + (request, typeName, arguments, substGenericParam, substWitnessTable)) + +OVERRIDE_WITNESSTABLE(getAssociatedTypeWitnessSlow, MetadataResponse, + SWIFT_RUNTIME_STDLIB_INTERNAL, SWIFT_CC(swift), swift::, + (MetadataRequest request, WitnessTable *wtable, + const Metadata *conformingType, + const ProtocolRequirement *reqBase, + const ProtocolRequirement *assocType), + (request, wtable, conformingType, reqBase, assocType)) + +OVERRIDE_WITNESSTABLE(getAssociatedConformanceWitnessSlow, const WitnessTable *, + SWIFT_RUNTIME_STDLIB_INTERNAL, SWIFT_CC(swift), swift::, + (WitnessTable *wtable, const Metadata *conformingType, + const Metadata *assocType, + const ProtocolRequirement *reqBase, + const ProtocolRequirement *assocConformance), + (wtable, conformingType, assocType, reqBase, + assocConformance)) +#if SWIFT_OBJC_INTEROP + +OVERRIDE_OBJC(dynamicCastObjCClass, const void *, , , swift::, + (const void *object, + const ClassMetadata *targetType), + (object, targetType)) + + +OVERRIDE_OBJC(dynamicCastObjCClassUnconditional, const void *, , , swift::, + (const void *object, + const ClassMetadata *targetType, + const char *file, unsigned line, unsigned column), + (object, targetType, file, line, column)) + +OVERRIDE_OBJC(dynamicCastObjCClassMetatype, const ClassMetadata *, , , swift::, + (const ClassMetadata *sourceType, + const ClassMetadata *targetType), + (sourceType, targetType)) + + +OVERRIDE_OBJC(dynamicCastObjCClassMetatypeUnconditional, const ClassMetadata *, , , swift::, + (const ClassMetadata *sourceType, const ClassMetadata *targetType, + const char *file, unsigned line, unsigned column), + (sourceType, targetType, file, line, column)) + + +OVERRIDE_FOREIGN(dynamicCastForeignClass, const void *, , , swift::, + (const void *object, + const ForeignClassMetadata *targetType), + (object, targetType)) + + +OVERRIDE_FOREIGN(dynamicCastForeignClassUnconditional, const void *, , , swift::, + (const void *object, const ForeignClassMetadata *targetType, + const char *file, unsigned line, unsigned column), + (object, targetType, file, line, column)) + +#endif + +#undef OVERRIDE +#undef OVERRIDE_METADATALOOKUP +#undef OVERRIDE_CASTING +#undef OVERRIDE_OBJC +#undef OVERRIDE_FOREIGN +#undef OVERRIDE_PROTOCOLCONFORMANCE +#undef OVERRIDE_KEYPATH +#undef OVERRIDE_WITNESSTABLE diff --git a/stdlib/toolchain/Compatibility51/CompatibilityOverride.h b/stdlib/toolchain/Compatibility51/CompatibilityOverride.h new file mode 100644 index 0000000000000..e726e41958f50 --- /dev/null +++ b/stdlib/toolchain/Compatibility51/CompatibilityOverride.h @@ -0,0 +1,61 @@ +//===--- CompatibiltyOverride.h - Back-deploying compatibility fixes --*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2018 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 +// +//===----------------------------------------------------------------------===// +// +// Support back-deploying compatibility fixes for newer apps running on older runtimes. +// +//===----------------------------------------------------------------------===// + +#ifndef COMPATIBILITY_OVERRIDE_H +#define COMPATIBILITY_OVERRIDE_H + +#include "../../public/runtime/Private.h" +#include "swift/Runtime/Metadata.h" +#include "swift/Runtime/Once.h" +#include + +namespace swift { + +#define COMPATIBILITY_UNPAREN(...) __VA_ARGS__ + +#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ + ccAttrs typedef ret (*Original_ ## name) typedArgs; +#include "CompatibilityOverride.def" + +#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ + ccAttrs typedef ret (*Override_ ## name)(COMPATIBILITY_UNPAREN typedArgs, \ + Original_ ## name originalImpl); +#include "CompatibilityOverride.def" + +#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ + Override_ ## name getOverride_ ## name(); +#include "CompatibilityOverride.def" + + +/// Used to define an override point. The override point #defines the appropriate +/// OVERRIDE macro from CompatibilityOverride.def to this macro, then includes +/// the file to generate the override points. The original implementation of the +/// functionality must be available as swift_funcNameHereImpl. +#define COMPATIBILITY_OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ + attrs ccAttrs ret namespace swift_ ## name typedArgs { \ + static Override_ ## name Override; \ + static swift_once_t Predicate; \ + swift_once(&Predicate, [](void *) { \ + Override = getOverride_ ## name(); \ + }, nullptr); \ + if (Override != nullptr) \ + return Override(COMPATIBILITY_UNPAREN namedArgs, swift_ ## name ## Impl); \ + return swift_ ## name ## Impl namedArgs; \ + } + +} /* end namespace swift */ + +#endif /* COMPATIBILITY_OVERRIDE_H */ diff --git a/stdlib/toolchain/Compatibility51/Overrides.cpp b/stdlib/toolchain/Compatibility51/Overrides.cpp index 5e1eb78f3ab37..f9a89ec39e115 100644 --- a/stdlib/toolchain/Compatibility51/Overrides.cpp +++ b/stdlib/toolchain/Compatibility51/Overrides.cpp @@ -14,7 +14,7 @@ // //===----------------------------------------------------------------------===// -#include "../../public/runtime/CompatibilityOverride.h" +#include "CompatibilityOverride.h" #include "Overrides.h" #include @@ -27,7 +27,7 @@ struct OverrideSection { uintptr_t version; #define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \ Override_ ## name name; -#include "../../public/runtime/CompatibilityOverride.def" +#include "CompatibilityOverride.def" }; OverrideSection Swift51Overrides diff --git a/test/AutoDiff/SILOptimizer/activity_analysis.swift b/test/AutoDiff/SILOptimizer/activity_analysis.swift index fe8fd1a7785c1..2a2fdcca7f650 100644 --- a/test/AutoDiff/SILOptimizer/activity_analysis.swift +++ b/test/AutoDiff/SILOptimizer/activity_analysis.swift @@ -543,17 +543,25 @@ func activeInoutArgNonactiveInitialResult(_ x: Float) -> Float { func rethrowing(_ x: () throws -> Void) rethrows -> Void {} -// expected-error @+1 {{function is not differentiable}} @differentiable -// expected-note @+1 {{when differentiating this function definition}} func testTryApply(_ x: Float) -> Float { - // expected-note @+1 {{cannot differentiate unsupported control flow}} rethrowing({}) return x } // TF-433: differentiation diagnoses `try_apply` before activity info is printed. -// CHECK-NOT: [AD] Activity info for ${{.*}}testTryApply{{.*}} at (parameters=(0) results=(0)) +// CHECK-LABEL: [AD] Activity info for ${{.*}}testTryApply{{.*}} at (parameters=(0) results=(0)) +// CHECK: bb0: +// CHECK: [ACTIVE] %0 = argument of bb0 : $Float +// CHECK: [NONE] // function_ref closure #1 in testTryApply(_:) +// CHECK: [NONE] %3 = convert_function %2 : $@convention(thin) () -> () to $@convention(thin) @noescape () -> () +// CHECK: [NONE] %4 = thin_to_thick_function %3 : $@convention(thin) @noescape () -> () to $@noescape @callee_guaranteed () -> () +// CHECK: [NONE] %5 = convert_function %4 : $@noescape @callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> @error Error +// CHECK: [NONE] // function_ref rethrowing(_:) +// CHECK: bb1: +// CHECK: [NONE] %8 = argument of bb1 : $() +// CHECK: bb2: +// CHECK: [NONE] %10 = argument of bb2 : $Error //===----------------------------------------------------------------------===// // Coroutine differentiation (`begin_apply`) diff --git a/test/AutoDiff/SILOptimizer/differentiation_control_flow_diagnostics.swift b/test/AutoDiff/SILOptimizer/differentiation_control_flow_diagnostics.swift index 6bc8cda64005f..5248811b04aa0 100644 --- a/test/AutoDiff/SILOptimizer/differentiation_control_flow_diagnostics.swift +++ b/test/AutoDiff/SILOptimizer/differentiation_control_flow_diagnostics.swift @@ -78,11 +78,8 @@ func nested_loop(_ x: Float) -> Float { func rethrowing(_ x: () throws -> Void) rethrows -> Void {} -// expected-error @+1 {{function is not differentiable}} @differentiable -// expected-note @+1 {{when differentiating this function definition}} func testTryApply(_ x: Float) -> Float { - // expected-note @+1 {{cannot differentiate unsupported control flow}} rethrowing({}) return x } @@ -93,10 +90,19 @@ func testTryApply(_ x: Float) -> Float { func withoutDerivative( at x: T, in body: (T) throws -> R ) rethrows -> R { - // expected-note @+1 {{cannot differentiate unsupported control flow}} + // expected-note @+1 {{expression is not differentiable}} try body(x) } +// Tests active `try_apply`. +// expected-error @+1 {{function is not differentiable}} +@differentiable +// expected-note @+1 {{when differentiating this function definition}} +func testNilCoalescing(_ maybeX: Float?) -> Float { + // expected-note @+1 {{expression is not differentiable}} + return maybeX ?? 10 +} + // Test unsupported differentiation of active enum values. // expected-error @+1 {{function is not differentiable}} @@ -165,7 +171,7 @@ func loop_array(_ array: [Float]) -> Float { var result: Float = 1 // TODO(TF-957): Improve non-differentiability errors for for-in loops // (`Collection.makeIterator` and `IteratorProtocol.next`). - // expected-note @+1 {{cannot differentiate through a non-differentiable result; do you want to use 'withoutDerivative(at:)'?}} + // expected-note @+1 {{cannot differentiate through a non-differentiable result; do you want to use 'withoutDerivative(at:)'?}} {{12-12=withoutDerivative(at: }} {{17-17=)}} for x in array { result = result * x } diff --git a/test/AutoDiff/SILOptimizer/differentiation_control_flow_sil.swift b/test/AutoDiff/SILOptimizer/differentiation_control_flow_sil.swift index 4b30bd64cd358..2778a4d849cd3 100644 --- a/test/AutoDiff/SILOptimizer/differentiation_control_flow_sil.swift +++ b/test/AutoDiff/SILOptimizer/differentiation_control_flow_sil.swift @@ -68,29 +68,30 @@ func cond(_ x: Float) -> Float { // CHECK-SIL: [[PB:%.*]] = partial_apply [callee_guaranteed] [[PULLBACK_REF]]([[BB3_PB_STRUCT]]) // CHECK-SIL: [[VJP_RESULT:%.*]] = tuple ([[ORIG_RES]] : $Float, [[PB]] : $@callee_guaranteed (Float) -> Float) // CHECK-SIL: return [[VJP_RESULT]] +// CHECK-SIL-LABEL: } // end sil function 'AD__cond__vjp_src_0_wrt_0' // CHECK-SIL-LABEL: sil private [ossa] @AD__cond__pullback_src_0_wrt_0 : $@convention(thin) (Float, @owned _AD__cond_bb3__PB__src_0_wrt_0) -> Float { // CHECK-SIL: bb0([[SEED:%.*]] : $Float, [[BB3_PB_STRUCT:%.*]] : @owned $_AD__cond_bb3__PB__src_0_wrt_0): // CHECK-SIL: [[BB3_PRED:%.*]] = destructure_struct [[BB3_PB_STRUCT]] : $_AD__cond_bb3__PB__src_0_wrt_0 -// CHECK-SIL: switch_enum [[BB3_PRED]] : $_AD__cond_bb3__Pred__src_0_wrt_0, case #_AD__cond_bb3__Pred__src_0_wrt_0.bb2!enumelt: bb3, case #_AD__cond_bb3__Pred__src_0_wrt_0.bb1!enumelt: bb1 +// CHECK-SIL: switch_enum [[BB3_PRED]] : $_AD__cond_bb3__Pred__src_0_wrt_0, case #_AD__cond_bb3__Pred__src_0_wrt_0.bb2!enumelt: bb1, case #_AD__cond_bb3__Pred__src_0_wrt_0.bb1!enumelt: bb3 -// CHECK-SIL: bb1([[BB3_PRED1_TRAMP_PB_STRUCT:%.*]] : @owned $_AD__cond_bb1__PB__src_0_wrt_0): -// CHECK-SIL: br bb2({{%.*}} : $Float, {{%.*}}: $Float, [[BB3_PRED1_TRAMP_PB_STRUCT]] : $_AD__cond_bb1__PB__src_0_wrt_0) +// CHECK-SIL: bb1([[BB3_PRED2_TRAMP_PB_STRUCT:%.*]] : @owned $_AD__cond_bb2__PB__src_0_wrt_0): +// CHECK-SIL: br bb2({{%.*}} : $Float, {{%.*}}: $Float, [[BB3_PRED2_TRAMP_PB_STRUCT]] : $_AD__cond_bb2__PB__src_0_wrt_0) -// CHECK-SIL: bb2({{%.*}} : $Float, {{%.*}} : $Float, [[BB1_PB_STRUCT:%.*]] : @owned $_AD__cond_bb1__PB__src_0_wrt_0): -// CHECK-SIL: ([[BB1_PRED:%.*]], [[BB1_PB:%.*]]) = destructure_struct [[BB1_PB_STRUCT]] -// CHECK-SIL: [[BB1_ADJVALS:%.*]] = apply [[BB1_PB]]([[SEED]]) : $@callee_guaranteed (Float) -> (Float, Float) -// CHECK-SIL: switch_enum [[BB1_PRED]] : $_AD__cond_bb1__Pred__src_0_wrt_0, case #_AD__cond_bb1__Pred__src_0_wrt_0.bb0!enumelt: bb5 - -// CHECK-SIL: bb3([[BB3_PRED2_TRAMP_PB_STRUCT:%.*]] : @owned $_AD__cond_bb2__PB__src_0_wrt_0): -// CHECK-SIL: br bb4({{%.*}} : $Float, {{%.*}}: $Float, [[BB3_PRED2_TRAMP_PB_STRUCT]] : $_AD__cond_bb2__PB__src_0_wrt_0) - -// CHECK-SIL: bb4({{%.*}} : $Float, {{%.*}} : $Float, [[BB2_PB_STRUCT:%.*]] : @owned $_AD__cond_bb2__PB__src_0_wrt_0): +// CHECK-SIL: bb2({{%.*}} : $Float, {{%.*}} : $Float, [[BB2_PB_STRUCT:%.*]] : @owned $_AD__cond_bb2__PB__src_0_wrt_0): // CHECK-SIL: ([[BB2_PRED:%.*]], [[BB2_PB:%.*]]) = destructure_struct [[BB2_PB_STRUCT]] // CHECK-SIL: [[BB2_ADJVALS:%.*]] = apply [[BB2_PB]]([[SEED]]) : $@callee_guaranteed (Float) -> (Float, Float) // CHECK-SIL: switch_enum [[BB2_PRED]] : $_AD__cond_bb2__Pred__src_0_wrt_0, case #_AD__cond_bb2__Pred__src_0_wrt_0.bb0!enumelt: bb6 +// CHECK-SIL: bb3([[BB3_PRED1_TRAMP_PB_STRUCT:%.*]] : @owned $_AD__cond_bb1__PB__src_0_wrt_0): +// CHECK-SIL: br bb4({{%.*}} : $Float, {{%.*}}: $Float, [[BB3_PRED1_TRAMP_PB_STRUCT]] : $_AD__cond_bb1__PB__src_0_wrt_0) + +// CHECK-SIL: bb4({{%.*}} : $Float, {{%.*}} : $Float, [[BB1_PB_STRUCT:%.*]] : @owned $_AD__cond_bb1__PB__src_0_wrt_0): +// CHECK-SIL: ([[BB1_PRED:%.*]], [[BB1_PB:%.*]]) = destructure_struct [[BB1_PB_STRUCT]] +// CHECK-SIL: [[BB1_ADJVALS:%.*]] = apply [[BB1_PB]]([[SEED]]) : $@callee_guaranteed (Float) -> (Float, Float) +// CHECK-SIL: switch_enum [[BB1_PRED]] : $_AD__cond_bb1__Pred__src_0_wrt_0, case #_AD__cond_bb1__Pred__src_0_wrt_0.bb0!enumelt: bb5 + // CHECK-SIL: bb5([[BB1_PRED0_TRAMP_PB_STRUCT:%.*]] : $_AD__cond_bb0__PB__src_0_wrt_0): // CHECK-SIL: br bb7({{%.*}} : $Float, [[BB1_PRED0_TRAMP_PB_STRUCT]] : $_AD__cond_bb0__PB__src_0_wrt_0) @@ -99,6 +100,7 @@ func cond(_ x: Float) -> Float { // CHECK-SIL: bb7({{%.*}} : $Float, [[BB0_PB_STRUCT:%.*]] : $_AD__cond_bb0__PB__src_0_wrt_0): // CHECK-SIL: return {{%.*}} : $Float +// CHECK-SIL-LABEL: } // end sil function 'AD__cond__pullback_src_0_wrt_0' @differentiable @_silgen_name("nested_cond") @@ -178,7 +180,7 @@ func enum_notactive(_ e: Enum, _ x: Float) -> Float { // CHECK-SIL: [[PB:%.*]] = partial_apply [callee_guaranteed] [[PULLBACK_REF]]([[BB3_PB_STRUCT]]) // CHECK-SIL: [[VJP_RESULT:%.*]] = tuple ([[ORIG_RES]] : $Float, [[PB]] : $@callee_guaranteed (Float) -> Float) // CHECK-SIL: return [[VJP_RESULT]] -// CHECK-SIL: } +// CHECK-SIL-LABEL: } // end sil function 'AD__enum_notactive__vjp_src_0_wrt_1' // Test `switch_enum_addr`. @@ -227,7 +229,7 @@ func enum_addr_notactive(_ e: AddressOnlyEnum, _ x: Float) -> Float { // CHECK-SIL: [[PB:%.*]] = partial_apply [callee_guaranteed] [[PB_FNREF]]<τ_0_0>([[BB3_PB_STRUCT]]) : $@convention(thin) <τ_0_0> (Float, @owned _AD__enum_addr_notactive_bb3__PB__src_0_wrt_1_l<τ_0_0>) -> Float // CHECK-SIL: [[VJP_RESULT:%.*]] = tuple ([[X_ARG]] : $Float, [[PB]] : $@callee_guaranteed (Float) -> Float) // CHECK-SIL: return [[VJP_RESULT]] : $(Float, @callee_guaranteed (Float) -> Float) -// CHECK-SIL: } +// CHECK-SIL-LABEL: } // end sil function 'AD__enum_addr_notactive__vjp_src_0_wrt_1_l' // Test control flow + tuple buffer. // Verify that pullback buffers are not allocated for address projections. @@ -248,25 +250,25 @@ func cond_tuple_var(_ x: Float) -> Float { // CHECK-SIL: [[BB3_PRED:%.*]] = destructure_struct [[BB3_PB_STRUCT]] : $_AD__cond_tuple_var_bb3__PB__src_0_wrt_0 // CHECK-SIL: copy_addr {{%.*}} to {{%.*}} : $*(Float, Float) // CHECK-SIL-NOT: copy_addr {{%.*}} to {{%.*}} : $*Float -// CHECK-SIL: switch_enum [[BB3_PRED]] : $_AD__cond_tuple_var_bb3__Pred__src_0_wrt_0, case #_AD__cond_tuple_var_bb3__Pred__src_0_wrt_0.bb2!enumelt: bb3, case #_AD__cond_tuple_var_bb3__Pred__src_0_wrt_0.bb1!enumelt: bb1 +// CHECK-SIL: switch_enum [[BB3_PRED]] : $_AD__cond_tuple_var_bb3__Pred__src_0_wrt_0, case #_AD__cond_tuple_var_bb3__Pred__src_0_wrt_0.bb2!enumelt: bb1, case #_AD__cond_tuple_var_bb3__Pred__src_0_wrt_0.bb1!enumelt: bb3 -// CHECK-SIL: bb1([[BB3_PRED1_TRAMP_PB_STRUCT:%.*]] : $_AD__cond_tuple_var_bb1__PB__src_0_wrt_0): -// CHECK-SIL: br bb2({{%.*}} : $Float, {{%.*}} : $Float, [[BB3_PRED1_TRAMP_PB_STRUCT]] : $_AD__cond_tuple_var_bb1__PB__src_0_wrt_0) +// CHECK-SIL: bb1([[BB3_PRED2_TRAMP_PB_STRUCT:%.*]] : $_AD__cond_tuple_var_bb2__PB__src_0_wrt_0): +// CHECK-SIL: br bb2({{%.*}} : $Float, {{%.*}} : $Float, [[BB3_PRED2_TRAMP_PB_STRUCT]] : $_AD__cond_tuple_var_bb2__PB__src_0_wrt_0) -// CHECK-SIL: bb2({{%.*}} : $Float, {{%.*}} : $Float, [[BB1_PB_STRUCT:%.*]] : $_AD__cond_tuple_var_bb1__PB__src_0_wrt_0): -// CHECK-SIL: [[BB1_PRED:%.*]] = destructure_struct [[BB1_PB_STRUCT]] +// CHECK-SIL: bb2({{%.*}} : $Float, {{%.*}} : $Float, [[BB2_PB_STRUCT:%.*]] : $_AD__cond_tuple_var_bb2__PB__src_0_wrt_0): +// CHECK-SIL: [[BB2_PRED:%.*]] = destructure_struct [[BB2_PB_STRUCT]] // CHECK-SIL: copy_addr {{%.*}} to {{%.*}} : $*(Float, Float) // CHECK-SIL-NOT: copy_addr {{%.*}} to {{%.*}} : $*Float -// CHECK-SIL: switch_enum [[BB1_PRED]] : $_AD__cond_tuple_var_bb1__Pred__src_0_wrt_0, case #_AD__cond_tuple_var_bb1__Pred__src_0_wrt_0.bb0!enumelt: bb5 +// CHECK-SIL: switch_enum [[BB2_PRED]] : $_AD__cond_tuple_var_bb2__Pred__src_0_wrt_0, case #_AD__cond_tuple_var_bb2__Pred__src_0_wrt_0.bb0!enumelt: bb6 -// CHECK-SIL: bb3([[BB3_PRED2_TRAMP_PB_STRUCT:%.*]] : $_AD__cond_tuple_var_bb2__PB__src_0_wrt_0): -// CHECK-SIL: br bb4({{%.*}} : $Float, {{%.*}} : $Float, [[BB3_PRED2_TRAMP_PB_STRUCT]] : $_AD__cond_tuple_var_bb2__PB__src_0_wrt_0) +// CHECK-SIL: bb3([[BB3_PRED1_TRAMP_PB_STRUCT:%.*]] : $_AD__cond_tuple_var_bb1__PB__src_0_wrt_0): +// CHECK-SIL: br bb4({{%.*}} : $Float, {{%.*}} : $Float, [[BB3_PRED1_TRAMP_PB_STRUCT]] : $_AD__cond_tuple_var_bb1__PB__src_0_wrt_0) -// CHECK-SIL: bb4({{%.*}} : $Float, {{%.*}} : $Float, [[BB2_PB_STRUCT:%.*]] : $_AD__cond_tuple_var_bb2__PB__src_0_wrt_0): -// CHECK-SIL: [[BB2_PRED:%.*]] = destructure_struct [[BB2_PB_STRUCT]] +// CHECK-SIL: bb4({{%.*}} : $Float, {{%.*}} : $Float, [[BB1_PB_STRUCT:%.*]] : $_AD__cond_tuple_var_bb1__PB__src_0_wrt_0): +// CHECK-SIL: [[BB1_PRED:%.*]] = destructure_struct [[BB1_PB_STRUCT]] // CHECK-SIL: copy_addr {{%.*}} to {{%.*}} : $*(Float, Float) // CHECK-SIL-NOT: copy_addr {{%.*}} to {{%.*}} : $*Float -// CHECK-SIL: switch_enum [[BB2_PRED]] : $_AD__cond_tuple_var_bb2__Pred__src_0_wrt_0, case #_AD__cond_tuple_var_bb2__Pred__src_0_wrt_0.bb0!enumelt: bb6 +// CHECK-SIL: switch_enum [[BB1_PRED]] : $_AD__cond_tuple_var_bb1__Pred__src_0_wrt_0, case #_AD__cond_tuple_var_bb1__Pred__src_0_wrt_0.bb0!enumelt: bb5 // CHECK-SIL: bb5([[BB1_PRED0_TRAMP_PB_STRUCT:%.*]] : $_AD__cond_tuple_var_bb0__PB__src_0_wrt_0): // CHECK-SIL: br bb7({{%.*}} : $Float, [[BB1_PRED0_TRAMP_PB_STRUCT]] : $_AD__cond_tuple_var_bb0__PB__src_0_wrt_0) @@ -276,3 +278,4 @@ func cond_tuple_var(_ x: Float) -> Float { // CHECK-SIL: bb7({{%.*}} : $Float, [[BB0_PB_STRUCT:%.*]] : $_AD__cond_tuple_var_bb0__PB__src_0_wrt_0): // CHECK-SIL: return {{%.*}} : $Float +// CHECK-SIL-LABEL: } // end sil function 'AD__cond_tuple_var__pullback_src_0_wrt_0' diff --git a/test/AutoDiff/SILOptimizer/differentiation_diagnostics.swift b/test/AutoDiff/SILOptimizer/differentiation_diagnostics.swift index 9473311a62247..22d3fca6a17c3 100644 --- a/test/AutoDiff/SILOptimizer/differentiation_diagnostics.swift +++ b/test/AutoDiff/SILOptimizer/differentiation_diagnostics.swift @@ -32,22 +32,16 @@ func conditional(_ x: Float, _ flag: Bool) -> Float { func throwing() throws -> Void {} -// expected-error @+2 {{function is not differentiable}} -// expected-note @+2 {{when differentiating this function definition}} @differentiable func try_apply(_ x: Float) -> Float { - // expected-note @+1 {{cannot differentiate unsupported control flow}} try! throwing() return x } func rethrowing(_ x: () throws -> Void) rethrows -> Void {} -// expected-error @+2 {{function is not differentiable}} -// expected-note @+2 {{when differentiating this function definition}} @differentiable func try_apply_rethrows(_ x: Float) -> Float { - // expected-note @+1 {{cannot differentiate unsupported control flow}} rethrowing({}) return x } @@ -307,14 +301,14 @@ struct TF_687 : Differentiable { } } // expected-error @+2 {{function is not differentiable}} -// expected-note @+1 {{cannot differentiate through a non-differentiable argument; do you want to use 'withoutDerivative(at:)'?}} +// expected-note @+1 {{cannot differentiate through a non-differentiable argument; do you want to use 'withoutDerivative(at:)'?}} {{78-78=withoutDerivative(at: }} {{79-79=)}} let _: @differentiable (Float) -> TF_687 = { x in TF_687(x, dummy: x) } // expected-error @+1 {{function is not differentiable}} @differentiable // expected-note @+1 {{when differentiating this function definition}} func roundingGivesError(x: Float) -> Float { - // expected-note @+1 {{cannot differentiate through a non-differentiable result; do you want to use 'withoutDerivative(at:)'?}} + // expected-note @+1 {{cannot differentiate through a non-differentiable result; do you want to use 'withoutDerivative(at:)'?}} {{16-16=withoutDerivative(at: }} {{22-22=)}} return Float(Int(x)) } @@ -694,7 +688,7 @@ func differentiableProjectedValueAccess(_ s: Struct) -> Float { // expected-note @+2 {{when differentiating this function definition}} @differentiable func projectedValueAccess(_ s: Struct) -> Float { - // expected-note @+1 {{cannot differentiate through a non-differentiable result; do you want to use 'withoutDerivative(at:)'?}} + // expected-note @+1 {{cannot differentiate through a non-differentiable result; do you want to use 'withoutDerivative(at:)'?}} {{3-3=withoutDerivative(at: }} {{7-7=)}} s.$y.wrappedValue } @@ -720,7 +714,7 @@ func modify(_ s: Struct, _ x: Float) -> Float { func tupleArrayLiteralInitialization(_ x: Float, _ y: Float) -> Float { // `Array<(Float, Float)>` does not conform to `Differentiable`. let array = [(x * y, x * y)] - // expected-note @+1 {{cannot differentiate through a non-differentiable argument; do you want to use 'withoutDerivative(at:)'?}} + // expected-note @+1 {{cannot differentiate through a non-differentiable argument; do you want to use 'withoutDerivative(at:)'?}} {{10-10=withoutDerivative(at: }} {{15-15=)}} return array[0].0 } diff --git a/test/AutoDiff/SILOptimizer/forward_mode_diagnostics.swift b/test/AutoDiff/SILOptimizer/forward_mode_diagnostics.swift index f028db4baca4f..ad21c18467142 100644 --- a/test/AutoDiff/SILOptimizer/forward_mode_diagnostics.swift +++ b/test/AutoDiff/SILOptimizer/forward_mode_diagnostics.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -enable-experimental-forward-mode-differentiation -emit-sil -verify %s +// RUN: %target-swift-frontend -emit-sil -enable-experimental-forward-mode-differentiation -verify %s // Test forward-mode differentiation transform diagnostics. @@ -46,8 +46,6 @@ func nonVariedResult(_ x: Float) -> Float { // Multiple results //===----------------------------------------------------------------------===// -// TODO(TF-983): Support differentiation of multiple results. -/* func multipleResults(_ x: Float) -> (Float, Float) { return (x, x) } @@ -56,28 +54,21 @@ func usesMultipleResults(_ x: Float) -> Float { let tuple = multipleResults(x) return tuple.0 + tuple.1 } -*/ //===----------------------------------------------------------------------===// // `inout` parameter differentiation //===----------------------------------------------------------------------===// -// expected-error @+1 {{function is not differentiable}} @differentiable -// expected-note @+1 {{when differentiating this function definition}} func activeInoutParamNonactiveInitialResult(_ x: Float) -> Float { var result: Float = 1 - // expected-note @+1 {{cannot differentiate through 'inout' arguments}} result += x return result } -// expected-error @+1 {{function is not differentiable}} @differentiable -// expected-note @+1 {{when differentiating this function definition}} func activeInoutParamTuple(_ x: Float) -> Float { var tuple = (x, x) - // expected-note @+1 {{cannot differentiate through 'inout' arguments}} tuple.0 *= x return x * tuple.0 } @@ -94,49 +85,37 @@ func activeInoutParamControlFlow(_ array: [Float]) -> Float { return result } -struct Mut: Differentiable {} -extension Mut { - @differentiable(wrt: x) - mutating func mutatingMethod(_ x: Mut) {} -} - // FIXME(TF-984): Forward-mode crash due to unset tangent buffer. /* -@differentiable(wrt: x) -func nonActiveInoutParam(_ nonactive: inout Mut, _ x: Mut) -> Mut { - return nonactive.mutatingMethod(x) +struct X: Differentiable { + var x : Float + + @differentiable(wrt: y) + mutating func mutate(_ y: X) { self.x = y.x } } -*/ -// FIXME(TF-984): Forward-mode crash due to unset tangent buffer. -/* -@differentiable(wrt: x) -func activeInoutParamMutatingMethod(_ x: Mut) -> Mut { - var result = x - result = result.mutatingMethod(result) - return result +@differentiable +func activeMutatingMethod(_ x: Float) -> Float { + let x1 = X.init(x: x) + var x2 = X.init(x: 0) + x2.mutate(x1) + return x1.x } */ -// FIXME(TF-984): Forward-mode crash due to unset tangent buffer. -/* -@differentiable(wrt: x) -func activeInoutParamMutatingMethodVar(_ nonactive: inout Mut, _ x: Mut) -> Mut { - var result = nonactive - result = result.mutatingMethod(x) - return result + +struct Mut: Differentiable {} +extension Mut { + @differentiable(wrt: x) + mutating func mutatingMethod(_ x: Mut) {} } -*/ -// FIXME(TF-984): Forward-mode crash due to unset tangent buffer. -/* @differentiable(wrt: x) -func activeInoutParamMutatingMethodTuple(_ nonactive: inout Mut, _ x: Mut) -> Mut { - var result = (nonactive, x) - let result2 = result.0.mutatingMethod(result.0) - return result2 +func activeInoutParamMutatingMethod(_ x: Mut) -> Mut { + var result = x + result.mutatingMethod(result) + return result } -*/ //===----------------------------------------------------------------------===// // Subset parameter differentiation thunks diff --git a/test/AutoDiff/Sema/DerivedConformances/class_differentiable.swift b/test/AutoDiff/Sema/DerivedConformances/class_differentiable.swift index 4b1110b39636e..f4b50fb19fa21 100644 --- a/test/AutoDiff/Sema/DerivedConformances/class_differentiable.swift +++ b/test/AutoDiff/Sema/DerivedConformances/class_differentiable.swift @@ -570,8 +570,10 @@ class WrappedProperties: Differentiable { // Test derived conformances in disallowed contexts. -// expected-error @+1 2 {{implementation of 'Differentiable' cannot be automatically synthesized in an extension in a different file to the type}} extension OtherFileNonconforming: Differentiable {} +// expected-error @-1 {{extension outside of file declaring class 'OtherFileNonconforming' prevents automatic synthesis of 'move(along:)' for protocol 'Differentiable'}} +// expected-error @-2 {{extension outside of file declaring class 'OtherFileNonconforming' prevents automatic synthesis of 'zeroTangentVectorInitializer' for protocol 'Differentiable'}} -// expected-error @+1 2 {{implementation of 'Differentiable' cannot be automatically synthesized in an extension in a different file to the type}} extension GenericOtherFileNonconforming: Differentiable {} +// expected-error @-1 {{extension outside of file declaring generic class 'GenericOtherFileNonconforming' prevents automatic synthesis of 'move(along:)' for protocol 'Differentiable'}} +// expected-error @-2 {{extension outside of file declaring generic class 'GenericOtherFileNonconforming' prevents automatic synthesis of 'zeroTangentVectorInitializer' for protocol 'Differentiable'}} diff --git a/test/AutoDiff/Sema/DerivedConformances/struct_additive_arithmetic.swift b/test/AutoDiff/Sema/DerivedConformances/struct_additive_arithmetic.swift index f6958318df05e..993be5409c16f 100644 --- a/test/AutoDiff/Sema/DerivedConformances/struct_additive_arithmetic.swift +++ b/test/AutoDiff/Sema/DerivedConformances/struct_additive_arithmetic.swift @@ -113,8 +113,12 @@ where T: AdditiveArithmetic {} // Test derived conformances in disallowed contexts. -// expected-error @+1 3 {{implementation of 'AdditiveArithmetic' cannot be automatically synthesized in an extension in a different file to the type}} extension OtherFileNonconforming: AdditiveArithmetic {} +// expected-error @-1 {{extension outside of file declaring struct 'OtherFileNonconforming' prevents automatic synthesis of 'zero' for protocol 'AdditiveArithmetic'}} +// expected-error @-2 {{extension outside of file declaring struct 'OtherFileNonconforming' prevents automatic synthesis of '+' for protocol 'AdditiveArithmetic'}} +// expected-error @-3 {{extension outside of file declaring struct 'OtherFileNonconforming' prevents automatic synthesis of '-' for protocol 'AdditiveArithmetic'}} -// expected-error @+1 3 {{implementation of 'AdditiveArithmetic' cannot be automatically synthesized in an extension in a different file to the type}} extension GenericOtherFileNonconforming: AdditiveArithmetic {} +// expected-error @-1 {{extension outside of file declaring generic struct 'GenericOtherFileNonconforming' prevents automatic synthesis of 'zero' for protocol 'AdditiveArithmetic'}} +// expected-error @-2 {{extension outside of file declaring generic struct 'GenericOtherFileNonconforming' prevents automatic synthesis of '+' for protocol 'AdditiveArithmetic'}} +// expected-error @-3 {{extension outside of file declaring generic struct 'GenericOtherFileNonconforming' prevents automatic synthesis of '-' for protocol 'AdditiveArithmetic'}} diff --git a/test/AutoDiff/Sema/DerivedConformances/struct_differentiable.swift b/test/AutoDiff/Sema/DerivedConformances/struct_differentiable.swift index 02f9154426cf4..e75b2730232f5 100644 --- a/test/AutoDiff/Sema/DerivedConformances/struct_differentiable.swift +++ b/test/AutoDiff/Sema/DerivedConformances/struct_differentiable.swift @@ -383,8 +383,10 @@ struct WrappedProperties: Differentiable { // Verify that cross-file derived conformances are disallowed. -// expected-error @+1 2 {{implementation of 'Differentiable' cannot be automatically synthesized in an extension in a different file to the type}} extension OtherFileNonconforming: Differentiable {} +// expected-error @-1 {{extension outside of file declaring struct 'OtherFileNonconforming' prevents automatic synthesis of 'move(along:)' for protocol 'Differentiable'}} +// expected-error @-2 {{extension outside of file declaring struct 'OtherFileNonconforming' prevents automatic synthesis of 'zeroTangentVectorInitializer' for protocol 'Differentiable'}} -// expected-error @+1 2 {{implementation of 'Differentiable' cannot be automatically synthesized in an extension in a different file to the type}} extension GenericOtherFileNonconforming: Differentiable {} +// expected-error @-1 {{extension outside of file declaring generic struct 'GenericOtherFileNonconforming' prevents automatic synthesis of 'move(along:)' for protocol 'Differentiable'}} +// expected-error @-2 {{extension outside of file declaring generic struct 'GenericOtherFileNonconforming' prevents automatic synthesis of 'zeroTangentVectorInitializer' for protocol 'Differentiable'}} diff --git a/test/AutoDiff/compiler_crashers_fixed/sr13411-tangent-value-category-mismatch.swift b/test/AutoDiff/compiler_crashers_fixed/sr13411-tangent-value-category-mismatch.swift new file mode 100644 index 0000000000000..a7678c55ffd6e --- /dev/null +++ b/test/AutoDiff/compiler_crashers_fixed/sr13411-tangent-value-category-mismatch.swift @@ -0,0 +1,12 @@ +// RUN: %target-build-swift %s +// REQUIRES: asserts + +// SR-13411: Semantic member getter pullback generation crash due to tangent value category mismatch + +import _Differentiation + +struct Dense: Differentiable { + @differentiable + var bias: Float? +} + diff --git a/test/AutoDiff/validation-test/control_flow.swift b/test/AutoDiff/validation-test/control_flow.swift index d2042a1135216..ea3dff8e0ba2a 100644 --- a/test/AutoDiff/validation-test/control_flow.swift +++ b/test/AutoDiff/validation-test/control_flow.swift @@ -736,4 +736,85 @@ ControlFlowTests.test("BranchingCastInstructions") { expectEqual((3, 1), valueWithGradient(at: Float(3), in: conditionalCast)) } +ControlFlowTests.test("ThrowingCalls") { + // TF-433: Test non-active `try_apply` differentiation. + func throwing() throws -> Void {} + + @differentiable + func testThrowing(_ x: Float) -> Float { + try! throwing() + return x + } + expectEqual(10, pullback(at: 3, in: testThrowing)(10)) + + @differentiable + func testThrowingGeneric(_ x: T) -> T { + try! throwing() + return x + } + expectEqual(10, pullback(at: 3, in: testThrowingGeneric)(10)) + + func rethrowing(_ body: () throws -> Void) rethrows -> Void {} + + @differentiable + func testRethrowingIdentity(_ x: Float) -> Float { + rethrowing({}) // non-active `try_apply` + return x + } + expectEqual(10, pullback(at: 3, in: testRethrowingIdentity)(10)) + + @differentiable + func testRethrowingIdentityGeneric(_ x: T) -> T { + rethrowing({}) // non-active `try_apply` + return x + } + expectEqual(10, pullback(at: 3, in: testRethrowingIdentityGeneric)(10)) + + @differentiable + func testComplexControlFlow(_ x: Float) -> Float { + rethrowing({}) + for _ in 0..(_ x: T) -> T { + rethrowing({}) + for _ in 0..<10 { + if true { + rethrowing({}) + } + rethrowing({}) // non-active `try_apply` + } + rethrowing({}) + return x + } + expectEqual(10, pullback(at: 3, in: testComplexControlFlowGeneric)(10)) + + // Test `Array.map(_:)`, which is rethrowing. + func testArrayMap(_ x: [Float]) -> [Float] { + let max = x.map { $0 }.max()! // non-active `try_apply` + _blackHole(max) + return x + } + expectEqual([10, 10], pullback(at: [2, 3], in: testArrayMap)([10, 10])) + + // Test `Bool.&&(_:)`, which is rethrowing. + func testBooleanShortCircuitingOperations(_ x: Float, bool: Bool) -> Float { + if bool && bool || bool { // non-active `try_apply` + return x * x + } + return x + x + } + expectEqual(6, gradient(at: 3, in: { x in testBooleanShortCircuitingOperations(x, bool: true) })) + expectEqual(2, gradient(at: 3, in: { x in testBooleanShortCircuitingOperations(x, bool: false) })) +} + runAllTests() diff --git a/test/AutoDiff/validation-test/forward_mode_inout.swift b/test/AutoDiff/validation-test/forward_mode_inout.swift new file mode 100644 index 0000000000000..42ed40a89c6ca --- /dev/null +++ b/test/AutoDiff/validation-test/forward_mode_inout.swift @@ -0,0 +1,161 @@ +// RUN: %target-run-simple-swift(-Xfrontend -enable-experimental-forward-mode-differentiation) +// REQUIRES: executable_test + +import StdlibUnittest +import DifferentiationUnittest + +var ForwardModeInoutTests = TestSuite("ForwardModeInoutDifferentiation") + +//===----------------------------------------------------------------------===// +// Inout tests. +//===----------------------------------------------------------------------===// + +import DifferentiationUnittest +import StdlibUnittest + +ForwardModeInoutTests.test("Float.+=") { + func mutatingAddWrapper(_ x: Float, _ y: Float) -> Float { + var result: Float = x + result += y + return result + } + expectEqual(20, differential(at: 4, 5, in: mutatingAddWrapper)(10, 10)) +} + +ForwardModeInoutTests.test("Float.-=") { + func mutatingSubtractWrapper(_ x: Float, _ y: Float) -> Float { + var result: Float = x + result -= y + return result + } + expectEqual(0, differential(at: 4, 5, in: mutatingSubtractWrapper)(10, 10)) + expectEqual(10, differential(at: 4, 5, in: mutatingSubtractWrapper)(20, 10)) +} + +ForwardModeInoutTests.test("Float.*=") { + func mutatingMultiplyWrapper(_ x: Float, _ y: Float) -> Float { + var result: Float = x + result *= y + return result + } + expectEqual(22, differential(at: 4, 5, in: mutatingMultiplyWrapper)(2, 3)) +} + +ForwardModeInoutTests.test("Float./=") { + func mutatingDivideWrapper(_ x: Float, _ y: Float) -> Float { + var result: Float = x + result /= y + return result + } + expectEqual(-1, differential(at: 2, 3, in: mutatingDivideWrapper)(3, 9)) +} + +// Simplest possible `inout` parameter differentiation. +ForwardModeInoutTests.test("InoutIdentity") { + // Semantically, an empty function with an `inout` parameter is an identity + // function. + func inoutIdentity(_ x: inout Float) {} + + func identity(_ x: Float) -> Float { + var result = x + inoutIdentity(&result) + return result + } + expectEqual(1, derivative(at: 10, in: identity)) + expectEqual(10, differential(at: 10, in: identity)(10)) + + func inoutIdentityGeneric(_ x: inout T) {} + + func identityGeneric(_ x: T) -> T { + var result: T = x + inoutIdentityGeneric(&result) + return result + } + expectEqual(1, derivative(at: 10.0, in: identityGeneric)) + expectEqual(10, differential(at: 10.0, in: identityGeneric)(10)) +} + +ForwardModeInoutTests.test("MultipleInoutParams") { + func swap(_ x: inout T, _ y: inout T) { + let z = x + x = y + y = z + } + + func first(_ x: T, _ y: T) -> T { + var p1 = x + var p2 = y + swap(&p1, &p2) + return p2 + } + expectEqual(1, differential(at: 1, 1, in: first)(1, 2)) + + func second(_ x: T, _ y: T) -> T { + var p1 = x + var p2 = y + swap(&p1, &p2) + return p1 + } + expectEqual(2, differential(at: 1, 1, in: second)(1, 2)) +} + +ForwardModeInoutTests.test("StructMutatingMethod") { + struct Mut: Differentiable { + var x: Float + + mutating func add(_ y: Float) { + self.x += y + } + + mutating func addMut(_ m: Mut) { + self.x += m.x + } + } + + func identity(_ y: Float) -> Float { + var mut = Mut(x: 0.0) + mut.add(y) + return mut.x + } + expectEqual(1, derivative(at: 1, in: identity)) + + func identity2(_ y: Float) -> Float { + var mut = Mut(x: 0.0) + let mut2 = Mut(x: y) + mut.addMut(mut2) + return mut.x + } + expectEqual(1, derivative(at: 1, in: identity2)) + + func double(_ y: Float) -> Float { + var mut = Mut(x: y) + mut.add(y) + return mut.x + } + expectEqual(2, derivative(at: 1, in: double)) + + func double2(_ y: Float) -> Float { + var mut = Mut(x: y) + let mut2 = Mut(x: y) + mut.addMut(mut2) + return mut.x + } + expectEqual(2, derivative(at: 1, in: double2)) + + func square(_ y: Float) -> Float { + var mut = Mut(x: 0.0) + mut.add(y * y) + return mut.x + } + expectEqual(6, derivative(at: 3, in: square)) + + func square2(_ y: Float) -> Float { + var mut = Mut(x: 0.0) + let mut2 = Mut(x: y * y) + mut.addMut(mut2) + return mut.x + } + expectEqual(6, derivative(at: 3, in: square2)) +} + +runAllTests() diff --git a/test/AutoDiff/validation-test/inout_parameters.swift b/test/AutoDiff/validation-test/inout_parameters.swift index 4cbd25590b943..626546040a900 100644 --- a/test/AutoDiff/validation-test/inout_parameters.swift +++ b/test/AutoDiff/validation-test/inout_parameters.swift @@ -1,11 +1,174 @@ // RUN: %target-run-simple-swift // REQUIRES: executable_test +// `inout` parameter differentiation tests. + import DifferentiationUnittest import StdlibUnittest var InoutParameterAutoDiffTests = TestSuite("InoutParameterDifferentiation") +// TODO(TF-1173): Move floating-point mutating operation tests to +// `test/AutoDiff/stdlib/floating_point.swift.gyb` when forward-mode +// differentiation supports `inout` parameter differentiation. + +InoutParameterAutoDiffTests.test("Float.+=") { + func mutatingAddWrapper(_ x: Float, _ y: Float) -> Float { + var result: Float = x + result += y + return result + } + expectEqual((1, 1), gradient(at: 4, 5, in: mutatingAddWrapper)) + expectEqual((10, 10), pullback(at: 4, 5, in: mutatingAddWrapper)(10)) +} + +InoutParameterAutoDiffTests.test("Float.-=") { + func mutatingSubtractWrapper(_ x: Float, _ y: Float) -> Float { + var result: Float = x + result += y + return result + } + expectEqual((1, 1), gradient(at: 4, 5, in: mutatingSubtractWrapper)) + expectEqual((10, 10), pullback(at: 4, 5, in: mutatingSubtractWrapper)(10)) +} + +InoutParameterAutoDiffTests.test("Float.*=") { + func mutatingMultiplyWrapper(_ x: Float, _ y: Float) -> Float { + var result: Float = x + result += y + return result + } + expectEqual((1, 1), gradient(at: 4, 5, in: mutatingMultiplyWrapper)) + expectEqual((10, 10), pullback(at: 4, 5, in: mutatingMultiplyWrapper)(10)) +} + +InoutParameterAutoDiffTests.test("Float./=") { + func mutatingDivideWrapper(_ x: Float, _ y: Float) -> Float { + var result: Float = x + result += y + return result + } + expectEqual((1, 1), gradient(at: 4, 5, in: mutatingDivideWrapper)) + expectEqual((10, 10), pullback(at: 4, 5, in: mutatingDivideWrapper)(10)) +} + +// Simplest possible `inout` parameter differentiation. +InoutParameterAutoDiffTests.test("InoutIdentity") { + // Semantically, an empty function with an `inout` parameter is an identity + // function. + func inoutIdentity(_ x: inout Float) {} + + func identity(_ x: Float) -> Float { + var result = x + inoutIdentity(&result) + return result + } + expectEqual(1, gradient(at: 10, in: identity)) + expectEqual(10, pullback(at: 10, in: identity)(10)) +} + +extension Float { + // Custom version of `Float.*=`, implemented using `Float.*` and mutation. + // Verify that its generated derivative has the same behavior as the + // registered derivative for `Float.*=`. + @differentiable + static func multiplyAssign(_ lhs: inout Float, _ rhs: Float) { + lhs = lhs * rhs + } +} + +InoutParameterAutoDiffTests.test("ControlFlow") { + func sum(_ array: [Float]) -> Float { + var result: Float = 0 + for i in withoutDerivative(at: array.indices) { + result += array[i] + } + return result + } + expectEqual([1, 1, 1], gradient(at: [1, 2, 3], in: sum)) + + func product(_ array: [Float]) -> Float { + var result: Float = 1 + for i in withoutDerivative(at: array.indices) { + result *= array[i] + } + return result + } + expectEqual([20, 15, 12], gradient(at: [3, 4, 5], in: product)) + + func productCustom(_ array: [Float]) -> Float { + var result: Float = 1 + for i in withoutDerivative(at: array.indices) { + Float.multiplyAssign(&result, array[i]) + } + return result + } + expectEqual([20, 15, 12], gradient(at: [3, 4, 5], in: productCustom)) +} + +InoutParameterAutoDiffTests.test("SetAccessor") { + struct S: Differentiable { + var x: Float + + var computed: Float { + get { x } + set { x = newValue } + } + } + + // `squared` implemented using a `set` accessor. + func squared(_ x: Float) -> Float { + var s = S(x: 1) + s.x *= x + s.computed *= x + return s.x + } + expectEqual(6, gradient(at: 3, in: squared)) + expectEqual(8, gradient(at: 4, in: squared)) +} + +// Test differentiation wrt `inout` parameters that have a class type. +InoutParameterAutoDiffTests.test("InoutClassParameter") { + class Class: Differentiable { + @differentiable + var x: Float + + init(_ x: Float) { + self.x = x + } + } + + do { + func squaredViaMutation(_ c: inout Class) { + c = Class(c.x * c.x) + } + func squared(_ x: Float) -> Float { + var c = Class(x) + squaredViaMutation(&c) + return c.x + } + expectEqual((100, 20), valueWithGradient(at: 10, in: squared)) + expectEqual(200, pullback(at: 10, in: squared)(10)) + } + + do { + func squaredViaModifyAccessor(_ c: inout Class) { + // The line below calls `Class.x.modify`. + c.x *= c.x + } + func squared(_ x: Float) -> Float { + var c = Class(x) + squaredViaModifyAccessor(&c) + return c.x + } + // FIXME(TF-1080): Fix incorrect class property `modify` accessor derivative values. + // expectEqual((100, 20), valueWithGradient(at: 10, in: squared)) + // expectEqual(200, pullback(at: 10, in: squared)(10)) + expectEqual((100, 1), valueWithGradient(at: 10, in: squared)) + expectEqual(10, pullback(at: 10, in: squared)(10)) + } +} + // SR-13305: Test function with non-wrt `inout` parameter, which should be // treated as a differentiability result. diff --git a/test/AutoDiff/validation-test/optional.swift b/test/AutoDiff/validation-test/optional.swift index c2fc0fac4a695..455fa091e9e67 100644 --- a/test/AutoDiff/validation-test/optional.swift +++ b/test/AutoDiff/validation-test/optional.swift @@ -1,8 +1,8 @@ // RUN: %target-run-simple-swift // REQUIRES: executable_test -import StdlibUnittest import DifferentiationUnittest +import StdlibUnittest var OptionalTests = TestSuite("OptionalDifferentiation") @@ -10,11 +10,11 @@ var OptionalTests = TestSuite("OptionalDifferentiation") // Basic tests. //===----------------------------------------------------------------------===// + +// TODO(TF-433): operator `??` lowers to an active `try_apply`. /* -// TODO(TF-433): operator `??` lowers to `try_apply` instead of `switch_enum`, -// which is not yet supported by differentiation. @differentiable -func optional1(_ maybeX: Float?) -> Float { +func optional_nil_coalescing(_ maybeX: Float?) -> Float { return maybeX ?? 10 } */ @@ -23,7 +23,7 @@ OptionalTests.test("Let") { @differentiable func optional_let(_ maybeX: Float?) -> Float { if let x = maybeX { - return x * x + return x * x } return 10 } @@ -33,13 +33,27 @@ OptionalTests.test("Let") { @differentiable func optional_let_tracked(_ maybeX: Tracked?) -> Tracked { if let x = maybeX { - return x * x + return x * x } return 10 } expectEqual(gradient(at: 10, in: optional_let_tracked), .init(20.0)) expectEqual(gradient(at: nil, in: optional_let_tracked), .init(0.0)) + @differentiable + func optional_let_nonresilient_tracked(_ maybeX: NonresilientTracked?) + -> NonresilientTracked + { + if let x = maybeX { + return x * x + } + return 10 + } + expectEqual( + gradient(at: 10, in: optional_let_nonresilient_tracked), .init(20.0)) + expectEqual( + gradient(at: nil, in: optional_let_nonresilient_tracked), .init(0.0)) + @differentiable func optional_let_nested(_ nestedMaybeX: Float??) -> Float { if let maybeX = nestedMaybeX { @@ -54,7 +68,26 @@ OptionalTests.test("Let") { expectEqual(gradient(at: nil, in: optional_let_nested), .init(.init(0.0))) @differentiable - func optional_let_nested_tracked(_ nestedMaybeX: Tracked??) -> Tracked { + func optional_let_nested_tracked(_ nestedMaybeX: Tracked??) -> Tracked< + Float + > { + if let maybeX = nestedMaybeX { + if let x = maybeX { + return x * x + } + return 10 + } + return 10 + } + expectEqual( + gradient(at: 10, in: optional_let_nested_tracked), .init(.init(20.0))) + expectEqual( + gradient(at: nil, in: optional_let_nested_tracked), .init(.init(0.0))) + + @differentiable + func optional_let_nested_nonresilient_tracked( + _ nestedMaybeX: NonresilientTracked?? + ) -> NonresilientTracked { if let maybeX = nestedMaybeX { if let x = maybeX { return x * x @@ -63,24 +96,38 @@ OptionalTests.test("Let") { } return 10 } - expectEqual(gradient(at: 10, in: optional_let_nested_tracked), .init(.init(20.0))) - expectEqual(gradient(at: nil, in: optional_let_nested_tracked), .init(.init(0.0))) + expectEqual( + gradient(at: 10, in: optional_let_nested_nonresilient_tracked), + .init(.init(20.0))) + expectEqual( + gradient(at: nil, in: optional_let_nested_nonresilient_tracked), + .init(.init(0.0))) @differentiable - func optional_let_generic(_ maybeX: T?, _ defaultValue: T) -> T { + func optional_let_generic(_ maybeX: T?, _ defaultValue: T) + -> T + { if let x = maybeX { - return x + return x } return defaultValue } expectEqual(gradient(at: 10, 20, in: optional_let_generic), (.init(1.0), 0.0)) - expectEqual(gradient(at: nil, 20, in: optional_let_generic), (.init(0.0), 1.0)) + expectEqual( + gradient(at: nil, 20, in: optional_let_generic), (.init(0.0), 1.0)) - expectEqual(gradient(at: Tracked.init(10), Tracked.init(20), in: optional_let_generic), (.init(1.0), 0.0)) - expectEqual(gradient(at: nil, Tracked.init(20), in: optional_let_generic), (.init(0.0), 1.0)) + expectEqual( + gradient( + at: Tracked.init(10), Tracked.init(20), + in: optional_let_generic), (.init(1.0), 0.0)) + expectEqual( + gradient(at: nil, Tracked.init(20), in: optional_let_generic), + (.init(0.0), 1.0)) @differentiable - func optional_let_nested_generic(_ nestedMaybeX: T??, _ defaultValue: T) -> T { + func optional_let_nested_generic( + _ nestedMaybeX: T??, _ defaultValue: T + ) -> T { if let maybeX = nestedMaybeX { if let x = maybeX { return x @@ -90,8 +137,12 @@ OptionalTests.test("Let") { return defaultValue } - expectEqual(gradient(at: 10.0, 20.0, in: optional_let_nested_generic), (.init(.init(1.0)), 0.0)) - expectEqual(gradient(at: nil, 20, in: optional_let_nested_generic), (.init(.init(0.0)), 1.0)) + expectEqual( + gradient(at: 10.0, 20.0, in: optional_let_nested_generic), + (.init(.init(1.0)), 0.0)) + expectEqual( + gradient(at: nil, 20, in: optional_let_nested_generic), + (.init(.init(0.0)), 1.0)) } OptionalTests.test("Switch") { @@ -115,14 +166,28 @@ OptionalTests.test("Switch") { expectEqual(gradient(at: 10, in: optional_switch_tracked), .init(20.0)) expectEqual(gradient(at: nil, in: optional_switch_tracked), .init(0.0)) + @differentiable + func optional_switch_nonresilient_tracked( + _ maybeX: NonresilientTracked? + ) -> NonresilientTracked { + switch maybeX { + case nil: return 10 + case let .some(x): return x * x + } + } + expectEqual( + gradient(at: 10, in: optional_switch_nonresilient_tracked), .init(20.0)) + expectEqual( + gradient(at: nil, in: optional_switch_nonresilient_tracked), .init(0.0)) + @differentiable func optional_switch_nested(_ nestedMaybeX: Float??) -> Float { switch nestedMaybeX { case nil: return 10 case let .some(maybeX): switch maybeX { - case nil: return 10 - case let .some(x): return x * x + case nil: return 10 + case let .some(x): return x * x } } } @@ -130,42 +195,76 @@ OptionalTests.test("Switch") { expectEqual(gradient(at: nil, in: optional_switch_nested), .init(.init(0.0))) @differentiable - func optional_switch_nested_tracked(_ nestedMaybeX: Tracked??) -> Tracked { + func optional_switch_nested_tracked(_ nestedMaybeX: Tracked??) + -> Tracked + { + switch nestedMaybeX { + case nil: return 10 + case let .some(maybeX): + switch maybeX { + case nil: return 10 + case let .some(x): return x * x + } + } + } + expectEqual( + gradient(at: 10, in: optional_switch_nested_tracked), .init(.init(20.0))) + expectEqual( + gradient(at: nil, in: optional_switch_nested_tracked), .init(.init(0.0))) + + @differentiable + func optional_switch_nested_nonresilient_tracked( + _ nestedMaybeX: NonresilientTracked?? + ) -> NonresilientTracked { switch nestedMaybeX { case nil: return 10 case let .some(maybeX): switch maybeX { - case nil: return 10 - case let .some(x): return x * x + case nil: return 10 + case let .some(x): return x * x } } } - expectEqual(gradient(at: 10, in: optional_switch_nested_tracked), .init(.init(20.0))) - expectEqual(gradient(at: nil, in: optional_switch_nested_tracked), .init(.init(0.0))) + expectEqual( + gradient(at: 10, in: optional_switch_nested_nonresilient_tracked), + .init(.init(20.0))) + expectEqual( + gradient(at: nil, in: optional_switch_nested_nonresilient_tracked), + .init(.init(0.0))) @differentiable - func optional_switch_generic(_ maybeX: T?, _ defaultValue: T) -> T { + func optional_switch_generic( + _ maybeX: T?, _ defaultValue: T + ) -> T { switch maybeX { case nil: return defaultValue case let .some(x): return x } } - expectEqual(gradient(at: 10, 20, in: optional_switch_generic), (.init(1.0), 0.0)) - expectEqual(gradient(at: nil, 20, in: optional_switch_generic), (.init(0.0), 1.0)) + expectEqual( + gradient(at: 10, 20, in: optional_switch_generic), (.init(1.0), 0.0)) + expectEqual( + gradient(at: nil, 20, in: optional_switch_generic), (.init(0.0), 1.0)) @differentiable - func optional_switch_nested_generic(_ nestedMaybeX: T??, _ defaultValue: T) -> T { + func optional_switch_nested_generic( + _ nestedMaybeX: T??, _ defaultValue: T + ) -> T { switch nestedMaybeX { case nil: return defaultValue case let .some(maybeX): switch maybeX { - case nil: return defaultValue - case let .some(x): return x + case nil: return defaultValue + case let .some(x): return x } } } - expectEqual(gradient(at: 10, 20, in: optional_switch_nested_generic), (.init(.init(1.0)), 0.0)) - expectEqual(gradient(at: nil, 20, in: optional_switch_nested_generic), (.init(.init(0.0)), 1.0)) + expectEqual( + gradient(at: 10, 20, in: optional_switch_nested_generic), + (.init(.init(1.0)), 0.0)) + expectEqual( + gradient(at: nil, 20, in: optional_switch_nested_generic), + (.init(.init(0.0)), 1.0)) } OptionalTests.test("Var1") { @@ -173,7 +272,7 @@ OptionalTests.test("Var1") { func optional_var1(_ maybeX: Float?) -> Float { var maybeX = maybeX if let x = maybeX { - return x * x + return x * x } return 10 } @@ -184,13 +283,28 @@ OptionalTests.test("Var1") { func optional_var1_tracked(_ maybeX: Tracked?) -> Tracked { var maybeX = maybeX if let x = maybeX { - return x * x + return x * x } return 10 } expectEqual(gradient(at: 10, in: optional_var1_tracked), .init(20.0)) expectEqual(gradient(at: nil, in: optional_var1_tracked), .init(0.0)) + @differentiable + func optional_var1_nonresilient_tracked(_ maybeX: NonresilientTracked?) + -> NonresilientTracked + { + var maybeX = maybeX + if let x = maybeX { + return x * x + } + return 10 + } + expectEqual( + gradient(at: 10, in: optional_var1_nonresilient_tracked), .init(20.0)) + expectEqual( + gradient(at: nil, in: optional_var1_nonresilient_tracked), .init(0.0)) + @differentiable func optional_var1_nested(_ nestedMaybeX: Float??) -> Float { var nestedMaybeX = nestedMaybeX @@ -206,7 +320,27 @@ OptionalTests.test("Var1") { expectEqual(gradient(at: nil, in: optional_var1_nested), .init(.init(0.0))) @differentiable - func optional_var1_nested_tracked(_ nestedMaybeX: Tracked??) -> Tracked { + func optional_var1_nested_tracked(_ nestedMaybeX: Tracked??) + -> Tracked + { + var nestedMaybeX = nestedMaybeX + if let maybeX = nestedMaybeX { + if var x = maybeX { + return x * x + } + return 10 + } + return 10 + } + expectEqual( + gradient(at: 10, in: optional_var1_nested_tracked), .init(.init(20.0))) + expectEqual( + gradient(at: nil, in: optional_var1_nested_tracked), .init(.init(0.0))) + + @differentiable + func optional_var1_nested_nonresilient_tracked( + _ nestedMaybeX: NonresilientTracked?? + ) -> NonresilientTracked { var nestedMaybeX = nestedMaybeX if let maybeX = nestedMaybeX { if var x = maybeX { @@ -216,22 +350,32 @@ OptionalTests.test("Var1") { } return 10 } - expectEqual(gradient(at: 10, in: optional_var1_nested_tracked), .init(.init(20.0))) - expectEqual(gradient(at: nil, in: optional_var1_nested_tracked), .init(.init(0.0))) + expectEqual( + gradient(at: 10, in: optional_var1_nested_nonresilient_tracked), + .init(.init(20.0))) + expectEqual( + gradient(at: nil, in: optional_var1_nested_nonresilient_tracked), + .init(.init(0.0))) @differentiable - func optional_var1_generic(_ maybeX: T?, _ defaultValue: T) -> T { + func optional_var1_generic(_ maybeX: T?, _ defaultValue: T) + -> T + { var maybeX = maybeX if let x = maybeX { - return x + return x } return defaultValue } - expectEqual(gradient(at: 10, 20, in: optional_var1_generic), (.init(1.0), 0.0)) - expectEqual(gradient(at: nil, 20, in: optional_var1_generic), (.init(0.0), 1.0)) + expectEqual( + gradient(at: 10, 20, in: optional_var1_generic), (.init(1.0), 0.0)) + expectEqual( + gradient(at: nil, 20, in: optional_var1_generic), (.init(0.0), 1.0)) @differentiable - func optional_var1_nested_generic(_ nestedMaybeX: T??, _ defaultValue: T) -> T { + func optional_var1_nested_generic( + _ nestedMaybeX: T??, _ defaultValue: T + ) -> T { var nestedMaybeX = nestedMaybeX if let maybeX = nestedMaybeX { if var x = maybeX { @@ -241,8 +385,12 @@ OptionalTests.test("Var1") { } return defaultValue } - expectEqual(gradient(at: 10, 20, in: optional_var1_nested_generic), (.init(.init(1.0)), 0.0)) - expectEqual(gradient(at: nil, 20, in: optional_var1_nested_generic), (.init(.init(0.0)), 1.0)) + expectEqual( + gradient(at: 10, 20, in: optional_var1_nested_generic), + (.init(.init(1.0)), 0.0)) + expectEqual( + gradient(at: nil, 20, in: optional_var1_nested_generic), + (.init(.init(0.0)), 1.0)) } OptionalTests.test("Var2") { @@ -266,6 +414,20 @@ OptionalTests.test("Var2") { expectEqual(gradient(at: 10, in: optional_var2_tracked), .init(20.0)) expectEqual(gradient(at: nil, in: optional_var2_tracked), .init(0.0)) + @differentiable + func optional_var2_nonresilient_tracked(_ maybeX: NonresilientTracked?) + -> NonresilientTracked + { + if var x = maybeX { + return x * x + } + return 10 + } + expectEqual( + gradient(at: 10, in: optional_var2_nonresilient_tracked), .init(20.0)) + expectEqual( + gradient(at: nil, in: optional_var2_nonresilient_tracked), .init(0.0)) + @differentiable func optional_var2_nested(_ nestedMaybeX: Float??) -> Float { if var maybeX = nestedMaybeX { @@ -280,7 +442,26 @@ OptionalTests.test("Var2") { expectEqual(gradient(at: nil, in: optional_var2_nested), .init(.init(0.0))) @differentiable - func optional_var2_nested_tracked(_ nestedMaybeX: Tracked??) -> Tracked { + func optional_var2_nested_tracked(_ nestedMaybeX: Tracked??) + -> Tracked + { + if var maybeX = nestedMaybeX { + if var x = maybeX { + return x * x + } + return 10 + } + return 10 + } + expectEqual( + gradient(at: 10, in: optional_var2_nested_tracked), .init(.init(20.0))) + expectEqual( + gradient(at: nil, in: optional_var2_nested_tracked), .init(.init(0.0))) + + @differentiable + func optional_var2_nested_nonresilient_tracked( + _ nestedMaybeX: NonresilientTracked?? + ) -> NonresilientTracked { if var maybeX = nestedMaybeX { if var x = maybeX { return x * x @@ -289,21 +470,31 @@ OptionalTests.test("Var2") { } return 10 } - expectEqual(gradient(at: 10, in: optional_var2_nested_tracked), .init(.init(20.0))) - expectEqual(gradient(at: nil, in: optional_var2_nested_tracked), .init(.init(0.0))) + expectEqual( + gradient(at: 10, in: optional_var2_nested_nonresilient_tracked), + .init(.init(20.0))) + expectEqual( + gradient(at: nil, in: optional_var2_nested_nonresilient_tracked), + .init(.init(0.0))) @differentiable - func optional_var2_generic(_ maybeX: T?, _ defaultValue: T) -> T { + func optional_var2_generic(_ maybeX: T?, _ defaultValue: T) + -> T + { if var x = maybeX { return x } return defaultValue } - expectEqual(gradient(at: 10, 20, in: optional_var2_generic), (.init(1.0), 0.0)) - expectEqual(gradient(at: nil, 20, in: optional_var2_generic), (.init(0.0), 1.0)) + expectEqual( + gradient(at: 10, 20, in: optional_var2_generic), (.init(1.0), 0.0)) + expectEqual( + gradient(at: nil, 20, in: optional_var2_generic), (.init(0.0), 1.0)) @differentiable - func optional_var2_nested_generic(_ nestedMaybeX: T??, _ defaultValue: T) -> T { + func optional_var2_nested_generic( + _ nestedMaybeX: T??, _ defaultValue: T + ) -> T { if var maybeX = nestedMaybeX { if var x = maybeX { return x @@ -312,8 +503,12 @@ OptionalTests.test("Var2") { } return defaultValue } - expectEqual(gradient(at: 10, 20, in: optional_var2_nested_generic), (.init(.init(1.0)), 0.0)) - expectEqual(gradient(at: nil, 20, in: optional_var2_nested_generic), (.init(.init(0.0)), 1.0)) + expectEqual( + gradient(at: 10, 20, in: optional_var2_nested_generic), + (.init(.init(1.0)), 0.0)) + expectEqual( + gradient(at: nil, 20, in: optional_var2_nested_generic), + (.init(.init(0.0)), 1.0)) } runAllTests() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 858da28140d94..91d1d02d9e19a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -102,6 +102,7 @@ function(get_test_dependencies SDK result_var_name) ("${SDK}" STREQUAL "IOS_SIMULATOR") OR ("${SDK}" STREQUAL "TVOS_SIMULATOR") OR ("${SDK}" STREQUAL "WATCHOS_SIMULATOR") OR + ("${SDK}" STREQUAL "FREESTANDING") OR ("${SDK}" STREQUAL "LINUX") OR ("${SDK}" STREQUAL "CYGWIN") OR ("${SDK}" STREQUAL "FREEBSD") OR @@ -355,7 +356,7 @@ _Block_release(void) { }\n") endif() execute_process(COMMAND - $ "-c" "import psutil" + $ "-c" "import psutil" RESULT_VARIABLE python_psutil_status TIMEOUT 1 # second ERROR_QUIET) @@ -419,7 +420,7 @@ _Block_release(void) { }\n") ${command_upload_swift_reflection_test} ${command_clean_test_results_dir} COMMAND - $ "${LIT}" + $ "${LIT}" ${LIT_ARGS} "--param" "swift_test_subset=${test_subset}" "--param" "swift_test_mode=${test_mode}" @@ -438,7 +439,7 @@ _Block_release(void) { }\n") ${command_upload_swift_reflection_test} ${command_clean_test_results_dir} COMMAND - $ "${LIT}" + $ "${LIT}" ${LIT_ARGS} "--param" "swift_test_subset=${test_subset}" "--param" "swift_test_mode=${test_mode}" diff --git a/test/stdlib/CastTraps.swift.gyb b/test/Casting/CastTraps.swift.gyb similarity index 61% rename from test/stdlib/CastTraps.swift.gyb rename to test/Casting/CastTraps.swift.gyb index e5608874d028d..95c7cbbebfe31 100644 --- a/test/stdlib/CastTraps.swift.gyb +++ b/test/Casting/CastTraps.swift.gyb @@ -5,17 +5,17 @@ // FIXME: Casting.cpp has dozens of places to fail a cast. This test does not // attempt to enumerate them all. -// REQUIRES: objc_interop - import StdlibUnittest - +#if _runtime(_ObjC) import Foundation +#endif % types = [] % objectTypes = [] % protocolTypes = [] +% ObjCTypes = [] % types.append(['main.Class1', 'main.Class2']) % objectTypes.append(['main.Class1', 'main.Class2']) @@ -28,11 +28,15 @@ struct Struct2 { } % types.append(['main.ObjCClass1', 'main.ObjCClass2']) % objectTypes.append(['main.ObjCClass1', 'main.ObjCClass2']) +% ObjCTypes.extend(['main.ObjCClass1', 'main.ObjCClass2']) +#if _runtime(_ObjC) class ObjCClass1 : NSObject { } class ObjCClass2 : NSObject { } +#endif % types.append(['DateFormatter', 'NumberFormatter']) % objectTypes.append(['DateFormatter', 'NumberFormatter']) +% ObjCTypes.extend(['DateFormatter', 'NumberFormatter']) // non-Swift Objective-C class % protocolTypes.append('main.Proto1') @@ -40,6 +44,7 @@ class ObjCClass2 : NSObject { } protocol Proto1 { } protocol Proto2 { } % protocolTypes.append('URLSessionDelegate') +% ObjCTypes.append('URLSessionDelegate') // non-Swift Objective-C protocol @@ -51,6 +56,7 @@ var CastTrapsTestSuite = TestSuite("CastTraps") % for (t1, _) in types: % for (_, t2) in types: +% if t1 not in ObjCTypes and t2 not in ObjCTypes: CastTrapsTestSuite.test("${t1}__${t2}") .skip(.custom( { _isFastAssertConfiguration() }, @@ -67,6 +73,7 @@ CastTrapsTestSuite.test("${t1}__${t2}") _blackHole(r) } +% end % end % end @@ -76,6 +83,7 @@ CastTrapsTestSuite.test("${t1}__${t2}") % for (t1, _) in objectTypes: % for (t2) in protocolTypes: +% if t1 not in ObjCTypes and t2 not in ObjCTypes: CastTrapsTestSuite.test("${t1}__${t2}") .skip(.custom( { _isFastAssertConfiguration() }, @@ -92,7 +100,47 @@ CastTrapsTestSuite.test("${t1}__${t2}") _blackHole(r) } +% end % end % end +protocol P2 {} +if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) { +CastTrapsTestSuite.test("Unexpected null") + .crashOutputMatches("Found unexpected null pointer value while trying to cast value of type '") + .crashOutputMatches("Foo'") + .crashOutputMatches(" to '") + .crashOutputMatches("P2'") + .code +{ + class Foo {} + let n = UnsafeRawPointer(bitPattern: 0) + var o: Foo = unsafeBitCast(n, to: Foo.self) + let r = o as Any + expectCrashLater() + let s = r as? P2 + _blackHole(s) +} +} + + +#if _runtime(_ObjC) +if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) { +CastTrapsTestSuite.test("Unexpected Obj-C null") + .crashOutputMatches("Found unexpected null pointer value while trying to cast value of type '") + .crashOutputMatches("NSObject'") + .crashOutputMatches(" to '") + .crashOutputMatches("P2'") + .code +{ + let n = UnsafeRawPointer(bitPattern: 0) + var o: NSObject = unsafeBitCast(n, to: NSObject.self) + let r = o as Any + expectCrashLater() + let s = r as? P2 + _blackHole(s) +} +} +#endif + runAllTests() diff --git a/test/Casting/Casts.swift b/test/Casting/Casts.swift new file mode 100644 index 0000000000000..54eeef85adff6 --- /dev/null +++ b/test/Casting/Casts.swift @@ -0,0 +1,763 @@ +// Casts.swift - Tests for conversion between types. +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 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 +// +// ----------------------------------------------------------------------------- +/// +/// Contains tests for non-trapping type conversions reported by users. +/// +// ----------------------------------------------------------------------------- +// RUN: %empty-directory(%t) +// +// RUN: %target-build-swift -swift-version 5 -g -Onone -Xfrontend -enable-experimental-concurrency -module-name a %s -o %t/a.swift5.Onone.out +// RUN: %target-codesign %t/a.swift5.Onone.out +// RUN: %target-run %t/a.swift5.Onone.out +// +// RUN: %target-build-swift -swift-version 5 -g -O -Xfrontend -enable-experimental-concurrency -module-name a %s -o %t/a.swift5.O.out +// RUN: %target-codesign %t/a.swift5.O.out +// RUN: %target-run %t/a.swift5.O.out +// +// REQUIRES: executable_test +// UNSUPPORTED: use_os_stdlib + +import StdlibUnittest +#if _runtime(_ObjC) +import Foundation +#endif + +func blackhole(_ t: T) { } + +private func runtimeCast(_ from: T, to: U.Type) -> U? { + return from as? U +} + +let CastsTests = TestSuite("Casts") + +// Test for SR-426: missing release for some types after failed conversion +CastsTests.test("No leak for failed tuple casts") { + let t: Any = (1, LifetimeTracked(0)) + expectFalse(t is Any.Type) +} + +protocol P {} +class ErrClass : Error { } + +CastsTests.test("No overrelease of existential boxes in failed casts") { + // Test for crash from SR-392 + // We fail casts of an existential box repeatedly + // to ensure it does not get over-released. + func bar(_ t: T) { + for _ in 0..<10 { + if case let a as P = t { + _ = a + } + } + } + + let err: Error = ErrClass() + bar(err) +} + +extension Int : P {} + +// Test for SR-7664: Inconsistent optional casting behaviour with generics +// Runtime failed to unwrap multiple levels of Optional when casting. +CastsTests.test("Multi-level optionals can be casted") { + func testSuccess(_ x: From, from: From.Type, to: To.Type) { + expectNotNil(x as? To) + } + func testFailure(_ x: From, from: From.Type, to: To.Type) { + expectNil(x as? To) + } + testSuccess(42, from: Int?.self, to: Int.self) + testSuccess(42, from: Int??.self, to: Int.self) + testSuccess(42, from: Int???.self, to: Int.self) + testSuccess(42, from: Int???.self, to: Int?.self) + testSuccess(42, from: Int???.self, to: Int??.self) + testSuccess(42, from: Int???.self, to: Int???.self) + testFailure(42, from: Int?.self, to: String.self) + testFailure(42, from: Int??.self, to: String.self) + testFailure(42, from: Int???.self, to: String.self) +} + +// Test for SR-9837: Optional.none not casting to Optional.none in generic context +CastsTests.test("Optional.none can be casted to Optional.none in generic context") { + func test(_ type: T.Type) -> T? { + return Any?.none as? T + } + + expectEqual(type(of: test(Bool.self)), Bool?.self) + expectEqual(type(of: test(Bool?.self)), Bool??.self) +} + +// Test for SR-3871: Cannot cast from ObjC existential without going through AnyObject +#if _runtime(_ObjC) +protocol P2 {} +CastsTests.test("Cast from ObjC existential to Protocol (SR-3871)") { + if #available(macOS 10.16, iOS 14.0, watchOS 7.0, tvOS 14.0, *) { + struct S: P2 {} + + class ObjCWrapper { + @objc dynamic let any: Any = S() + init() {} + } + let a = ObjCWrapper().any + expectTrue(a is P2) + // In SR-3871, the following cast failed (everything else here succeeded) + expectNotNil(a as? P2) + expectNotNil(a as? S) + let b = a as AnyObject + expectTrue(a is P2) + expectNotNil(b as? P2) + expectNotNil(b as? S) + } +} +#endif + +protocol P3 {} +CastsTests.test("Cast from Swift existential to Protocol") { + struct S: P3 {} + class SwiftWrapper { + let any: Any = S() + init() {} + } + let a = SwiftWrapper().any + expectTrue(a is P3) + expectNotNil(a as? P3) + expectNotNil(a as? S) + let b = a as AnyObject + expectTrue(b is P3) + expectNotNil(b as? P3) + expectNotNil(b as? S) +} + + +#if _runtime(_ObjC) +extension CFBitVector : P { + static func makeImmutable(from values: Array) -> CFBitVector { + return CFBitVectorCreate(/*allocator:*/ nil, values, values.count * 8) + } +} + +extension CFMutableBitVector { + static func makeMutable(from values: Array) -> CFMutableBitVector { + return CFBitVectorCreateMutableCopy( + /*allocator:*/ nil, + /*capacity:*/ 0, + CFBitVector.makeImmutable(from: values)) + } +} + +func isP(_ t: T) -> Bool { + return t is P +} + +CastsTests.test("Dynamic casts of CF types to protocol existentials (SR-2289)") +.skip(.custom({ + !_isDebugAssertConfiguration() + }, + reason: "This test behaves unpredictably in optimized mode.")) +.code { + expectTrue(isP(10 as Int)) + if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) { + expectTrue(isP(CFBitVector.makeImmutable(from: [10, 20]))) + expectTrue(isP(CFMutableBitVector.makeMutable(from: [10, 20]))) + } +} +#endif + +// Another test for SR-3871, SR-5590, SR-6309, SR-8651: +// user type in a _SwiftValue in an Optional can't be cast to a protocol. +// Note: This uses the (misnamed) _bridgeAnythingToObjectiveC so it can +// test these paths on Linux as well. +protocol P6309 {} +CastsTests.test("Casting struct -> Obj-C -> Protocol fails (SR-3871, SR-5590, SR-6309, SR-8651)") { + struct S: P6309 { + let value: Int + let tracker = LifetimeTracked(13) + } + + let a: P6309 = S(value: 13) + + let b = _bridgeAnythingToObjectiveC(a) + let d = b as? Any + let e = d as? P6309 + expectNotNil(e) +} + + +protocol P4552 {} +if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) { +CastsTests.test("Casting Any(Optional(T)) -> Protocol fails (SR-4552)") { + struct S: P4552 { + let tracker = LifetimeTracked(13) + } + + let a = S() + let b: S? = a + let c = b as? Any + let d = c as? P4552 + expectNotNil(d) +} +} + +// rdar://27108240 (Optional casting bug (crash)) +protocol Key { + associatedtype Value +} +CastsTests.test("Cast to associated type") { + // Helper function to bypass compiler cast optimizations + func runtimeCast (_ x: From, to: To.Type) -> To? { + return x as? To + } + struct StringKey : Key { + typealias Value = String? + } + var string: String? + func value(forKey key: K.Type) { + let b = runtimeCast(string, to: K.Value.self) + expectNotNil(b) + let c = string as? K.Value + expectNotNil(c) + } + value(forKey: StringKey.self) +} + +#if _runtime(_ObjC) +// rdar://36288786 (Swift metatype stored in an Objective-C id property can't be typecast back to its original type) +CastsTests.test("Store Swift metatype in ObjC property and cast back to Any.Type") { + class MyObj { + var sVar: Any? = nil + @objc dynamic var objcVar: Any? = nil + } + + let a = MyObj() + + // Double values + a.sVar = 1.234 + a.objcVar = 1.234 + + let sValue1 = a.sVar as? Double + let objcValue1 = a.objcVar as? Double + expectEqual(sValue1, objcValue1) + + // Swift types + let b = Bool.self + a.sVar = b + a.objcVar = b + + let sValue2 = a.sVar as? Any.Type + let objcValue2 = a.objcVar as? Any.Type + expectTrue(sValue2 == b) + if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) { + expectTrue(sValue2 == objcValue2) + expectTrue(objcValue2 == b) + } +} +#endif + +// rdar://37793004 ([dynamic casting] [SR-7049]: Enums don't cast back from AnyHashable) +CastsTests.test("Enums don't cast back from AnyHashable (SR-7049)") { + enum E { + case a + } + + // This works as expected. + let str: AnyHashable = "hello" + expectNotNil(str as? String) // Optional("hello") + expectNotNil(str as? String as Any) // Optional("hello") + + // This doesn't. + let ea: AnyHashable = E.a + expectNotNil(ea as? E) + expectNotNil(ea as? E as Any) + expectEqual((ea as? E), E.a) +} + +#if _runtime(_ObjC) +//rdar://39415812 ([dynamic casting] [SR-7432]: Can't see through boxed _SwiftValue when casting from @objc Type) +@objc(Exporter) +protocol Exporter: NSObjectProtocol { + var type: Any { get } + func export(item: Any) -> String? +} +CastsTests.test("Casts from @objc Type") { + struct User { var name: String } + + final class UserExporter: NSObject, Exporter { + var type: Any { return User.self } + func export(item: Any) -> String? { + let u = item as? User + return u?.name + } + } + + let user = User(name: "Kermit") + let exporter: Exporter = UserExporter() + + if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) { + expectTrue(exporter.type is User.Type) + } + expectNotNil(exporter.export(item: user)) +} +#endif + +#if _runtime(_ObjC) +// rdar://44467533 (Swift master branch: conditional casts for _ObjectiveCBridgeable miscompile in swift-corelibs-foundation) +CastsTests.test("Conditional NSNumber -> Bool casts") { + let x = NSNumber(value: -1) as? Bool + expectNil(x) +} +#endif + +// rdar://45217461 ([dynamic casting] [SR-8964]: Type check operator (is) fails for Any! variable holding an Error (struct) value) +if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) { +CastsTests.test("Casts from Any(struct) to Error (SR-8964)") { + struct MyError: Error { } + + let a: Any! = MyError() + let b: Any = a + expectTrue(b is Error) +} +} + +#if _runtime(_ObjC) +// rdar://15494623 (Handle dynamic cast to archetype bound to ObjC existential) +CastsTests.test("Dynamic cast to ObjC protocol") { + func genericCast(x: NSObject, _: T.Type) -> T? { + return x as? T + } + + let n: NSNumber = 1 + let copying = genericCast(x: n, NSCopying.self) + expectNotNil(copying) +} +#endif + +// SR-6126 +if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) { +CastsTests.test("Nil handling for Optionals and Arrays (SR-6126)") { + func check(_ arg: Int??) -> String { + switch arg { + case .none: + return ".none" + case .some(.none): + return ".some(.none)" + case .some(.some): + return ".some(.some)" + } + } + + let x: Int? = .none + let y: [Int?] = [.none] + + let a = x as Int?? + let b = (x as? Int??)! + let b2 = runtimeCast(x, to: Int??.self)! + let c = Int?.none as Int?? + let d = (Int?.none as? Int??)! + let d2 = runtimeCast(Int?.none, to: Int??.self)! + let e = (y as [Int??]).first! + let f = (y as? [Int??])!.first! + let f2 = runtimeCast(y, to: [Int??].self)!.first! + let g = ([Int?.none] as [Int??]).first! + let h = ([Int?.none] as? [Int??])!.first! + let h2 = runtimeCast([Int?.none], to: [Int??].self)!.first! + + // Original reporter believes all of these should be .some(.none) + expectEqual(".some(.none)", check(a)) // Xcode 9.0: .some(.none) + expectEqual(".some(.none)", check(b)) // Xcode 9.0: .some(.none) + expectEqual(".some(.none)", check(b2)) + expectEqual(".some(.none)", check(c)) // Xcode 9.0: .some(.none) + expectEqual(".some(.none)", check(d)) // Xcode 9.0: .some(.none) + expectEqual(".some(.none)", check(d2)) + expectEqual(".some(.none)", check(e)) // Xcode 9.0: .none + expectEqual(".some(.none)", check(f)) // Xcode 9.0: .none + expectEqual(".some(.none)", check(f2)) + expectEqual(".some(.none)", check(g)) // Xcode 9.0: .some(.none) + expectEqual(".some(.none)", check(h)) // Xcode 9.0: .none + expectEqual(".some(.none)", check(h2)) +} +} + +protocol SwiftProtocol {} +CastsTests.test("Swift Protocol Metatypes don't self-conform") { + let a = SwiftProtocol.self + // `is P.Protocol` tests whether the argument is a subtype of P. + // In particular, the protocol identifier `P.self` is such a subtype. + if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) { + expectNotNil(runtimeCast(a, to: SwiftProtocol.Protocol.self)) // Fixed by rdar://58991956 + } + expectNotNil(a as? SwiftProtocol.Protocol) + expectTrue(a is SwiftProtocol.Protocol) + blackhole(a as! SwiftProtocol.Protocol) // Should not trap + + // `is P.Type` tests conformance to P. Protocols cannot conform to + // protocols, so these always fail. + expectNil(runtimeCast(a, to: SwiftProtocol.Type.self)) + expectNil(a as? SwiftProtocol.Type) + expectFalse(a is SwiftProtocol.Type) +} + +CastsTests.test("Self-conformance for Any.self") { + let b = Any.self + expectNotNil(runtimeCast(b, to: Any.Protocol.self)) + blackhole(b as! Any.Protocol) // Should not trap + expectTrue(b is Any.Protocol) + expectNotNil(b as? Any.Protocol) + + // Unlike most other protocols, Any.self does conform to Any + expectNotNil(runtimeCast(b, to: Any.Type.self)) + expectNotNil(b as? Any.Type) + expectTrue(b is Any.Type) + blackhole(b as! Any.Type) +} + +// rdar://59067748 (Error Protocol should self-conform in optimized casts) +CastsTests.test("Self-conformance for Error.self") +.skip(.custom({ + !_isDebugAssertConfiguration() + }, + reason: "Cast optimizer breaks this test")) +.code { + let c = Error.self + expectNotNil(runtimeCast(c, to: Error.Protocol.self)) + expectNotNil(c as? Error.Protocol) + expectTrue(c is Error.Protocol) + blackhole(c as! Error.Protocol) + + // Unlike most other protocols, Error.self does conform to Error + expectNotNil(runtimeCast(c, to: Error.Type.self)) + expectFailure { expectNotNil(c as? Error.Type) } + expectFailure { expectTrue(c is Error.Type) } + // blackhole(c as! Error.Type) // Should not trap, but currently does +} + +// rdar://59067556 (Obj-C Protocol Metatypes should self-conform) +#if _runtime(_ObjC) +@objc protocol ObjCProtocol {} +CastsTests.test("ObjC Protocol Metatypes self-conform") { + let a = ObjCProtocol.self + if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) { + expectNotNil(runtimeCast(a, to: ObjCProtocol.Protocol.self)) + } + expectNotNil(a as? ObjCProtocol.Protocol) + expectTrue(a is ObjCProtocol.Protocol) + blackhole(a as! ObjCProtocol.Protocol) + + // Unlike Swift protocols, ObjC protocols do conform to themselves + expectFailure { expectNotNil(runtimeCast(a, to: ObjCProtocol.Type.self)) } + expectFailure { expectNotNil(a as? ObjCProtocol.Type) } + expectFailure { expectTrue(a is ObjCProtocol.Type) } + // blackhole(a as! ObjCProtocol.Type) // Should not trap, but currently does +} +#endif + +#if _runtime(_ObjC) +protocol NewStringProtocol {} +extension String: NewStringProtocol { } +CastsTests.test("String/NSString extension compat") { + let x: Any = NSString() + expectFailure { expectNotNil(runtimeCast(x, to: NewStringProtocol.self)) } + expectFailure { expectNotNil(x as? NewStringProtocol) } +} +#endif + +protocol P1999 {} +if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) { +CastsTests.test("Cast Any(Optional(class)) to Protocol type (SR-1999)") { + class Foo: P1999 { } + + let optionalFoo : Foo? = Foo() + let anyValue: Any = optionalFoo + + let foo1 = anyValue as? Foo + expectNotNil(foo1) + + let foo2 = anyValue as? P1999 + expectNotNil(foo2) + + let foo3 = runtimeCast(anyValue, to: Foo.self) + expectNotNil(foo3) + + let foo4 = runtimeCast(anyValue, to: P1999.self) + expectNotNil(foo4) +} +} + +#if _runtime(_ObjC) +CastsTests.test("Dict value casting (SR-2911)") { + var dict: [AnyHashable: String] = [:] + dict["Key"] = "Value" + expectNotNil(dict["Key"] as? NSString) + expectNotNil(runtimeCast(dict["Key"], to: NSString.self)) +} +#endif + +#if _runtime(_ObjC) +CastsTests.test("String coercions should work on Linux (SR-12020)") { + let a = "abc" as Substring as NSString + let b = "abc" as NSString + expectEqual(a, b) + + let c = "abc" as Substring + let d = c as? NSString + let e = "abc" as? NSString + expectEqual(d, e) + + let f = runtimeCast(d, to: NSString.self) + expectEqual(e, f) +} +#endif + +class ClassInt: Equatable, Hashable { + private var tracker = LifetimeTracked(77) + static func == (lhs: ClassInt, rhs: ClassInt) -> Bool {return true} + func hash(into hasher: inout Hasher) {} +} +CastsTests.test("AnyHashable(Class) -> Obj-C -> Class") +.skip(.custom({ + !_isDebugAssertConfiguration() + }, + reason: "Cast optimizer breaks this test")) +.code { + let a = ClassInt() + let b = runtimeCast(a, to: AnyHashable.self)! + let c = _bridgeAnythingToObjectiveC(b) + let d = /* SwiftValueBox(AnyHashable(ClassInt)) */ c as? ClassInt + expectNotNil(d) + let d2 = runtimeCast(c, to: ClassInt.self) + expectNotNil(d2) + let e = runtimeCast(/* SwiftValueBox(AnyHashable(ClassInt)) */ c, to: ClassInt.self) + expectNotNil(e) +} + +#if _runtime(_ObjC) +// rdar://58999120 +CastsTests.test("Error -> NSError -> Protocol transitivity (SR-12095)") { + enum NonConformingError: Error { + case ok + } + + let nonConformingError: Error = NonConformingError.ok + + // NSError conforms to CustomStringConvertible, so ... + let conformingError = nonConformingError as? NSError + expectTrue(conformingError is CustomStringConvertible) + expectNotNil(conformingError as? CustomStringConvertible) + + // Our error type does not conform directly, but should conform + // indirectly because of NSError... + // Note: Known broken in both runtime and compiler. + expectFailure { expectTrue(nonConformingError is CustomStringConvertible) } + expectFailure { expectNotNil(nonConformingError as? CustomStringConvertible) } +} +#endif + +#if _runtime(_ObjC) +CastsTests.test("Runtime crash casting Obj-C object to Obj-C protocol (rdar://16449805)") { + // FIXME: The reported crash was for `NSPoint(x:0, y:0) as? NSCoding`, + // but NSPoint seems to not be available on 32-bit platforms. + expectNotNil(NSString() as? NSCoding) +} +#endif + +CastsTests.test("Casting Swift Error-conforming types to Error existentials") { + enum Foo: Error { + case OK + case Broken + } + let a = Foo.Broken + let b = a as? Error + expectNotNil(b) + let c = b as? Foo + expectNotNil(c) + let d = Foo.self as? Error.Type + expectNotNil(d) +} + +#if _runtime(_ObjC) +CastsTests.test("Casting NSError <-> Error") { + @objc class Bar: NSError { + init() {super.init(domain: "Bar", code: 99)} + required init?(coder: NSCoder) {super.init(coder: coder)} + } + let e = Bar.self as? Error.Type + expectNotNil(e) + let f = Bar.self as? Bar.Type + expectNotNil(f) + let g = Bar() as? Error + expectNotNil(g) +} +#endif + +// Foundation's JSON handling makes heavy use of passing Any? inside of Any +// existentials. That inspired the following three checks: +CastsTests.test("[Any(Any?)] -> [Any?] should prefer unwrapping source") { + let a: Any? = nil + let b: [Any] = [a as Any] + let c = b as? [Any?] + let d = c! + let e = d[0] + expectNil(e) +} + +CastsTests.test("Any(Any?) -> Any? should prefer unwrapping source") { + let a: Any? = nil + let b: Any = a + let c = b as? Any? + let d = c! + expectNil(d) +} + +#if _runtime(_ObjC) +CastsTests.test("NSNull?.none -> Any? should set outer nil") { + let a: NSNull? = nil + let b = a as? Any? + let c = b! + expectNil(c) +} +#endif + +CastsTests.test("Int??.some(nil) => Int??? should inject naturally") { + let a: Int?? = .some(nil) + let b = a as? Int??? + let c = b! + let d = c! + let e = d! + expectNil(e) +} + +CastsTests.test("Int??.some(nil) => String??? should inject naturally") { + let a: Int?? = .some(nil) + let b = runtimeCast(a, to: String???.self) + let c = b! + let d = c! + let e = d! + expectNil(e) +} + +CastsTests.test("Int??.some(nil) => Any??? should inject naturally") { + let a: Int?? = .some(nil) + let b = a as? Any??? + let c = b! + let d = c! + let e = d! + expectNil(e) +} + +#if _runtime(_ObjC) +CastsTests.test("NSString -> String fast path") { + let a = "short" as NSString + expectNotNil(a as? String) + let b = runtimeCast(a, to: String.self) + expectNotNil(b) + + let c = "Long (adj) -- extended, large, the opposite of short" as NSString + expectNotNil(c as? String) + let d = runtimeCast(c, to: String.self) + expectNotNil(d) + + let e = NSMutableString("not read-only") + expectNotNil(e as? String) + let f = runtimeCast(e, to: String.self) + expectNotNil(f) + + let g = CFStringCreateWithCString(nil, "hello, world", CFStringBuiltInEncodings.UTF8.rawValue) + expectNotNil(g as? String) + let h = runtimeCast(g, to: String.self) + expectNotNil(h) + + let i = CFStringCreateMutable(nil, 0) + expectNotNil(i as? String) + let j = runtimeCast(i, to: String.self) + expectNotNil(j) +} +#endif + +// This fails in optimized builds because after inlining `runtimeCast`, +// the resulting SIL cast operation is left in a form that IRGen can't +// correctly handle. +//CastsTests.test("Optimized metatype -> AnyObject cast") { +// struct StructInt { } +// let a = StructInt.self +// let b = runtimeCast(a, to: AnyObject.self) +// expectNotNil(b) +//} + +CastsTests.test("Any.Protocol") { + class C {} + struct S {} + func isAnyProtocol(_ type: T.Type) -> Bool { + let result = T.self is Any.Protocol + if result { + // `as!` should succeed if `is` does + blackhole(T.self as! Any.Protocol) + } + return result + } + func isAnyType(_ type: T.Type) -> Bool { + return T.self is Any.Type + } + func isType(_ type: T.Type, to: U.Type) -> Bool { + return T.self is U.Type + } + + expectTrue(Int.self is Any.Type) + expectNotNil(Int.self as? Any.Type) + expectTrue(isAnyType(Int.self)) + expectFalse(Int.self is Any.Protocol) + expectNil(Int.self as? Any.Protocol) + expectFalse(isAnyProtocol(Int.self)) + expectFalse(isType(Int.self, to: Any.self)) + + expectTrue(C.self is Any.Type) + expectNotNil(C.self as? Any.Type) + expectTrue(isAnyType(C.self)) + expectFalse(C.self is Any.Protocol) + expectNil(C.self as? Any.Protocol) + expectFalse(isAnyProtocol(C.self)) + expectFalse(isType(C.self, to: Any.self)) + + expectTrue(S.self is Any.Type) + expectNotNil(S.self as? Any.Type) + expectTrue(isAnyType(S.self)) + expectFalse(S.self is Any.Protocol) + expectNil(S.self as? Any.Protocol) + expectFalse(isAnyProtocol(S.self)) + expectFalse(isType(S.self, to: Any.self)) + + expectTrue(Any.self is Any.Type) + expectNotNil(Any.self as? Any.Type) + expectTrue(isAnyType(Any.self)) + expectTrue(Any.self is Any.Protocol) + expectNotNil(Any.self as? Any.Protocol) + expectTrue(isAnyProtocol(Any.self)) + expectTrue(isType(Any.self, to: Any.self)) + + expectTrue(Any?.self is Any.Type) + expectNotNil(Any?.self as? Any.Type) + expectTrue(isAnyType(Any?.self)) + expectFalse(Any?.self is Any.Protocol) + expectNil(Any?.self as? Any.Protocol) + expectFalse(isAnyProtocol(Any?.self)) + expectFalse(isType(Any?.self, to: Any.self)) +} + +CastsTests.test("Async function types") { + let asyncFnType: Any.Type = (() async -> Void).self + let fnType: Any.Type = (() -> Void).self + + expectTrue(fnType is (() -> Void).Type) + expectTrue(asyncFnType is (() async -> Void).Type) + expectFalse(fnType is (() async -> Void).Type) + expectFalse(asyncFnType is (() -> Void).Type) +} + +runAllTests() diff --git a/test/ClangImporter/objc_async.swift b/test/ClangImporter/objc_async.swift new file mode 100644 index 0000000000000..15b149a89c5dd --- /dev/null +++ b/test/ClangImporter/objc_async.swift @@ -0,0 +1,24 @@ +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-sil -I %S/Inputs/custom-modules -enable-experimental-concurrency %s -verify + +// REQUIRES: objc_interop +import Foundation +import ObjCConcurrency + +func testSlowServer(slowServer: SlowServer) async { + let _: Int = await slowServer.doSomethingSlow("mail") + let _: Bool = await slowServer.checkAvailability() + let _: String = await slowServer.findAnswer() ?? "nope" + let _: String = await slowServer.findAnswerFailingly() ?? "nope" + // FIXME: expected-error@-2{{call can throw, but it is not marked with 'try'}} + // FIXME: expected-error@-2{{call can throw, but it is not marked with 'try'}} + let _: Void = await slowServer.doSomethingFun("jump") + let _: (Int) -> Void = slowServer.completionHandler +} + +func testSlowServerOldSchool(slowServer: SlowServer) { + var i1: Int = 0 + slowServer.doSomethingSlow("mail") { i in + i1 = i + } + print(i1) +} diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift index b6f99b7350729..0b77ce6ac87b2 100644 --- a/test/Constraints/closures.swift +++ b/test/Constraints/closures.swift @@ -1030,3 +1030,15 @@ func sr12815() { .doesntExist2() { $0 } } } + +// Make sure we can infer generic arguments in an explicit result type. +let explicitUnboundResult1 = { () -> Array in [0] } +let explicitUnboundResult2: (Array) -> Array = { + (arr: Array) -> Array in [0] +} +// FIXME: Should we prioritize the contextual result type and infer Array +// rather than using a type variable in these cases? +// expected-error@+1 {{unable to infer closure type in the current context}} +let explicitUnboundResult3: (Array) -> Array = { + (arr: Array) -> Array in [true] +} diff --git a/test/Constraints/conditionally_defined_types.swift b/test/Constraints/conditionally_defined_types.swift index 193d40a7f766d..73ebce7633514 100644 --- a/test/Constraints/conditionally_defined_types.swift +++ b/test/Constraints/conditionally_defined_types.swift @@ -36,12 +36,12 @@ let _ = SameType.Decl3.self let _ = SameType.Decl4.self let _ = SameType.Decl5.self -let _ = SameType.TypeAlias1.self // expected-error {{'SameType.TypeAlias1' (aka 'X') requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.TypeAlias2.self // expected-error {{'SameType.TypeAlias2' (aka 'Y') requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.TypeAlias1.self // expected-error {{'SameType.TypeAlias1' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.TypeAlias2.self // expected-error {{'SameType.TypeAlias2' (aka 'Y') requires the types 'Y' and 'X' be equivalent}} let _ = SameType.TypeAlias3.self // expected-error {{'SameType.TypeAlias3' requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.Decl1.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.Decl2.self // expected-error {{'SameType.Decl2' requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.Decl3.self // expected-error {{'SameType.Decl3' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl1.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl2.self // expected-error {{'SameType.Decl2' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl3.self // expected-error {{'SameType.Decl3' requires the types 'Y' and 'X' be equivalent}} let _ = SameType.Decl4.self // expected-error {{'SameType.Decl4' requires the types 'Y' and 'X' be equivalent}} let _ = SameType.Decl5.self // expected-error {{'SameType.Decl5' requires the types 'Y' and 'X' be equivalent}} @@ -49,7 +49,7 @@ extension SameType: AssociatedType where T == X {} // expected-note@-1 {{requirement specified as 'T' == 'X' [with T = Y]}} let _ = SameType.T.self -let _ = SameType.T.self // expected-error {{'SameType.T' (aka 'X') requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.T.self // expected-error {{'SameType.T' (aka 'X') requires the types 'Y' and 'X' be equivalent}} struct Conforms {} @@ -112,14 +112,14 @@ let _ = SameType.Decl1.Decl3.self let _ = SameType.Decl1.Decl4.self let _ = SameType.Decl1.Decl5.self -let _ = SameType.Decl1.TypeAlias1.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.Decl1.TypeAlias2.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.Decl1.TypeAlias3.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.Decl1.Decl1.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.Decl1.Decl2.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.Decl1.Decl3.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.Decl1.Decl4.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.Decl1.Decl5.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl1.TypeAlias1.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl1.TypeAlias2.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl1.TypeAlias3.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl1.Decl1.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl1.Decl2.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl1.Decl3.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl1.Decl4.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl1.Decl5.self // expected-error {{'SameType.Decl1' requires the types 'Y' and 'X' be equivalent}} extension SameType.Decl4 where U == X { // expected-note 5 {{requirement specified as 'U' == 'X' [with U = Y]}} typealias TypeAlias1 = T @@ -144,12 +144,12 @@ let _ = SameType.Decl4.Decl3.self let _ = SameType.Decl4.Decl4.self let _ = SameType.Decl4.Decl5.self -let _ = SameType.Decl4.TypeAlias1.self // expected-error {{'SameType.Decl4.TypeAlias1' (aka 'X') requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.Decl4.TypeAlias2.self // expected-error {{'SameType.Decl4.TypeAlias2' (aka 'Y') requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl4.TypeAlias1.self // expected-error {{'SameType.Decl4.TypeAlias1' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl4.TypeAlias2.self // expected-error {{'SameType.Decl4.TypeAlias2' (aka 'Y') requires the types 'Y' and 'X' be equivalent}} let _ = SameType.Decl4.TypeAlias3.self // expected-error {{'SameType.Decl4.TypeAlias3' requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.Decl4.Decl1.self // expected-error {{'SameType.Decl4.Decl1' requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.Decl4.Decl2.self // expected-error {{'SameType.Decl4.Decl2' requires the types 'Y' and 'X' be equivalent}} -let _ = SameType.Decl4.Decl3.self // expected-error {{'SameType.Decl4.Decl3' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl4.Decl1.self // expected-error {{'SameType.Decl4.Decl1' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl4.Decl2.self // expected-error {{'SameType.Decl4.Decl2' requires the types 'Y' and 'X' be equivalent}} +let _ = SameType.Decl4.Decl3.self // expected-error {{'SameType.Decl4.Decl3' requires the types 'Y' and 'X' be equivalent}} let _ = SameType.Decl4.Decl4.self // expected-error {{'SameType.Decl4.Decl4' requires the types 'Y' and 'X' be equivalent}} let _ = SameType.Decl4.Decl5.self // expected-error {{'SameType.Decl4.Decl5' requires the types 'Y' and 'X' be equivalent}} diff --git a/test/Constraints/construction.swift b/test/Constraints/construction.swift index 82f660ed6a7bb..048667c4e129b 100644 --- a/test/Constraints/construction.swift +++ b/test/Constraints/construction.swift @@ -22,7 +22,7 @@ enum Z { init(_ x: Int, _ y: Int) { self = .point(x, y) } } -enum Optional { // expected-note {{'T' declared as parameter to type 'Optional'}} +enum Optional { case none case value(T) @@ -59,8 +59,7 @@ acceptString("\(hello), \(world) #\(i)!") Optional(1) // expected-warning{{unused}} Optional(1) // expected-warning{{unused}} _ = .none as Optional -Optional(.none) // expected-error{{generic parameter 'T' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{9-9=}} -// expected-error@-1 {{cannot infer contextual base in reference to member 'none'}} +Optional(.none) // expected-error {{cannot infer contextual base in reference to member 'none'}} // Interpolation _ = "\(hello), \(world) #\(i)!" diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift index bff33fe7caa73..fac6d8b343a10 100644 --- a/test/Constraints/diagnostics.swift +++ b/test/Constraints/diagnostics.swift @@ -423,7 +423,7 @@ let _ : Color = .rainbow(42) // expected-error {{argument passed to call that t let _ : (Int, Float) = (42.0, 12) // expected-error {{cannot convert value of type '(Double, Float)' to specified type '(Int, Float)'}} -let _ : Color = .rainbow // expected-error {{member 'rainbow()' is a function; did you mean to call it?}} {{25-25=()}} +let _ : Color = .rainbow // expected-error {{member 'rainbow()' is a function that produces expected type 'Color'; did you mean to call it?}} {{25-25=()}} let _: Color = .overload(a : 1.0) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}} let _: Color = .overload(1.0) // expected-error {{no exact matches in call to static method 'overload'}} diff --git a/test/Constraints/function_builder.swift b/test/Constraints/function_builder.swift index eb5e6857c55c1..d30a3a932f7ce 100644 --- a/test/Constraints/function_builder.swift +++ b/test/Constraints/function_builder.swift @@ -6,10 +6,6 @@ enum Either { case second(U) } -struct Do { - var value: T -} - @_functionBuilder struct TupleBuilder { static func buildBlock(_ t1: T1) -> (T1) { @@ -36,19 +32,6 @@ struct TupleBuilder { return (t1, t2, t3, t4, t5) } - static func buildDo(_ t1: T1) -> Do<(T1)> { - .init(value: t1) - } - - static func buildDo(_ t1: T1, _ t2: T2) -> Do<(T1, T2)> { - .init(value: (t1, t2)) - } - - static func buildDo(_ t1: T1, _ t2: T2, _ t3: T3) - -> Do<(T1, T2, T3)> { - .init(value: (t1, t2, t3)) - } - static func buildIf(_ value: T?) -> T? { return value } static func buildEither(first value: T) -> Either { @@ -61,11 +44,11 @@ struct TupleBuilder { static func buildArray(_ array: [T]) -> [T] { return array } } -func tuplify(_ cond: Bool, @TupleBuilder body: (Bool) -> T) { - print(body(cond)) +func tuplify(_ cond: Bool, @TupleBuilder body: (Bool) throws -> T) rethrows { + print(try body(cond)) } -// CHECK: (17, 3.14159, "Hello, DSL", main.Do<(Swift.Array, Swift.Int)>(value: (["nested", "do"], 6)), Optional((2.71828, ["if", "stmt"]))) +// CHECK: (17, 3.14159, "Hello, DSL", (["nested", "do"], 6), Optional((2.71828, ["if", "stmt"]))) let name = "dsl" tuplify(true) { 17 @@ -664,7 +647,6 @@ struct TupleBuilderWithOpt { return (t1, t2, t3, t4, t5) } - static func buildDo(_ value: T) -> T { return value } static func buildOptional(_ value: T?) -> T? { return value } static func buildEither(first value: T) -> Either { @@ -703,5 +685,85 @@ tuplify(true) { c in } } +// Test the use of function builders partly implemented through a protocol. +indirect enum FunctionBuilder { + case expression(Expression) + case block([FunctionBuilder]) + case either(Either) + case optional(FunctionBuilder?) +} + +protocol FunctionBuilderProtocol { + associatedtype Expression + typealias Component = FunctionBuilder + associatedtype Return + + static func buildExpression(_ expression: Expression) -> Component + static func buildBlock(_ components: Component...) -> Component + static func buildOptional(_ optional: Component?) -> Component + static func buildArray(_ components: [Component]) -> Component + static func buildLimitedAvailability(_ component: Component) -> Component + + static func buildFinalResult(_ components: Component) -> Return +} +extension FunctionBuilderProtocol { + static func buildExpression(_ expression: Expression) -> Component { .expression(expression) } + static func buildBlock(_ components: Component...) -> Component { .block(components) } + static func buildOptional(_ optional: Component?) -> Component { .optional(optional) } + static func buildArray(_ components: [Component]) -> Component { .block(components) } + static func buildLimitedAvailability(_ component: Component) -> Component { component } +} +@_functionBuilder +enum ArrayBuilder: FunctionBuilderProtocol { + typealias Expression = E + typealias Component = FunctionBuilder + typealias Return = [E] + + static func buildFinalResult(_ components: Component) -> Return { + switch components { + case .expression(let e): return [e] + case .block(let children): return children.flatMap(buildFinalResult) + case .either(.first(let child)): return buildFinalResult(child) + case .either(.second(let child)): return buildFinalResult(child) + case .optional(let child?): return buildFinalResult(child) + case .optional(nil): return [] + } + } +} + + +func buildArray(@ArrayBuilder build: () -> [String]) -> [String] { + return build() +} + + +let a = buildArray { + "1" + "2" + if Bool.random() { + "maybe 3" + } +} +// CHECK: ["1", "2" +print(a) + +// Throwing in function builders. +enum MyError: Error { + case boom +} + +// CHECK: testThrow +do { + print("testThrow") + try tuplify(true) { c in + "ready to throw" + throw MyError.boom + } +} catch MyError.boom { + // CHECK: caught it! + print("caught it!") +} catch { + fatalError("Threw something else?") +} diff --git a/test/Constraints/function_builder_diags.swift b/test/Constraints/function_builder_diags.swift index 7a7029b499935..89e4264df312f 100644 --- a/test/Constraints/function_builder_diags.swift +++ b/test/Constraints/function_builder_diags.swift @@ -6,7 +6,7 @@ enum Either { } @_functionBuilder -struct TupleBuilder { // expected-note 3{{struct 'TupleBuilder' declared here}} +struct TupleBuilder { // expected-note 2 {{struct 'TupleBuilder' declared here}} static func buildBlock() -> () { } static func buildBlock(_ t1: T1) -> T1 { @@ -87,7 +87,7 @@ func testDiags() { // For loop tuplify(true) { _ in 17 - for c in name { // expected-error{{closure containing control flow statement cannot be used with function builder 'TupleBuilder'}} + for c in name { // expected-error@-1 {{cannot find 'name' in scope}} } } @@ -418,13 +418,16 @@ func testNonExhaustiveSwitch(e: E) { // rdar://problem/59856491 struct TestConstraintGenerationErrors { @TupleBuilder var buildTupleFnBody: String { - let a = nil // expected-error {{'nil' requires a contextual type}} + let a = nil // There is no diagnostic here because next line fails to pre-check, so body is invalid String(nothing) // expected-error {{cannot find 'nothing' in scope}} } + @TupleBuilder var nilWithoutContext: String { + let a = nil // expected-error {{'nil' requires a contextual type}} + } + func buildTupleClosure() { - // FIXME: suppress the ambiguity error - tuplify(true) { _ in // expected-error {{type of expression is ambiguous without more context}} + tuplify(true) { _ in let a = nothing // expected-error {{cannot find 'nothing' in scope}} String(nothing) // expected-error {{cannot find 'nothing' in scope}} } @@ -620,3 +623,15 @@ struct MyView { "" } } + +// Make sure throwing function builder closures are implied. +enum MyError: Error { + case boom +} + +do { + tuplify(true) { c in // expected-error{{invalid conversion from throwing function of type '(Bool) throws -> String' to non-throwing function type '(Bool) -> String'}} + "testThrow" + throw MyError.boom + } +} diff --git a/test/Constraints/keypath.swift b/test/Constraints/keypath.swift index 107739ee0b9a8..2512e9d9f372b 100644 --- a/test/Constraints/keypath.swift +++ b/test/Constraints/keypath.swift @@ -179,3 +179,11 @@ func key_path_root_mismatch(_ base: KeyPathBase?, subBase: KeyPathBaseSubtype let _ : T = subBase[keyPath: kpa] // expected-error {{key path with root type 'AnotherBase' cannot be applied to a base of type 'KeyPathBaseSubtype?'}} } + +// SR-13442 +func SR13442(_ x: KeyPath) -> T { "1"[keyPath: x] } + +func testSR13442() { + _ = SR13442(\.!.count) // OK + _ = SR13442(\String?.!.count) // OK +} diff --git a/test/Constraints/rdar39931339.swift b/test/Constraints/rdar39931339.swift index 40add2eb11c18..eee8de950baad 100644 --- a/test/Constraints/rdar39931339.swift +++ b/test/Constraints/rdar39931339.swift @@ -32,12 +32,12 @@ _ = B.S1() // Ok _ = B.S2() // Ok _ = B.S1() // expected-error {{type 'Float' does not conform to protocol 'P'}} _ = B.S2() -// expected-error@-1 {{'B.S2' (aka 'Int') requires the types '[String]' and '[Int]' be equivalent}} +// expected-error@-1 {{'A.S2' (aka 'Int') requires the types '[String]' and '[Int]' be equivalent}} _ = S.A() // Ok _ = S.A() // expected-error {{type 'Int' does not conform to protocol 'P'}} _ = S.B() // expected-error {{type 'String' does not conform to protocol 'P'}} -_ = S.C() // expected-error {{'S.C' (aka 'Int') requires the types 'Int' and 'Float' be equivalent}} +_ = S.C() // expected-error {{'S.C' (aka 'Int') requires the types 'Int' and 'Float' be equivalent}} func foo(_ s: S.Type) { _ = s.A() // expected-error {{referencing type alias 'A' on 'S' requires that 'T' conform to 'P'}} diff --git a/test/Constraints/rdar44770297.swift b/test/Constraints/rdar44770297.swift index 8d0b128b9e136..9853dd1ca2f53 100644 --- a/test/Constraints/rdar44770297.swift +++ b/test/Constraints/rdar44770297.swift @@ -4,10 +4,8 @@ protocol P { associatedtype A } -func foo(_: () throws -> T) -> T.A? { +func foo(_: () throws -> T) -> T.A? { // expected-note {{where 'T' = 'Never'}} fatalError() } -let _ = foo() {fatalError()} & nil // expected-error {{value of optional type 'Never.A?' must be unwrapped to a value of type 'Never.A'}} -// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} -// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} +let _ = foo() {fatalError()} & nil // expected-error {{global function 'foo' requires that 'Never' conform to 'P'}} diff --git a/test/Constraints/rdar65320500.swift b/test/Constraints/rdar65320500.swift new file mode 100644 index 0000000000000..dfb8f722a2692 --- /dev/null +++ b/test/Constraints/rdar65320500.swift @@ -0,0 +1,43 @@ +// RUN: %target-typecheck-verify-swift + +struct Result {} + +@_functionBuilder +struct Builder { + static func buildBlock() -> Result { + Result() + } +} + +func test_builder(@Builder _: () -> T) {} +func test_builder(@Builder _: () -> Int) {} + +test_builder { + let _ = 0 + + if let x = does_not_exist { // expected-error {{cannot find 'does_not_exist' in scope}} + } +} + +func test(_: Int) -> Bool { + return false +} + +test_builder { + let totalSeconds = 42000 + test(totalseconds / 3600) // expected-error {{cannot find 'totalseconds' in scope}} +} + +test_builder { + test(doesntExist()) // expected-error {{cannot find 'doesntExist' in scope}} + + if let result = doesntExist() { // expected-error {{cannot find 'doesntExist' in scope}} + } + + if bar = test(42) {} // expected-error {{cannot find 'bar' in scope}} + + let foo = bar() // expected-error {{cannot find 'bar' in scope}} + + switch (doesntExist()) { // expected-error {{cannot find 'doesntExist' in scope}} + } +} diff --git a/test/Constraints/requirement_failures_in_contextual_type.swift b/test/Constraints/requirement_failures_in_contextual_type.swift index 31eb477fa7153..75bf679ad92ce 100644 --- a/test/Constraints/requirement_failures_in_contextual_type.swift +++ b/test/Constraints/requirement_failures_in_contextual_type.swift @@ -14,11 +14,11 @@ extension A where T == Int32 { // expected-note 3{{requirement specified as 'T' } let _: A.B = 0 -// expected-error@-1 {{'A.B' requires the types 'Int' and 'Int32' be equivalent}} +// expected-error@-1 {{'A.B' requires the types 'Int' and 'Int32' be equivalent}} let _: A.C = 0 -// expected-error@-1 {{'A.C' (aka 'Int') requires the types 'Int' and 'Int32' be equivalent}} +// expected-error@-1 {{'A.C' (aka 'Int') requires the types 'Int' and 'Int32' be equivalent}} let _: A.B.E = 0 -// expected-error@-1 {{'A.B' requires the types 'Int' and 'Int32' be equivalent}} +// expected-error@-1 {{'A.B' requires the types 'Int' and 'Int32' be equivalent}} protocol P {} diff --git a/test/DebugInfo/modulecache.swift b/test/DebugInfo/modulecache.swift index 6af85efa2bcf3..22d126eca7cde 100644 --- a/test/DebugInfo/modulecache.swift +++ b/test/DebugInfo/modulecache.swift @@ -16,7 +16,7 @@ import ClangModule // RUN: %empty-directory(%t) // RUN: %target-swift-frontend %s -c -g -o %t.o -module-cache-path %t -I %S/Inputs // RUN: llvm-readobj -h %t/*/ClangModule-*.pcm | %FileCheck %s -// CHECK: Format: {{(Mach-O|ELF|COFF|WASM)}} +// CHECK: Format: {{(Mach-O|ELF|elf64|COFF|elf32-littlearm|WASM)}} // 3. Test that swift-ide-check will not share swiftc's module cache. diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt index 01591a1ab8530..f0b200e2979a9 100644 --- a/test/Demangle/Inputs/manglings.txt +++ b/test/Demangle/Inputs/manglings.txt @@ -365,3 +365,5 @@ $s0059xxxxxxxxxxxxxxx_ttttttttBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBee -> $s0059xxxx $sx1td_t ---> (t: A...) $s7example1fyyYF -> example.f() async -> () $s7example1fyyYKF -> example.f() async throws -> () +$s4main20receiveInstantiationyySo34__CxxTemplateInst12MagicWrapperIiEVzF ---> main.receiveInstantiation(inout __C.__CxxTemplateInst12MagicWrapperIiE) -> () +$s4main19returnInstantiationSo34__CxxTemplateInst12MagicWrapperIiEVyF ---> main.returnInstantiation() -> __C.__CxxTemplateInst12MagicWrapperIiE diff --git a/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/CoreDaemon.h b/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/CoreDaemon.h new file mode 100644 index 0000000000000..82d8f39a18d69 --- /dev/null +++ b/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/CoreDaemon.h @@ -0,0 +1,5 @@ +typedef void Runner(int); + +struct Daemon { + Runner *run; +}; diff --git a/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/CoreMemory.h b/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/CoreMemory.h new file mode 100644 index 0000000000000..058328d0f82a9 --- /dev/null +++ b/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/CoreMemory.h @@ -0,0 +1,4 @@ +struct MemoryMapRegion { + void *start; + void *end; +}; diff --git a/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/DaemonKit.h b/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/DaemonKit.h new file mode 100644 index 0000000000000..bb28f0606b6a3 --- /dev/null +++ b/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/DaemonKit.h @@ -0,0 +1,5 @@ +#import + +struct DaemonPair { + struct Daemon daemons[2]; +}; diff --git a/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/FilesystemKit.h b/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/FilesystemKit.h new file mode 100644 index 0000000000000..5956aaf20c0cf --- /dev/null +++ b/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/FilesystemKit.h @@ -0,0 +1,5 @@ +#import + +struct FileStorage { + MyNode *nodes[4]; +}; diff --git a/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/MemoryKit.h b/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/MemoryKit.h new file mode 100644 index 0000000000000..fd8b265646ccc --- /dev/null +++ b/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/MemoryKit.h @@ -0,0 +1,7 @@ +#import +#import + +struct MemoryMap { + MemoryMapEntry *entries; + unsigned count; +}; diff --git a/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/module.modulemap b/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/module.modulemap new file mode 100644 index 0000000000000..d0673487e9836 --- /dev/null +++ b/test/Driver/Inputs/imported_modules/ComplexModuleGraph2/module.modulemap @@ -0,0 +1,29 @@ +module CoreFilesystem { + header "CoreFilesystem-Generated.h" + export * +} + +module FilesystemKit { + header "FilesystemKit.h" + export * +} + +module CoreDaemon { + header "CoreDaemon.h" + export * +} + +module DaemonKit { + header "DaemonKit.h" + export * +} + +module CoreMemory { + header "CoreMemory.h" + export * +} + +module MemoryKit { + header "MemoryKit.h" + export * +} diff --git a/test/Driver/Inputs/imported_modules/SelfImport/module.modulemap b/test/Driver/Inputs/imported_modules/SelfImport/module.modulemap new file mode 100644 index 0000000000000..df67010362525 --- /dev/null +++ b/test/Driver/Inputs/imported_modules/SelfImport/module.modulemap @@ -0,0 +1,6 @@ +module Outer { + module Inner { + export Outer.Inner + } + export Outer +} diff --git a/test/Driver/loaded_module_trace_directness_2.swift b/test/Driver/loaded_module_trace_directness_2.swift new file mode 100644 index 0000000000000..95f06446c1df1 --- /dev/null +++ b/test/Driver/loaded_module_trace_directness_2.swift @@ -0,0 +1,185 @@ +// RUN: %empty-directory(%t) +// RUN: cp -r %S/Inputs/imported_modules/ComplexModuleGraph2 %t/include + +// REQUIRES: objc_interop + +// Dependency graph: +// +// * CoreFilesystem - Swift module with generated ObjC header +// * FilesystemKit - ObjC module without overlay, has #import +// * TestFilesystem - Swift module, has import CoreFilesystem or FilesystemKit. +// +// * CoreDaemon - ObjC module with overlay, the overlay has import DaemonKit +// * DaemonKit - ObjC module without overlay, has #import +// * TestDaemon - Swift module, has import CoreDaemon or DaemonKit. +// NOTE: This mimics the Darwin -> SwiftOverlayShims -> Darwin dependency "cycle". +// +// * CoreMemory - ObjC module with overlay and generated header for overlay, the overlay has import MemoryKit +// * MemoryKit - ObjC module without overlay, has #import +// * TestMemory - Swift module, has import CoreMemory or MemoryKit. + +// 1. CoreFilesystem - Build. + +// RUN: %target-swift-frontend %s -emit-module -o %t/include/CoreFilesystem.swiftmodule -DCoreFilesystem -module-name CoreFilesystem -emit-objc-header-path %t/include/CoreFilesystem-Generated.h -disable-objc-attr-requires-foundation-module + +#if CoreFilesystem +@objc +public class MyNode { + public var number: Int + public init(_ n: Int) { number = n } +} +#endif + +// 2. FilesystemKit - Nothing to do (pure Clang module). + +// 3. TestFilesystem - Check that CoreFilesystem and Filesytem can be imported. + +// RUN: %target-swift-frontend %s -typecheck -DTestFilesystem -DV1 -module-name TestFilesystemV1 -emit-loaded-module-trace-path %t/TestFilesystemV1.trace.json -I %t/include +// RUN: %FileCheck %s --check-prefix=TESTFILESYSTEM < %t/TestFilesystemV1.trace.json +// RUN: %target-swift-frontend %s -typecheck -DTestFilesystem -DV2 -module-name TestFilesystemV2 -emit-loaded-module-trace-path %t/TestFilesystemV2.trace.json -I %t/include +// RUN: %FileCheck %s --check-prefix=TESTFILESYSTEM < %t/TestFilesystemV2.trace.json +// RUN: %target-swift-frontend %s -typecheck -DTestFilesystem -DV3 -module-name TestFilesystemV3 -emit-loaded-module-trace-path %t/TestFilesystemV3.trace.json -I %t/include +// RUN: %FileCheck %s --check-prefix=TESTFILESYSTEM < %t/TestFilesystemV3.trace.json +// RUN: %target-swift-frontend %s -typecheck -DTestFilesystem -DV4 -module-name TestFilesystemV4 -emit-loaded-module-trace-path %t/TestFilesystemV4.trace.json -I %t/include +// RUN: %FileCheck %s --check-prefix=TESTFILESYSTEM < %t/TestFilesystemV4.trace.json + +#if TestFilesystem + #if V1 + import CoreFilesystem + #endif + #if V2 + import FilesystemKit + public func noop(_: CoreFilesystem.MyNode) {} + #endif + #if V3 + import CoreFilesystem + import FilesystemKit + #endif + #if V4 + import FilesystemKit + import CoreFilesystem + #endif +#endif + +// FilesystemKit has no overlay, so it shouldn't show up. +// TESTFILESYSTEM: "swiftmodulesDetailedInfo":[ +// TESTFILESYSTEM-NOT: FilesystemKit +// TESTFILESYSTEM-DAG: {"name":"CoreFilesystem","path":"{{[^"]*}}CoreFilesystem.swiftmodule","isImportedDirectly":true, +// TESTFILESYSTEM: ] + +// 4. CoreDaemon - Build. + +// RUN: %target-swift-frontend %s -emit-module -o %t/include/CoreDaemon.swiftmodule -DCoreDaemon -module-name CoreDaemon -emit-loaded-module-trace-path %t/CoreDaemon.trace.json -I %t/include +// RUN: %FileCheck %s --check-prefix=COREDAEMON < %t/CoreDaemon.trace.json + +// * CoreDaemon - ObjC module with overlay, the overlay has import DaemonKit +// * DaemonKit - ObjC module without overlay, has #import +// * TestDaemon - Swift module, has import CoreDaemon or DaemonKit. + +#if CoreDaemon +@_exported import CoreDaemon +import DaemonKit + +public func runBoth(_ pair: DaemonKit.DaemonPair) { + let daemons : (CoreDaemon.Daemon, CoreDaemon.Daemon) = pair.daemons; + daemons.0.run(0); + daemons.1.run(1); +} +#endif + +// COREDAEMON: "swiftmodulesDetailedInfo":[ +// COREDAEMON-NOT: CoreDaemon +// COREDAEMON-NOT: DaemonKit +// COREDAEMON: ] + +// 5. DaemonKit - Nothing to do (pure Clang module). + +// 6. TestCoreDaemon + +// RUN: %target-swift-frontend %s -typecheck -DTestDaemon -DV1 -module-name TestDaemonV1 -emit-loaded-module-trace-path %t/TestDaemonV1.trace.json -I %t/include +// RUN: %FileCheck %s --check-prefix=TESTDAEMON < %t/TestDaemonV1.trace.json + +// RUN: %target-swift-frontend %s -typecheck -DTestDaemon -DV2 -module-name TestDaemonV2 -emit-loaded-module-trace-path %t/TestDaemonV2.trace.json -I %t/include +// RUN: %FileCheck %s --check-prefix=TESTDAEMON < %t/TestDaemonV2.trace.json + +// RUN: %target-swift-frontend %s -typecheck -DTestDaemon -DV3 -module-name TestDaemonV3 -emit-loaded-module-trace-path %t/TestDaemonV3.trace.json -I %t/include +// RUN: %FileCheck %s --check-prefix=TESTDAEMON < %t/TestDaemonV3.trace.json + +// RUN: %target-swift-frontend %s -typecheck -DTestDaemon -DV4 -module-name TestDaemonV4 -emit-loaded-module-trace-path %t/TestDaemonV4.trace.json -I %t/include +// RUN: %FileCheck %s --check-prefix=TESTDAEMON < %t/TestDaemonV4.trace.json + +#if TestDaemon + #if V1 + import CoreDaemon + #endif + #if V2 + import DaemonKit + public func noop(_: CoreDaemon.Daemon) {} + #endif + #if V3 + import CoreDaemon + import DaemonKit + #endif + #if V4 + import DaemonKit + import CoreDaemon + #endif +#endif + +// DaemonKit has no overlay, so it shouldn't show up. +// TESTDAEMON: "swiftmodulesDetailedInfo":[ +// TESTDAEMON-NOT: DaemonKit +// TESTDAEMON-DAG: {"name":"CoreDaemon","path":"{{[^"]*}}CoreDaemon.swiftmodule","isImportedDirectly":true, +// TESTDAEMON: ] + +// 7. CoreMemory - Build. + +// RUN: %target-swift-frontend %s -emit-module -o %t/include/CoreMemory.swiftmodule -DCoreMemory -module-name CoreMemory -emit-objc-header-path %t/include/CoreMemory-Generated.h -disable-objc-attr-requires-foundation-module -I %t/include + +#if CoreMemory +@_exported import CoreMemory + +@objc +public class MemoryMapEntry { + public var region: MemoryMapRegion + public var permissions: Int = 0 + public init(_ r: MemoryMapRegion) { region = r } +} +#endif + +// 8. MemoryKit - Nothing to do (pure Clang module). + +// 9. TestMemory - Check that CoreMemory and MemoryKit can be imported. + +// RUN: %target-swift-frontend %s -typecheck -DTestMemory -DV1 -module-name TestMemoryV1 -emit-loaded-module-trace-path %t/TestMemoryV1.trace.json -I %t/include +// RUN: %FileCheck %s --check-prefix=TESTMEMORY < %t/TestMemoryV1.trace.json +// RUN: %target-swift-frontend %s -typecheck -DTestMemory -DV2 -module-name TestMemoryV2 -emit-loaded-module-trace-path %t/TestMemoryV2.trace.json -I %t/include +// RUN: %FileCheck %s --check-prefix=TESTMEMORY < %t/TestMemoryV2.trace.json +// RUN: %target-swift-frontend %s -typecheck -DTestMemory -DV3 -module-name TestMemoryV3 -emit-loaded-module-trace-path %t/TestMemoryV3.trace.json -I %t/include +// RUN: %FileCheck %s --check-prefix=TESTMEMORY < %t/TestMemoryV3.trace.json +// RUN: %target-swift-frontend %s -typecheck -DTestMemory -DV4 -module-name TestMemoryV4 -emit-loaded-module-trace-path %t/TestMemoryV4.trace.json -I %t/include +// RUN: %FileCheck %s --check-prefix=TESTMEMORY < %t/TestMemoryV4.trace.json + +#if TestMemory + #if V1 + import CoreMemory + #endif + #if V2 + import MemoryKit + public func noop(_: CoreMemory.MemoryMapRegion, _: CoreMemory.MemoryMapEntry) {} + #endif + #if V3 + import CoreMemory + import MemoryKit + #endif + #if V4 + import MemoryKit + import CoreMemory + #endif +#endif + +// MemoryKit has no overlay, so it shouldn't show up. +// TESTMEMORY: "swiftmodulesDetailedInfo":[ +// TESTMEMORY-NOT: MemoryKit +// TESTMEMORY-DAG: {"name":"CoreMemory","path":"{{[^"]*}}CoreMemory.swiftmodule","isImportedDirectly":true, +// TESTMEMORY: ] diff --git a/test/Driver/loaded_module_trace_self_cycle.swift b/test/Driver/loaded_module_trace_self_cycle.swift new file mode 100644 index 0000000000000..309ef714e34bf --- /dev/null +++ b/test/Driver/loaded_module_trace_self_cycle.swift @@ -0,0 +1,4 @@ +// Check that this doesn't crash due to a self-cycle. rdar://67435472 +// RUN: %target-swift-frontend %s -emit-module -o /dev/null -emit-loaded-module-trace-path /dev/null -I %S/Inputs/imported_modules/SelfImport + +import Outer diff --git a/test/Generics/constrained_type_witnesses.swift b/test/Generics/constrained_type_witnesses.swift new file mode 100644 index 0000000000000..e56586e752a64 --- /dev/null +++ b/test/Generics/constrained_type_witnesses.swift @@ -0,0 +1,75 @@ +// RUN: %target-typecheck-verify-swift + +protocol P { + associatedtype A + // expected-note@-1 3{{protocol requires nested type 'A'; do you want to add it?}} +} + +struct S1 {} + +extension S1 where T : P { + typealias A = Int +} + +// This is rejected because S1.A is not a suitable witness for P.A. +extension S1 : P {} +// expected-error@-1 {{type 'S1' does not conform to protocol 'P'}} + +struct S2 {} + +extension S2 where T : P { + typealias A = Never +} + +// Hack: This is OK to make SwiftUI work, which accidentally relies on the +// incorrect behavior with a typealias whose underlying type is 'Never' +// (so it didn't hit the compiler crash). +extension S2 : P {} + +// Here we have a suitable witness +struct S3 {} + +extension S3 where T == Int { + typealias A = Int +} + +extension S3 : P where T == Int {} + +// Check where clause on the type itself + +struct S4 { + typealias A = Int where T : P +} + +extension S4 : P {} +// expected-error@-1 {{type 'S4' does not conform to protocol 'P'}} + +struct S5 { + typealias A = Never where T : P +} + +extension S5 : P {} + +struct S6 { + typealias A = Int where T == Int +} + +extension S6 : P where T == Int {} + +// Witness in a constrained protocol extension +protocol Q { + associatedtype B +} + +extension Q where B == Int { + typealias A = Int +} + +struct S7 : Q, P { + typealias B = Int +} + +struct S8 : Q, P { +// expected-error@-1 {{type 'S8' does not conform to protocol 'P'}} + typealias B = String +} diff --git a/test/Generics/where_clause_contextually_generic_decls.swift b/test/Generics/where_clause_contextually_generic_decls.swift index 96b2c4fb6ed99..27819a167a03f 100644 --- a/test/Generics/where_clause_contextually_generic_decls.swift +++ b/test/Generics/where_clause_contextually_generic_decls.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift -typecheck %s -verify -swift-version 4 +// RUN: %target-typecheck-verify-swift -swift-version 4 func bet() where A : B {} // expected-error {{'where' clause cannot be applied to a non-generic top-level declaration}} @@ -148,7 +148,7 @@ _ = Container.NestedAlias2.self // expected-error {{type 'String' does n _ = Container>.NestedClass.self // expected-error {{type 'Container' does not conform to protocol 'Equatable'}} _ = Container.NestedStruct.self // expected-error {{type 'Void' does not conform to protocol 'Sequence'}} _ = Container>.NestedStruct2.self // expected-error {{type 'Void' does not conform to protocol 'Comparable'}} -_ = Container.NestedStruct2.NestedEnum.self // expected-error {{'Container.NestedStruct2.NestedEnum' requires the types 'String.Element' (aka 'Character') and 'Double' be equivalent}} +_ = Container.NestedStruct2.NestedEnum.self // expected-error {{'Container.NestedStruct2.NestedEnum' requires the types 'String.Element' (aka 'Character') and 'Double' be equivalent}} _ = Container.NestedAlias2.self _ = Container.NestedClass.self _ = Container.NestedStruct.self diff --git a/test/IDE/Inputs/complete_user_accessibility_helper.swift b/test/IDE/Inputs/complete_user_accessibility_helper.swift new file mode 100644 index 0000000000000..0ff5d6c417bf9 --- /dev/null +++ b/test/IDE/Inputs/complete_user_accessibility_helper.swift @@ -0,0 +1,3 @@ +public enum MyEnum { + case foo, bar +} diff --git a/test/IDE/complete_annotation.swift b/test/IDE/complete_annotation.swift index d9dde1ac6c8e5..0e267618ca87a 100644 --- a/test/IDE/complete_annotation.swift +++ b/test/IDE/complete_annotation.swift @@ -95,9 +95,13 @@ func testPostfix(value: MyStruct) { func testImplicitMember() -> MyStruct { return .#^EXPR_IMPLICITMEMBER^# } -// EXPR_IMPLICITMEMBER: Begin completions, 3 items +// EXPR_IMPLICITMEMBER: Begin completions, 7 items // EXPR_IMPLICITMEMBER-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Identical]: init(x: Int); typename=MyStruct; // EXPR_IMPLICITMEMBER-DAG: Decl[StaticVar]/ExprSpecific/TypeRelation[Identical]: instance; typename=MyStruct; +// EXPR_IMPLICITMEMBER-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: labelNameParamName(_ self: MyStruct); typename=(label: (inout Int) throws -> MyStruct) -> Void; +// EXPR_IMPLICITMEMBER-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: labelName(_ self: MyStruct); typename=(label: (@autoclosure () -> Int) -> Int) -> Void; +// EXPR_IMPLICITMEMBER-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: sameName(_ self: MyStruct); typename=(label: inout Int) -> Void; +// EXPR_IMPLICITMEMBER-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: paramName(_ self: MyStruct); typename=(Int) -> Void; // EXPR_IMPLICITMEMBER-DAG: Decl[StaticMethod]/ExprSpecific/TypeRelation[Identical]: create(x: Int); typename=MyStruct; // EXPR_IMPLICITMEMBER: End completions diff --git a/test/IDE/complete_assignment.swift b/test/IDE/complete_assignment.swift index 3fa5753e0b30c..871ef3db1dd2c 100644 --- a/test/IDE/complete_assignment.swift +++ b/test/IDE/complete_assignment.swift @@ -127,17 +127,19 @@ func f2() { d = .#^ASSIGN_5^# } -// ASSIGN_5: Begin completions, 2 items +// ASSIGN_5: Begin completions, 3 items // ASSIGN_5-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: case2[#D1#]; name=case2 // ASSIGN_5-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: case1[#D1#]; name=case1 +// ASSIGN_5-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): D1#})[#(into: inout Hasher) -> Void#]; name=hash(self: D1) func f6() { var d : D2 d = .#^ASSIGN_6^# } -// ASSIGN_6: Begin completions, 2 items +// ASSIGN_6: Begin completions, 3 items // ASSIGN_6-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: case3[#D2#]; name=case3 // ASSIGN_6-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: case4[#D2#]; name=case4 +// ASSIGN_6-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): D2#})[#(into: inout Hasher) -> Void#]; name=hash(self: D2) func f7 (C : C2) { var i : Int diff --git a/test/IDE/complete_attributes.swift b/test/IDE/complete_attributes.swift index a1fa33e3a9bb9..e7b5d203500f9 100644 --- a/test/IDE/complete_attributes.swift +++ b/test/IDE/complete_attributes.swift @@ -1,5 +1,7 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TOP_LEVEL_ATTR_1 -code-completion-keywords=false | %FileCheck %s -check-prefix=ERROR_COMMON // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=MEMBER_DECL_ATTR_1 -code-completion-keywords=false | %FileCheck %s -check-prefix=ERROR_COMMON +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ATTRARG_MEMBER | %FileCheck %s -check-prefix=MEMBER_MyValue +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ATTRARG_MEMBER_IN_CLOSURE | %FileCheck %s -check-prefix=MEMBER_MyValue // ERROR_COMMON: found code completion token // ERROR_COMMON-NOT: Keyword/ @@ -9,3 +11,22 @@ class MemberDeclAttribute { @#^MEMBER_DECL_ATTR_1^# func memberDeclAttr1() {} } + +struct MyValue { + init() {} + static var val: Int +} + +// MEMBER_MyValue: Begin completions, 4 items +// MEMBER_MyValue-DAG: Keyword[self]/CurrNominal: self[#MyValue.Type#]; +// MEMBER_MyValue-DAG: Keyword/CurrNominal: Type[#MyValue.Type#]; +// MEMBER_MyValue-DAG: Decl[Constructor]/CurrNominal: init()[#MyValue#]; +// MEMBER_MyValue-DAG: Decl[StaticVar]/CurrNominal: val[#Int#]; +// MEMBER_MyValue: End completions + +class TestUknownDanglingAttr1 { + @UknownAttr(arg: MyValue.#^ATTRARG_MEMBER^#) +} +class TestUknownDanglingAttr2 { + @UknownAttr(arg: { MyValue.#^ATTRARG_MEMBER_IN_CLOSURE^# }) +} diff --git a/test/IDE/complete_call_arg.swift b/test/IDE/complete_call_arg.swift index 978810776e125..bbd17ff20cd9e 100644 --- a/test/IDE/complete_call_arg.swift +++ b/test/IDE/complete_call_arg.swift @@ -78,11 +78,13 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STATIC_METHOD_AFTERPAREN_2 | %FileCheck %s -check-prefix=STATIC_METHOD_AFTERPAREN_2 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STATIC_METHOD_SECOND | %FileCheck %s -check-prefix=STATIC_METHOD_SECOND // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STATIC_METHOD_SKIPPED | %FileCheck %s -check-prefix=STATIC_METHOD_SKIPPED +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=STATIC_METHOD_OVERLOADED | %FileCheck %s -check-prefix=STATIC_METHOD_OVERLOADED // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_AFTERPAREN_1 | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_AFTERPAREN_1 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_AFTERPAREN_2 | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_AFTERPAREN_2 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_AFTERPAREN_3 | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_AFTERPAREN_3 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_SECOND | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_SECOND // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_SKIPPED | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_SKIPPED +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_OVERLOADED | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_OVERLOADED // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_ARRAY_1_AFTERPAREN_1 | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_AFTERPAREN_1 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_ARRAY_1_AFTERPAREN_2 | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_AFTERPAREN_2 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_ARRAY_1_SECOND | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_SECOND @@ -91,6 +93,7 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_ARRAY_2_AFTERPAREN_2 | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_AFTERPAREN_2 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_ARRAY_2_SECOND | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_SECOND // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_ARRAY_2_SKIPPED | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_SKIPPED +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IMPLICIT_MEMBER_ARRAY_2_OVERLOADED | %FileCheck %s -check-prefix=IMPLICIT_MEMBER_OVERLOADED // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ARCHETYPE_GENERIC_1 | %FileCheck %s -check-prefix=ARCHETYPE_GENERIC_1 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PARAM_WITH_ERROR_AUTOCLOSURE| %FileCheck %s -check-prefix=PARAM_WITH_ERROR_AUTOCLOSURE @@ -579,10 +582,12 @@ func testTupleShuffle() { // SHUFFLE_2-DAG: Decl[GlobalVar]/CurrModule/TypeRelation[Identical]: s1[#String#]; name=s1 // SHUFFLE_2-DAG: Decl[GlobalVar]/CurrModule/TypeRelation[Identical]: s2[#String#]; name=s2 -// SHUFFLE_3: Begin completions, 3 items +// SHUFFLE_3: Begin completions, 4 items // SHUFFLE_3-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: foo[#SimpleEnum#]; name=foo // SHUFFLE_3-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: bar[#SimpleEnum#]; name=bar // SHUFFLE_3-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: baz[#SimpleEnum#]; name=baz +// SHUFFLE_3-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): SimpleEnum#})[#(into: inout Hasher) -> Void#]; name=hash(self: SimpleEnum) + class HasSubscript { subscript(idx: Int) -> String {} @@ -665,6 +670,8 @@ class TestStaticMemberCall { static func create2(_ arg1: Int, arg2: Int = 0, arg3: Int = 1, arg4: Int = 2) -> TestStaticMemberCall { return TestStaticMemberCall() } + static func createOverloaded(arg1: Int) -> TestStaticMemberCall { TestStaticMemberCall() } + static func createOverloaded(arg1: String) -> String { arg1 } } func testStaticMemberCall() { let _ = TestStaticMemberCall.create1(#^STATIC_METHOD_AFTERPAREN_1^#) @@ -693,24 +700,30 @@ func testStaticMemberCall() { // STATIC_METHOD_SKIPPED: Pattern/ExprSpecific: {#arg3: Int#}[#Int#]; // STATIC_METHOD_SKIPPED: Pattern/ExprSpecific: {#arg4: Int#}[#Int#]; // STATIC_METHOD_SKIPPED: End completions + + let _ = TestStaticMemberCall.createOverloaded(#^STATIC_METHOD_OVERLOADED^#) +// STATIC_METHOD_OVERLOADED: Begin completions, 2 items +// STATIC_METHOD_OVERLOADED-DAG: Decl[StaticMethod]/CurrNominal: ['(']{#arg1: Int#}[')'][#TestStaticMemberCall#]; name=arg1: Int +// STATIC_METHOD_OVERLOADED-DAG: Decl[StaticMethod]/CurrNominal: ['(']{#arg1: String#}[')'][#String#]; name=arg1: String +// STATIC_METHOD_OVERLOADED: End completions } func testImplicitMember() { let _: TestStaticMemberCall = .create1(#^IMPLICIT_MEMBER_AFTERPAREN_1^#) // IMPLICIT_MEMBER_AFTERPAREN_1: Begin completions, 1 items -// IMPLICIT_MEMBER_AFTERPAREN_1: Decl[StaticMethod]/CurrNominal: ['(']{#arg1: Int#}[')'][#TestStaticMemberCall#]; name=arg1: Int +// IMPLICIT_MEMBER_AFTERPAREN_1: Decl[StaticMethod]/CurrNominal/TypeRelation[Identical]: ['(']{#arg1: Int#}[')'][#TestStaticMemberCall#]; name=arg1: Int // IMPLICIT_MEMBER_AFTERPAREN_1: End completions let _: TestStaticMemberCall = .create2(#^IMPLICIT_MEMBER_AFTERPAREN_2^#) // IMPLICIT_MEMBER_AFTERPAREN_2: Begin completions -// IMPLICIT_MEMBER_AFTERPAREN_2-DAG: Decl[StaticMethod]/CurrNominal: ['(']{#(arg1): Int#}[')'][#TestStaticMemberCall#]; -// IMPLICIT_MEMBER_AFTERPAREN_2-DAG: Decl[StaticMethod]/CurrNominal: ['(']{#(arg1): Int#}, {#arg2: Int#}, {#arg3: Int#}, {#arg4: Int#}[')'][#TestStaticMemberCall#]; +// IMPLICIT_MEMBER_AFTERPAREN_2-DAG: Decl[StaticMethod]/CurrNominal/TypeRelation[Identical]: ['(']{#(arg1): Int#}[')'][#TestStaticMemberCall#]; +// IMPLICIT_MEMBER_AFTERPAREN_2-DAG: Decl[StaticMethod]/CurrNominal/TypeRelation[Identical]: ['(']{#(arg1): Int#}, {#arg2: Int#}, {#arg3: Int#}, {#arg4: Int#}[')'][#TestStaticMemberCall#]; // IMPLICIT_MEMBER_AFTERPAREN_2-DAG: Decl[Struct]/OtherModule[Swift]/IsSystem/TypeRelation[Identical]: Int[#Int#]; // IMPLICIT_MEMBER_AFTERPAREN_2-DAG: Literal[Integer]/None/TypeRelation[Identical]: 0[#Int#]; // IMPLICIT_MEMBER_AFTERPAREN_2: End completions let _: TestStaticMemberCall? = .create1(#^IMPLICIT_MEMBER_AFTERPAREN_3^#) // IMPLICIT_MEMBER_AFTERPAREN_3: Begin completions, 1 items -// IMPLICIT_MEMBER_AFTERPAREN_3: Decl[StaticMethod]/CurrNominal: ['(']{#arg1: Int#}[')'][#TestStaticMemberCall#]; name=arg1: Int +// IMPLICIT_MEMBER_AFTERPAREN_3: Decl[StaticMethod]/CurrNominal/TypeRelation[Convertible]: ['(']{#arg1: Int#}[')'][#TestStaticMemberCall#]; name=arg1: Int // IMPLICIT_MEMBER_AFTERPAREN_3: End completions let _: TestStaticMemberCall = .create2(1, #^IMPLICIT_MEMBER_SECOND^#) @@ -726,6 +739,12 @@ func testImplicitMember() { // IMPLICIT_MEMBER_SKIPPED: Pattern/ExprSpecific: {#arg3: Int#}[#Int#]; // IMPLICIT_MEMBER_SKIPPED: Pattern/ExprSpecific: {#arg4: Int#}[#Int#]; // IMPLICIT_MEMBER_SKIPPED: End completions + + let _: TestStaticMemberCall = .createOverloaded(#^IMPLICIT_MEMBER_OVERLOADED^#) +// IMPLICIT_MEMBER_OVERLOADED: Begin completions, 2 items +// IMPLICIT_MEMBER_OVERLOADED: Decl[StaticMethod]/CurrNominal/TypeRelation[Identical]: ['(']{#arg1: Int#}[')'][#TestStaticMemberCall#]; name=arg1: Int +// IMPLICIT_MEMBER_OVERLOADED: Decl[StaticMethod]/CurrNominal: ['(']{#arg1: String#}[')'][#String#]; name=arg1: String +// IMPLICIT_MEMBER_OVERLOADED: End completions } func testImplicitMemberInArrayLiteral() { struct Receiver { @@ -739,8 +758,12 @@ func testImplicitMemberInArrayLiteral() { // Same as IMPLICIT_MEMBER_AFTERPAREN_1. ]) Receiver([ + .create1(x: 1), .create2(#^IMPLICIT_MEMBER_ARRAY_1_AFTERPAREN_2^#), // Same as IMPLICIT_MEMBER_AFTERPAREN_2. + ]) + Receiver([ + .create1(x: 1), .create2(1, #^IMPLICIT_MEMBER_ARRAY_1_SECOND^# // Same as IMPLICIT_MEMBER_SECOND. ]) @@ -749,15 +772,22 @@ func testImplicitMemberInArrayLiteral() { // Same as IMPLICIT_MEMBER_SKIPPED. .create1(x: 12) ]) + Receiver(arg1: 12, arg2: [ + .create1(x: 12), + .createOverloaded(#^IMPLICIT_MEMBER_ARRAY_1_OVERLOADED^#) + // Same as IMPLICIT_MEMBER_OVERLOADED. + ]) let _: [TestStaticMemberCall] = [ .create1(#^IMPLICIT_MEMBER_ARRAY_2_AFTERPAREN_1^#), - // Same as STATIC_METHOD_AFTERPAREN_1. + // Same as IMPLICIT_MEMBER_AFTERPAREN_1. .create2(#^IMPLICIT_MEMBER_ARRAY_2_AFTERPAREN_2^#), - // Same as STATIC_METHOD_AFTERPAREN_2. + // Same as IMPLICIT_MEMBER_AFTERPAREN_2. .create2(1, #^IMPLICIT_MEMBER_ARRAY_2_SECOND^#), - // Same as STATIC_METHOD_SECOND. + // Same as IMPLICIT_MEMBER_SECOND. .create2(1, arg3: 2, #^IMPLICIT_MEMBER_ARRAY_2_SKIPPED^#), - // Same as STATIC_METHOD_SKIPPED. + // Same as IMPLICIT_MEMBER_SKIPPED. + .createOverloaded(#^IMPLICIT_MEMBER_ARRAY_2_OVERLOADED^#), + // Same as IMPLICIT_MEMBER_OVERLOADED ] } @@ -833,10 +863,11 @@ func testPamrameterFlags(_: Int, inoutArg: inout Int, autoclosureArg: @autoclosu func testTupleElement(arg: (SimpleEnum, SimpleEnum)) { testTupleElement(arg: (.foo, .#^TUPLEELEM_1^#)) -// TUPLEELEM_1: Begin completions, 3 items +// TUPLEELEM_1: Begin completions, 4 items // TUPLEELEM_1-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: foo[#SimpleEnum#]; name=foo // TUPLEELEM_1-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: bar[#SimpleEnum#]; name=bar // TUPLEELEM_1-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: baz[#SimpleEnum#]; name=baz +// TUPLEELEM_1-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): SimpleEnum#})[#(into: inout Hasher) -> Void#]; name=hash(self: SimpleEnum) // TUPLEELEM_1: End completions testTupleElement(arg: (.foo, .bar, .#^TUPLEELEM_2^#)) // TUPLEELEM_2-NOT: Begin completions @@ -852,10 +883,11 @@ func testKeyPathThunkInBase() { func foo(_ fn: (TestKP) -> Int) -> TestKPResult { TestKPResult() } foo(\.value).testFunc(.#^KEYPATH_THUNK_BASE^#) -// KEYPATH_THUNK_BASE: Begin completions, 3 items +// KEYPATH_THUNK_BASE: Begin completions, 4 items // KEYPATH_THUNK_BASE-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: foo[#SimpleEnum#]; name=foo // KEYPATH_THUNK_BASE-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: bar[#SimpleEnum#]; name=bar // KEYPATH_THUNK_BASE-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: baz[#SimpleEnum#]; name=baz +// KEYPATH_THUNK_BASE-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): SimpleEnum#})[#(into: inout Hasher) -> Void#]; name=hash(self: SimpleEnum) // KEYPATH_THUNK_BASE: End completions } diff --git a/test/IDE/complete_call_as_function.swift b/test/IDE/complete_call_as_function.swift index 836b3a9a7d84e..ebd371b95312c 100644 --- a/test/IDE/complete_call_as_function.swift +++ b/test/IDE/complete_call_as_function.swift @@ -111,10 +111,12 @@ func testCallAsFunctionOverloaded(fn: Functor) { fn(h: .left, v: .#^OVERLOADED_ARG2_VALUE^#) // FIXME: Should only suggest 'up' and 'down' (rdar://problem/60346573). -//OVERLOADED_ARG2_VALUE: Begin completions, 4 items +//OVERLOADED_ARG2_VALUE: Begin completions, 6 items //OVERLOADED_ARG2_VALUE-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: up[#Functor.Vertical#]; //OVERLOADED_ARG2_VALUE-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: down[#Functor.Vertical#]; +//OVERLOADED_ARG2_VALUE-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): Functor.Vertical#})[#(into: inout Hasher) -> Void#]; //OVERLOADED_ARG2_VALUE-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: left[#Functor.Horizontal#]; //OVERLOADED_ARG2_VALUE-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: right[#Functor.Horizontal#]; +//OVERLOADED_ARG2_VALUE-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): Functor.Horizontal#})[#(into: inout Hasher) -> Void#]; //OVERLOADED_ARG2_VALUE: End completions } diff --git a/test/IDE/complete_constrained.swift b/test/IDE/complete_constrained.swift index bb85a6c711c02..cc655f4af2ea2 100644 --- a/test/IDE/complete_constrained.swift +++ b/test/IDE/complete_constrained.swift @@ -117,9 +117,11 @@ struct Vegetarian: EatsFruit, EatsVegetables { } func testVegetarian(chef: Chef) { chef.cook(.#^CONDITIONAL_OVERLOAD_ARG^#) -// CONDITIONAL_OVERLOAD_ARG: Begin completions, 2 items +// CONDITIONAL_OVERLOAD_ARG: Begin completions, 4 items // CONDITIONAL_OVERLOAD_ARG-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: apple[#Fruit#]; name=apple +// CONDITIONAL_OVERLOAD_ARG-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): Fruit#})[#(into: inout Hasher) -> Void#]; name=hash(self: Fruit) // CONDITIONAL_OVERLOAD_ARG-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: broccoli[#Vegetable#]; name=broccoli +// CONDITIONAL_OVERLOAD_ARG-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): Vegetable#})[#(into: inout Hasher) -> Void#]; name=hash(self: Vegetable) // CONDITIONAL_OVERLOAD_ARG: End completions var chefMeta: Chef.Type = Chef.self diff --git a/test/IDE/complete_enum_elements.swift b/test/IDE/complete_enum_elements.swift index 7f4097efb0a9c..48d8b01d8b23a 100644 --- a/test/IDE/complete_enum_elements.swift +++ b/test/IDE/complete_enum_elements.swift @@ -138,10 +138,20 @@ enum FooEnum: CaseIterable { // FOO_ENUM_DOT_INVALID-NEXT: Decl[StaticVar]/CurrNominal: allCases[#[FooEnum]#]{{; name=.+$}} // FOO_ENUM_DOT_INVALID-NEXT: End completions -// FOO_ENUM_DOT_ELEMENTS: Begin completions, 3 items +// FOO_ENUM_DOT_ELEMENTS: Begin completions, 13 items // FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: Foo1[#FooEnum#]{{; name=.+$}} // FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: Foo2[#FooEnum#]{{; name=.+$}} // FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[StaticVar]/ExprSpecific/TypeRelation[Identical]: alias1[#FooEnum#]; name=alias1 +// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): FooEnum#})[#(into: inout Hasher) -> Void#]; name=hash(self: FooEnum) +// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[Constructor]/CurrNominal/IsSystem: AllCases({#arrayLiteral: FooEnum...#})[#Array#]; name=AllCases(arrayLiteral: FooEnum...) +// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[Constructor]/CurrNominal/IsSystem: AllCases()[#Array#]; name=AllCases() +// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[Constructor]/CurrNominal/IsSystem: AllCases({#(s): Sequence#})[#Array#]; name=AllCases(s: Sequence) +// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[Constructor]/CurrNominal/IsSystem: AllCases({#repeating: FooEnum#}, {#count: Int#})[#Array#]; name=AllCases(repeating: FooEnum, count: Int) +// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[Constructor]/CurrNominal/IsSystem: AllCases({#unsafeUninitializedCapacity: Int#}, {#initializingWith: (inout UnsafeMutableBufferPointer, inout Int) throws -> Void##(inout UnsafeMutableBufferPointer, inout Int) throws -> Void#})[' rethrows'][#Array#]; name=AllCases(unsafeUninitializedCapacity: Int, initializingWith: (inout UnsafeMutableBufferPointer, inout Int) throws -> Void) rethrows +// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[Constructor]/CurrNominal/IsSystem: AllCases({#from: Decoder#})[' throws'][#Array#]; name=AllCases(from: Decoder) throws +// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[Constructor]/CurrNominal/IsSystem: AllCases({#repeating: FooEnum#}, {#count: Int#})[#FooEnum.AllCases#]; name=AllCases(repeating: FooEnum, count: Int) +// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[Constructor]/CurrNominal/IsSystem: AllCases({#(elements): Sequence#})[#FooEnum.AllCases#]; name=AllCases(elements: Sequence) +// FOO_ENUM_DOT_ELEMENTS-NEXT: Decl[StaticVar]/CurrNominal: allCases[#[FooEnum]#]; name=allCases // FOO_ENUM_DOT_ELEMENTS-NEXT: End completions enum BarEnum { @@ -454,9 +464,12 @@ func testWithInvalid1() { func testUnqualified1(x: QuxEnum) { _ = x == .Qux1 || x == .#^UNRESOLVED_2^#Qux2 - // UNRESOLVED_2: Begin completions, 2 items + // UNRESOLVED_2: Begin completions // UNRESOLVED_2-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: Qux1[#QuxEnum#]; name=Qux1 // UNRESOLVED_2-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: Qux2[#QuxEnum#]; name=Qux2 + // UNRESOLVED_2-DAG: Decl[Constructor]/CurrNominal/IsSystem: RawValue({#bitPattern: UInt#})[#Int#]; name=RawValue(bitPattern: UInt) + // UNRESOLVED_2-DAG: Decl[Constructor]/CurrNominal: init({#rawValue: Int#})[#QuxEnum?#]; name=init(rawValue: Int) + // UNRESOLVED_2-DAG: Decl[InstanceMethod]/Super/IsSystem/TypeRelation[Invalid]: hash({#(self): QuxEnum#})[#(into: inout Hasher) -> Void#]; name=hash(self: QuxEnum) // UNRESOLVED_2: End completions _ = (x == .Qux1#^UNRESOLVED_3^#) diff --git a/test/IDE/complete_exception.swift b/test/IDE/complete_exception.swift index 48d222ced7565..a5cef6bb5175b 100644 --- a/test/IDE/complete_exception.swift +++ b/test/IDE/complete_exception.swift @@ -5,11 +5,13 @@ // RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=CATCH2 | %FileCheck %s -check-prefix=CATCH2 // RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=THROW2 | %FileCheck %s -check-prefix=THROW2 // RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=CATCH3 | %FileCheck %s -check-prefix=CATCH3 +// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=THROW3 | %FileCheck %s -check-prefix=THROW3 // RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=TOP_LEVEL_CATCH1 | %FileCheck %s -check-prefix=CATCH1 // RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=TOP_LEVEL_THROW1 | %FileCheck %s -check-prefix=THROW1 // RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=TOP_LEVEL_CATCH2 | %FileCheck %s -check-prefix=CATCH2 // RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=TOP_LEVEL_THROW2 | %FileCheck %s -check-prefix=THROW2 +// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=TOP_LEVEL_THROW3 | %FileCheck %s -check-prefix=THROW3 // RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=INSIDE_CATCH1 > %t.inside_catch1 // RUN: %FileCheck %s -check-prefix=STMT < %t.inside_catch1 @@ -70,10 +72,10 @@ func test001() { do {} catch #^CATCH1^# // CATCH1: Begin completions -// CATCH1-DAG: Decl[Enum]/CurrModule: Error4[#Error4#]; name=Error4{{$}} -// CATCH1-DAG: Decl[Class]/CurrModule: Error3[#Error3#]; name=Error3{{$}} -// CATCH1-DAG: Decl[Class]/CurrModule: Error2[#Error2#]; name=Error2{{$}} -// CATCH1-DAG: Decl[Class]/CurrModule: Error1[#Error1#]; name=Error1{{$}} +// CATCH1-DAG: Decl[Enum]/CurrModule/TypeRelation[Convertible]: Error4[#Error4#]; name=Error4{{$}} +// CATCH1-DAG: Decl[Class]/CurrModule/TypeRelation[Convertible]: Error3[#Error3#]; name=Error3{{$}} +// CATCH1-DAG: Decl[Class]/CurrModule/TypeRelation[Convertible]: Error2[#Error2#]; name=Error2{{$}} +// CATCH1-DAG: Decl[Class]/CurrModule/TypeRelation[Convertible]: Error1[#Error1#]; name=Error1{{$}} // CATCH1-DAG: Keyword[let]/None: let{{; name=.+$}} // CATCH1-DAG: Decl[Class]/CurrModule: NoneError1[#NoneError1#]; name=NoneError1{{$}} // CATCH1-DAG: Decl[Class]/OtherModule[Foundation]/IsSystem: NSError[#NSError#]{{; name=.+$}} @@ -126,11 +128,20 @@ func test005() { // CATCH3: End completions } +func testInvalid() { + try throw Error4.#^THROW3^# +// THROW3: Begin completions +// THROW3: Decl[EnumElement]/CurrNominal: E1[#Error4#]{{; name=.+$}} +// THROW3: Decl[EnumElement]/CurrNominal: E2({#Int32#})[#Error4#]{{; name=.+$}} +// THROW3: End completions +} + //===--- Top-level throw/catch do {} catch #^TOP_LEVEL_CATCH1^# {} throw #^TOP_LEVEL_THROW1^# do {} catch Error4.#^TOP_LEVEL_CATCH2^# {} throw Error4.#^TOP_LEVEL_THROW2^# +try throw Error4.#^TOP_LEVEL_THROW3^# //===--- Inside catch body diff --git a/test/IDE/complete_in_ifconfig.swift b/test/IDE/complete_in_ifconfig.swift new file mode 100644 index 0000000000000..56b8bcfe46b6b --- /dev/null +++ b/test/IDE/complete_in_ifconfig.swift @@ -0,0 +1,75 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-ide-test -batch-code-completion -source-filename %s -filecheck %raw-FileCheck -completion-output-dir %t + +struct MyStruct { + init() {} + var value: Int +} + +// MEMBER_MyStruct: Begin completions, 2 items +// MEMBER_MyStruct-DAG: Keyword[self]/CurrNominal: self[#MyStruct#]; +// MEMBER_MyStruct-DAG: Decl[InstanceVar]/CurrNominal: value[#Int#]; +// MEMBER_MyStruct: End completions + +#if true +let toplevelActive = MyStruct() +_ = toplevelActive.#^MEMBER_TOPLEVEL_ACTIVE?check=MEMBER_MyStruct^# +#else +let toplevelInactive = MyStruct() +_ = toplevelInactive.#^MEMBER_TOPLEVEL_INACTIVE?check=MEMBER_MyStruct^# +#endif + +func foo() { +#if true + let infuncActive = MyStruct() + _ = infuncActive.#^MEMBER_INFUNC_ACTIVE?check=MEMBER_MyStruct^# +#else + let infuncInactive = MyStruct() + _ = infuncInactive.#^MEMBER_INFUNC_INACTIVE?check=MEMBER_MyStruct^# +#endif +} + +protocol TestP { + func foo() + func bar() +} +struct TestStruct: TestP { +#if true + func foo() {} + func #^OVERRIDE_ACTIVE^# +// OVERRIDE_ACTIVE: Begin completions, 1 items +// OVERRIDE_ACTIVE-DAG: Decl[InstanceMethod]/Super: bar() {|}; +// OVERRIDE_ACTIVE: End completions +#else + func bar() {} + func #^OVERRIDE_INACTIVE^# +// OVERRIDE_INACTIVE: Begin completions, 1 items +// OVERRIDE_INACTIVE-DAG: Decl[InstanceMethod]/Super: foo() {|}; +// OVERRIDE_INACTIVE: End completions +#endif +} + +struct TestStruct2 { +#if true + func activeFunc() {} + func test() { + self.#^SELF_ACTIVE^# + } +// SELF_ACTIVE: Begin completions, 3 items +// SELF_ACTIVE-DAG: Keyword[self]/CurrNominal: self[#TestStruct2#]; +// SELF_ACTIVE-DAG: Decl[InstanceMethod]/CurrNominal: activeFunc()[#Void#]; +// SELF_ACTIVE-DAG: Decl[InstanceMethod]/CurrNominal: test()[#Void#]; +// SELF_ACTIVE: End completions +#else + func inactiveFunc() {} + func test() { + self.#^SELF_INACTIVE^# + } +// SELF_INACTIVE: Begin completions, 3 items +// SELF_INACTIVE-DAG: Keyword[self]/CurrNominal: self[#TestStruct2#]; +// SELF_INACTIVE-DAG: Decl[InstanceMethod]/CurrNominal: inactiveFunc()[#Void#]; +// SELF_INACTIVE-DAG: Decl[InstanceMethod]/CurrNominal: test()[#Void#]; +// SELF_INACTIVE: End completions +#endif +} + diff --git a/test/IDE/complete_property_delegate_attribute.swift b/test/IDE/complete_property_delegate_attribute.swift index 5cf00f41e1b1b..ba1de7930993d 100644 --- a/test/IDE/complete_property_delegate_attribute.swift +++ b/test/IDE/complete_property_delegate_attribute.swift @@ -34,9 +34,10 @@ struct TestStruct { @MyStruct(arg1: .#^ARG_MyEnum_DOT^# var test3 -// ARG_MyEnum_DOT: Begin completions, 2 items +// ARG_MyEnum_DOT: Begin completions, 3 items // ARG_MyEnum_DOT-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: east[#MyEnum#]; name=east // ARG_MyEnum_DOT-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: west[#MyEnum#]; name=west +// ARG_MyEnum_DOT-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): MyEnum#})[#(into: inout Hasher) -> Void#]; // ARG_MyEnum_DOT: End completions @MyStruct(arg1: MyEnum.#^ARG_MyEnum_NOBINDING^#) diff --git a/test/IDE/complete_rdar67155695.swift b/test/IDE/complete_rdar67155695.swift new file mode 100644 index 0000000000000..9682653b1f662 --- /dev/null +++ b/test/IDE/complete_rdar67155695.swift @@ -0,0 +1,111 @@ +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PUBLIC | %FileCheck %s --check-prefix=PUBLIC +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=INTERNAL | %FileCheck %s --check-prefix=INTERNAL +// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=PRIVATE | %FileCheck %s --check-prefix=PRIVATE + +public protocol PubP {} + +public extension PubP { + func availableP_availableC() {} + + func availableP_unavailableC() {} + + @available(*, unavailable) + func unavailableP_availableC() {} + + @available(*, unavailable) + func unavailableP_unavailableC() {} +} + +struct TestForPubP: PubP { + func availableP_availableC() {} + + @available(*, unavailable) + func availableP_unavailableC() {} + + func unavailableP_availableC() {} + + @available(*, unavailable) + func unavailableP_unavailableC() {} +} + +func test(val: TestForPubP) { + val.#^PUBLIC^# +// PUBLIC: Begin completions, 4 items +// PUBLIC-DAG: Keyword[self]/CurrNominal: self[#TestForPubP#]; +// PUBLIC-DAG: Decl[InstanceMethod]/CurrNominal: unavailableP_availableC()[#Void#]; +// PUBLIC-DAG: Decl[InstanceMethod]/Super: availableP_availableC()[#Void#]; +// PUBLIC-DAG: Decl[InstanceMethod]/Super: availableP_unavailableC()[#Void#]; +// PUBLIC: End completions +} + +protocol InternalP {} + +extension InternalP { + func availableP_availableC() {} + + func availableP_unavailableC() {} + + @available(*, unavailable) + func unavailableP_availableC() {} + + @available(*, unavailable) + func unavailableP_unavailableC() {} +} + +struct TestForInternalP: InternalP { + func availableP_availableC() {} + + @available(*, unavailable) + func availableP_unavailableC() {} + + func unavailableP_availableC() {} + + @available(*, unavailable) + func unavailableP_unavailableC() {} +} + +func test(val: TestForInternalP) { + val.#^INTERNAL^# +// INTERNAL: Begin completions, 4 items +// INTERNAL-DAG: Keyword[self]/CurrNominal: self[#TestForInternalP#]; +// INTERNAL-DAG: Decl[InstanceMethod]/CurrNominal: availableP_availableC()[#Void#]; +// INTERNAL-DAG: Decl[InstanceMethod]/CurrNominal: unavailableP_availableC()[#Void#]; +// INTERNAL-DAG: Decl[InstanceMethod]/Super: availableP_unavailableC()[#Void#]; +// INTERNAL: End completions +} + +private protocol PrivP {} + +private extension PrivP { + func availableP_availableC() {} + + func availableP_unavailableC() {} + + @available(*, unavailable) + func unavailableP_availableC() {} + + @available(*, unavailable) + func unavailableP_unavailableC() {} +} + +struct TestForPrivP: PrivP { + func availableP_availableC() {} + + @available(*, unavailable) + func availableP_unavailableC() {} + + func unavailableP_availableC() {} + + @available(*, unavailable) + func unavailableP_unavailableC() {} +} + +func test(val: TestForPrivP) { + val.#^PRIVATE^# +// PRIVATE: Begin completions, 4 items +// PRIVATE-DAG: Keyword[self]/CurrNominal: self[#TestForPrivP#]; +// PRIVATE-DAG: Decl[InstanceMethod]/CurrNominal: availableP_availableC()[#Void#]; +// PRIVATE-DAG: Decl[InstanceMethod]/CurrNominal: unavailableP_availableC()[#Void#]; +// PRIVATE-DAG: Decl[InstanceMethod]/Super: availableP_unavailableC()[#Void#]; +// PRIVATE-DAG: End completions +} diff --git a/test/IDE/complete_stmt_controlling_expr.swift b/test/IDE/complete_stmt_controlling_expr.swift index b76a9bfad2f14..ccbabf4c8395f 100644 --- a/test/IDE/complete_stmt_controlling_expr.swift +++ b/test/IDE/complete_stmt_controlling_expr.swift @@ -644,11 +644,17 @@ func testGuardCase(x:FooStruct?) { // FOOSTRUCT_LOCALVAL-DAG: Decl[LocalVar]/Local{{(/TypeRelation\[Convertible\])?}}: boundVal[#FooStruct#]; // FOOSTRUCT_LOCALVAL: End completions -// OPTIONAL_FOOSTRUCT: Begin completions, 5 items +// OPTIONAL_FOOSTRUCT: Begin completions, 9 items // OPTIONAL_FOOSTRUCT-DAG: Keyword[nil]/None/Erase[1]: nil[#FooStruct?#]; name=nil // OPTIONAL_FOOSTRUCT-DAG: Decl[EnumElement]/CurrNominal/IsSystem: none[#Optional#]; name=none // OPTIONAL_FOOSTRUCT-DAG: Decl[EnumElement]/CurrNominal/IsSystem: some({#FooStruct#})[#Optional#]; name=some(FooStruct) // FIXME: 'FooStruct' members should not be shown. // OPTIONAL_FOOSTRUCT-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: init()[#FooStruct#]; name=init() // OPTIONAL_FOOSTRUCT-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: init({#Int#})[#FooStruct#]; name=init(Int) +// OPTIONAL_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal: boolGen({#(self): FooStruct#})[#() -> Bool#]; name=boolGen(self: FooStruct) +// OPTIONAL_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal: intGen({#(self): FooStruct#})[#() -> Int#]; name=intGen(self: FooStruct) +// OPTIONAL_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: map({#(self): Optional#})[#((FooStruct) throws -> U) -> U?#]; name=map(self: Optional) +// OPTIONAL_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: flatMap({#(self): Optional#})[#((FooStruct) throws -> U?) -> U?#]; name=flatMap(self: Optional) +// OPTIONAL_FOOSTRUCT-NOT: init({#(some): +// OPTIONAL_FOOSTRUCT-NOT: init({#nilLiteral: // OPTIONAL_FOOSTRUCT: End completions diff --git a/test/IDE/complete_string_interpolation.swift b/test/IDE/complete_string_interpolation.swift index 4187ca51cf480..1089516beb5f1 100644 --- a/test/IDE/complete_string_interpolation.swift +++ b/test/IDE/complete_string_interpolation.swift @@ -31,17 +31,19 @@ struct MsgInterpolation: StringInterpolationProtocol { var messenger = Messenger() func testMessenger(intVal: Int, fltVal: Float) { messenger.send(" \(intVal, format: .#^OVERLOAD_INT^#) ") -// OVERLOAD_INT: Begin completions, 4 items +// OVERLOAD_INT: Begin completions, 5 items // OVERLOAD_INT-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: decimal[#MsgInterpolation.IntFormat#]; // OVERLOAD_INT-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: hex[#MsgInterpolation.IntFormat#]; +// OVERLOAD_INT-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): MsgInterpolation.IntFormat#})[#(into: inout Hasher) -> Void#]; // OVERLOAD_INT-DAG: Decl[StaticMethod]/CurrNominal/TypeRelation[Identical]: precision({#Int#})[#MsgInterpolation.FloatFormat#]; // OVERLOAD_INT-DAG: Decl[StaticVar]/CurrNominal/TypeRelation[Identical]: hex[#MsgInterpolation.FloatFormat#]; // OVERLOAD_INT: End completions messenger.send(" \(fltVal, format: .#^OVERLOAD_FLT^#) ") -// OVERLOAD_FLT: Begin completions, 4 items +// OVERLOAD_FLT: Begin completions, 5 items // OVERLOAD_FLT-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: decimal[#MsgInterpolation.IntFormat#]; // OVERLOAD_FLT-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: hex[#MsgInterpolation.IntFormat#]; +// OVERLOAD_FLT-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): MsgInterpolation.IntFormat#})[#(into: inout Hasher) -> Void#]; // OVERLOAD_FLT-DAG: Decl[StaticMethod]/ExprSpecific/TypeRelation[Identical]: precision({#Int#})[#MsgInterpolation.FloatFormat#]; // OVERLOAD_FLT-DAG: Decl[StaticVar]/ExprSpecific/TypeRelation[Identical]: hex[#MsgInterpolation.FloatFormat#]; // OVERLOAD_FLT: End completions diff --git a/test/IDE/complete_type.swift b/test/IDE/complete_type.swift index 04b9158fda578..4178ff2840b04 100644 --- a/test/IDE/complete_type.swift +++ b/test/IDE/complete_type.swift @@ -765,3 +765,17 @@ func testUnbound2(x: OuterStruct.Inner.#^UNBOUND_DOT_3^#) {} // UNBOUND_DOT_3: Begin completions // UNBOUND_DOT_3-DAG: Keyword/None: Type[#OuterStruct.Inner.Type#]; name=Type // UNBOUND_DOT_3: End completions + +// rdar://problem/67102794 +struct HasProtoAlias { + typealias ProtoAlias = FooProtocol +} +extension FooStruct: HasProtoAlias.#^EXTENSION_INHERITANCE_1?check=EXTENSION_INHERITANCE^# {} + +struct ContainExtension { + extension FooStruct: HasProtoAlias.#^EXTENSION_INHERITANCE_2?check=EXTENSION_INHERITANCE^# {} +} +// EXTENSION_INHERITANCE: Begin completions, 2 items +// EXTENSION_INHERITANCE-DAG: Decl[TypeAlias]/CurrNominal: ProtoAlias[#FooProtocol#]; +// EXTENSION_INHERITANCE-DAG: Keyword/None: Type[#HasProtoAlias.Type#]; +// EXTENSION_INHERITANCE: End completions diff --git a/test/IDE/complete_unresolved_chains.swift b/test/IDE/complete_unresolved_chains.swift new file mode 100644 index 0000000000000..f1d2930ce7e17 --- /dev/null +++ b/test/IDE/complete_unresolved_chains.swift @@ -0,0 +1,85 @@ +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=UNRESOLVED_CHAIN_1 | %FileCheck %s -check-prefix=UNRESOLVED_CHAIN_1 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=UNRESOLVED_CHAIN_2 | %FileCheck %s -check-prefix=UNRESOLVED_CHAIN_1 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=UNRESOLVED_CHAIN_3 | %FileCheck %s -check-prefix=UNRESOLVED_CHAIN_1 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=UNRESOLVED_CHAIN_4 | %FileCheck %s -check-prefix=UNRESOLVED_CHAIN_1 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=UNRESOLVED_CHAIN_5 | %FileCheck %s -check-prefix=UNRESOLVED_CHAIN_2 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=UNRESOLVED_CHAIN_6 | %FileCheck %s -check-prefix=UNRESOLVED_CHAIN_3 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=UNRESOLVED_CHAIN_7 | %FileCheck %s -check-prefix=UNRESOLVED_CHAIN_3 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=DOUBLY_NESTED| %FileCheck %s -check-prefix=DOUBLY_NESTED + +struct ChainStruct1 { + static var chain2 = ChainStruct2() + static func chain2Func() -> ChainStruct2 { ChainStruct2() } +} + +struct ChainStruct2 { + var chainStruct1 = ChainStruct1() + var chainEnum = ChainEnum.case1 + var chainStruct2: ChainStruct2 { ChainStruct2() } + func chainStruct1Func() -> ChainStruct1 { ChainStruct1() } +} + +enum ChainEnum { + case case1 + var chainStruct2: ChainStruct2 { ChainStruct2() } + func chainStruct2Func() -> ChainStruct2 { ChainStruct2() } +} + +func testChains() { + let _: ChainStruct1 = .chain2.#^UNRESOLVED_CHAIN_1^# + let _: ChainStruct1 = .chain2.chainStruct2.#^UNRESOLVED_CHAIN_2^# + let _: ChainStruct1 = .chain2Func().#^UNRESOLVED_CHAIN_3^# + let _: ChainStruct1 = .chain2Func().#^UNRESOLVED_CHAIN_4^# + let _: ChainEnum = .case1.#^UNRESOLVED_CHAIN_5^# + let _: ChainEnum = .case1.chainStruct2.#^UNRESOLVED_CHAIN_6^# + let _: ChainEnum = .case1.chainStruct2.#^UNRESOLVED_CHAIN_7^# +} + +// UNRESOLVED_CHAIN_1: Begin completions, 5 items +// UNRESOLVED_CHAIN_1-DAG: Keyword[self]/CurrNominal: self[#ChainStruct2#]; name=self +// UNRESOLVED_CHAIN_1-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: chainStruct1[#ChainStruct1#]; +// UNRESOLVED_CHAIN_1-DAG: Decl[InstanceVar]/CurrNominal: chainEnum[#ChainEnum#]; +// UNRESOLVED_CHAIN_1-DAG: Decl[InstanceVar]/CurrNominal: chainStruct2[#ChainStruct2#]; +// UNRESOLVED_CHAIN_1-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: chainStruct1Func()[#ChainStruct1#]; +// UNRESOLVED_CHAIN_1: End completions + +// UNRESOLVED_CHAIN_2: Begin completions, 5 items +// UNRESOLVED_CHAIN_2-DAG: Keyword[self]/CurrNominal: self[#ChainEnum#]; name=self +// UNRESOLVED_CHAIN_2-DAG: Decl[InstanceVar]/CurrNominal: chainStruct2[#ChainStruct2#]; name=chainStruct2 +// UNRESOLVED_CHAIN_2-DAG: Decl[InstanceMethod]/CurrNominal: chainStruct2Func()[#ChainStruct2#]; name=chainStruct2Func() +// UNRESOLVED_CHAIN_2-DAG: Decl[InstanceVar]/CurrNominal: hashValue[#Int#]; name=hashValue +// UNRESOLVED_CHAIN_2-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#into: &Hasher#})[#Void#]; name=hash(into: &Hasher) +// UNRESOLVED_CHAIN_2: End completions + +// UNRESOLVED_CHAIN_3: Begin completions, 5 items +// UNRESOLVED_CHAIN_3-DAG: Decl[InstanceVar]/CurrNominal: chainStruct1[#ChainStruct1#]; name=chainStruct1 +// UNRESOLVED_CHAIN_3-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: chainEnum[#ChainEnum#]; name=chainEnum +// UNRESOLVED_CHAIN_3-DAG: Decl[InstanceVar]/CurrNominal: chainStruct2[#ChainStruct2#]; name=chainStruct2 +// UNRESOLVED_CHAIN_3-DAG: Decl[InstanceMethod]/CurrNominal: chainStruct1Func()[#ChainStruct1#]; name=chainStruct1Func() +// UNRESOLVED_CHAIN_3: End completions + +class Outer { + class Inner: Outer { + class InnerInner: Inner {} + static var outer = Outer() + static var inner = Inner() + static func makeOuter() -> Outer { Outer() } + static func makeInner() -> Inner { Inner() } + } +} + +func testDoublyNestedType() { + let _: Outer = .Inner.#^DOUBLY_NESTED^# +} + +// DOUBLY_NESTED: Begin completions, 8 items +// DOUBLY_NESTED-DAG: Keyword[self]/CurrNominal: self[#Outer.Inner.Type#]; name=self +// DOUBLY_NESTED-DAG: Decl[Class]/CurrNominal/TypeRelation[Convertible]: InnerInner[#Outer.Inner.InnerInner#]; +// DOUBLY_NESTED-DAG: Decl[StaticVar]/CurrNominal/TypeRelation[Identical]: outer[#Outer#]; +// DOUBLY_NESTED-DAG: Decl[StaticVar]/CurrNominal/TypeRelation[Convertible]: inner[#Outer.Inner#]; +// DOUBLY_NESTED-DAG: Decl[StaticMethod]/CurrNominal/TypeRelation[Identical]: makeOuter()[#Outer#]; +// DOUBLY_NESTED-DAG: Decl[StaticMethod]/CurrNominal/TypeRelation[Convertible]: makeInner()[#Outer.Inner#]; +// DOUBLY_NESTED-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: init()[#Outer.Inner#]; +// DOUBLY_NESTED-DAG: Decl[Class]/Super/TypeRelation[Convertible]: Inner[#Outer.Inner#]; +// DOUBLY_NESTED: End completions + diff --git a/test/IDE/complete_unresolved_members.swift b/test/IDE/complete_unresolved_members.swift index 7a895c550c665..53d20a8a07d36 100644 --- a/test/IDE/complete_unresolved_members.swift +++ b/test/IDE/complete_unresolved_members.swift @@ -109,9 +109,9 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERICPARAM_21 | %FileCheck %s -check-prefix=GENERICPARAM_1 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=DECL_MEMBER_INIT_1 | %FileCheck %s -check-prefix=UNRESOLVED_3 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=DEFAULT_ARG_1 | %FileCheck %s -check-prefix=UNRESOLVED_3_NOTIDEAL -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=DEFAULT_ARG_2 | %FileCheck %s -check-prefix=UNRESOLVED_3_NOTIDEAL -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=DEFAULT_ARG_3 | %FileCheck %s -check-prefix=UNRESOLVED_3_NOTIDEAL +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=DEFAULT_ARG_1 | %FileCheck %s -check-prefix=UNRESOLVED_3 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=DEFAULT_ARG_2 | %FileCheck %s -check-prefix=UNRESOLVED_3 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=DEFAULT_ARG_3 | %FileCheck %s -check-prefix=UNRESOLVED_3 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TYPEPARAM_IN_CONTEXTTYPE_1 | %FileCheck %s -check-prefix=TYPEPARAM_IN_CONTEXTTYPE_1 @@ -226,7 +226,8 @@ class C2 { // UNRESOLVED_1-DAG: Decl[StaticVar]/ExprSpecific/TypeRelation[Identical]: Option1[#SomeOptions1#]; name=Option1 // UNRESOLVED_1-DAG: Decl[StaticVar]/ExprSpecific/TypeRelation[Identical]: Option2[#SomeOptions1#]; name=Option2 // UNRESOLVED_1-DAG: Decl[StaticVar]/ExprSpecific/TypeRelation[Identical]: Option3[#SomeOptions1#]; name=Option3 -// UNRESOLVED_1-NOT: Not +// UNRESOLVED_1-DAG: Decl[StaticVar]/CurrNominal: NotOption[#Int#]; name=NotOption +// UNRESOLVED_1-NOT: NotStaticOption // UNRESOLVED_1_NOTIDEAL: Begin completions // UNRESOLVED_1_NOTIDEAL-NOT: SomeEnum1 @@ -234,7 +235,8 @@ class C2 { // UNRESOLVED_1_NOTIDEAL-DAG: Decl[StaticVar]/CurrNominal/TypeRelation[Identical]: Option1[#SomeOptions1#]; name=Option1 // UNRESOLVED_1_NOTIDEAL-DAG: Decl[StaticVar]/CurrNominal/TypeRelation[Identical]: Option2[#SomeOptions1#]; name=Option2 // UNRESOLVED_1_NOTIDEAL-DAG: Decl[StaticVar]/CurrNominal/TypeRelation[Identical]: Option3[#SomeOptions1#]; name=Option3 -// UNRESOLVED_1_NOTIDEAL-NOT: Not +// UNRESOLVED_1_NOTIDEAL-DAG: Decl[StaticVar]/CurrNominal: NotOption[#Int#]; name=NotOption +// UNRESOLVED_1_NOTIDEAL-NOT: NotStaticOption } class C3 { @@ -274,39 +276,49 @@ class C4 { var _: SomeEnum1??? = .#^UNRESOLVED_OPT_3^# } } -// UNRESOLVED_3: Begin completions, 2 items +// UNRESOLVED_3: Begin completions, 3 items // UNRESOLVED_3-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: North[#SomeEnum1#]; name=North // UNRESOLVED_3-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: South[#SomeEnum1#]; name=South +// UNRESOLVED_3-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): SomeEnum1#})[#(into: inout Hasher) -> Void#]; name=hash(self: SomeEnum1) // UNRESOLVED_3-NOT: SomeOptions1 // UNRESOLVED_3-NOT: SomeOptions2 // UNRESOLVED_3-NOT: none // UNRESOLVED_3-NOT: some( -// UNRESOLVED_3_NOTIDEAL: Begin completions, 2 items +// UNRESOLVED_3_NOTIDEAL: Begin completions, 3 items // UNRESOLVED_3_NOTIDEAL-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: North[#SomeEnum1#]; name=North // UNRESOLVED_3_NOTIDEAL-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: South[#SomeEnum1#]; name=South +// UNRESOLVED_3_NOTIDEAL-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): SomeEnum1#})[#(into: inout Hasher) -> Void#]; name=hash(self: SomeEnum1) // UNRESOLVED_3_NOTIDEAL-NOT: SomeOptions1 // UNRESOLVED_3_NOTIDEAL-NOT: SomeOptions2 // UNRESOLVED_3_NOTIDEAL-NOT: none // UNRESOLVED_3_NOTIDEAL-NOT: some( -// UNRESOLVED_3_OPT: Begin completions, 5 items +// UNRESOLVED_3_OPT: Begin completions, 9 items // UNRESOLVED_3_OPT-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Convertible]: North[#SomeEnum1#]; // UNRESOLVED_3_OPT-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Convertible]: South[#SomeEnum1#]; +// UNRESOLVED_3_OPT-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): SomeEnum1#})[#(into: inout Hasher) -> Void#]; // UNRESOLVED_3_OPT-DAG: Keyword[nil]/None/Erase[1]: nil[#SomeEnum1?#]; name=nil // UNRESOLVED_3_OPT-DAG: Decl[EnumElement]/CurrNominal/IsSystem: none[#Optional#]; name=none // UNRESOLVED_3_OPT-DAG: Decl[EnumElement]/CurrNominal/IsSystem: some({#SomeEnum1#})[#Optional#]; +// UNRESOLVED_3_OPT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: map({#(self): Optional#})[#((SomeEnum1) throws -> U) -> U?#]; +// UNRESOLVED_3_OPT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: flatMap({#(self): Optional#})[#((SomeEnum1) throws -> U?) -> U?#]; // UNRESOLVED_3_OPT-NOT: init({#(some): // UNRESOLVED_3_OPT-NOT: init({#nilLiteral: +// UNRESOLVED_3_OPT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem/TypeRelation[Invalid]: hash({#(self): Optional#})[#(into: inout Hasher) -> Void#]; -// UNRESOLVED_3_OPTOPTOPT: Begin completions, 5 items +// UNRESOLVED_3_OPTOPTOPT: Begin completions, 9 items // UNRESOLVED_3_OPTOPTOPT-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Convertible]: North[#SomeEnum1#]; // UNRESOLVED_3_OPTOPTOPT-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Convertible]: South[#SomeEnum1#]; +// UNRESOLVED_3_OPTOPTOPT-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): SomeEnum1#})[#(into: inout Hasher) -> Void#]; // UNRESOLVED_3_OPTOPTOPT-DAG: Keyword[nil]/None/Erase[1]: nil[#SomeEnum1???#]; name=nil // UNRESOLVED_3_OPTOPTOPT-DAG: Decl[EnumElement]/CurrNominal/IsSystem: none[#Optional#]; name=none // UNRESOLVED_3_OPTOPTOPT-DAG: Decl[EnumElement]/CurrNominal/IsSystem: some({#SomeEnum1??#})[#Optional#]; +// UNRESOLVED_3_OPTOPTOPT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: map({#(self): Optional#})[#((SomeEnum1??) throws -> U) -> U?#]; +// UNRESOLVED_3_OPTOPTOPT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: flatMap({#(self): Optional#})[#((SomeEnum1??) throws -> U?) -> U?#]; // UNRESOLVED_3_OPTOPTOPT-NOT: init({#(some): // UNRESOLVED_3_OPTOPTOPT-NOT: init({#nilLiteral: +// UNRESOLVED_3_OPTOPTOPT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem/TypeRelation[Invalid]: hash({#(self): Optional#})[#(into: inout Hasher) -> Void#]; enum Somewhere { case earth, mars @@ -317,14 +329,18 @@ extension Optional where Wrapped == Somewhere { } func testOptionalWithCustomExtension() { var _: Somewhere? = .#^UNRESOLVED_OPT_4^# -// UNRESOLVED_OPT_4: Begin completions, 7 items +// UNRESOLVED_OPT_4: Begin completions, 11 items // UNRESOLVED_OPT_4-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Convertible]: earth[#Somewhere#]; // UNRESOLVED_OPT_4-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Convertible]: mars[#Somewhere#]; +// UNRESOLVED_OPT_4-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): Somewhere#})[#(into: inout Hasher) -> Void#]; // UNRESOLVED_OPT_4-DAG: Keyword[nil]/None/Erase[1]: nil[#Somewhere?#]; name=nil // UNRESOLVED_OPT_4-DAG: Decl[EnumElement]/CurrNominal/IsSystem: none[#Optional#]; name=none // UNRESOLVED_OPT_4-DAG: Decl[EnumElement]/CurrNominal/IsSystem: some({#Somewhere#})[#Optional#]; // UNRESOLVED_OPT_4-DAG: Decl[Constructor]/CurrNominal: init({#str: String#})[#Optional#]; name=init(str: String) // UNRESOLVED_OPT_4-DAG: Decl[StaticVar]/CurrNominal/TypeRelation[Identical]: nowhere[#Optional#]; name=nowhere +// UNRESOLVED_OPT_4-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: map({#(self): Optional#})[#((Somewhere) throws -> U) -> U?#]; +// UNRESOLVED_OPT_4-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: flatMap({#(self): Optional#})[#((Somewhere) throws -> U?) -> U?#]; +// UNRESOLVED_OPT_4-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem/TypeRelation[Invalid]: hash({#(self): Optional#})[#(into: inout Hasher) -> Void#]; // UNRESOLVED_OPT_4-NOT: init({#(some): // UNRESOLVED_OPT_4-NOT: init({#nilLiteral: // UNRESOLVED_OPT_4: End completions @@ -433,10 +449,11 @@ let _: [SomeEnum3:SomeEnum1] = [.Payload(.South):.South, .Payload(.#^UNRESOLVED_ func testAvail1(_ x: EnumAvail1) { testAvail1(.#^ENUM_AVAIL_1^#) } -// ENUM_AVAIL_1: Begin completions, 2 items +// ENUM_AVAIL_1: Begin completions, 3 items // ENUM_AVAIL_1-NOT: AAA // ENUM_AVAIL_1-DAG: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: aaa[#EnumAvail1#]; // ENUM_AVAIL_1-DAG: Decl[EnumElement]/ExprSpecific/NotRecommended/TypeRelation[Identical]: BBB[#EnumAvail1#]; +// ENUM_AVAIL_1-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): EnumAvail1#})[#(into: inout Hasher) -> Void#]; // ENUM_AVAIL_1-NOT: AAA // ENUM_AVAIL_1: End completions @@ -444,11 +461,11 @@ func testAvail2(_ x: OptionsAvail1) { testAvail2(.#^OPTIONS_AVAIL_1^#) } // OPTIONS_AVAIL_1: Begin completions -// ENUM_AVAIL_1-NOT: AAA +// OPTIONS_AVAIL_1-NOT: AAA // OPTIONS_AVAIL_1-DAG: Decl[StaticVar]/ExprSpecific/TypeRelation[Identical]: aaa[#OptionsAvail1#]; // OPTIONS_AVAIL_1-DAG: Decl[StaticVar]/ExprSpecific/NotRecommended/TypeRelation[Identical]: BBB[#OptionsAvail1#]; // OPTIONS_AVAIL_1-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Identical]: init({#rawValue: Int#})[#OptionsAvail1#] -// ENUM_AVAIL_1-NOT: AAA +// OPTIONS_AVAIL_1-NOT: AAA // OPTIONS_AVAIL_1: End completions func testWithLiteral1() { @@ -460,8 +477,9 @@ func testWithLiteral1() { } let s: S _ = s.takeEnum(thing: .#^WITH_LITERAL_1^#, other: 1.0) -// WITH_LITERAL_1: Begin completions, 1 items +// WITH_LITERAL_1: Begin completions, 2 items // WITH_LITERAL_1-NEXT: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: myCase[#S.MyEnum#]; +// WITH_LITERAL_1-NEXT: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): S.MyEnum#})[#(into: inout Hasher) -> Void#]; // WITH_LITERAL_1-NEXT: End completions } func testWithLiteral2() { @@ -484,8 +502,9 @@ func testWithLiteral3() { func takeEnum(thing: MyEnum, other: Double) {} func test(s: S) { _ = s.takeEnum(thing: .#^WITH_LITERAL_3^#, other: 1.0) -// WITH_LITERAL_3: Begin completions, 1 items +// WITH_LITERAL_3: Begin completions, 2 items // WITH_LITERAL_3-NEXT: Decl[EnumElement]/ExprSpecific/TypeRelation[Identical]: myCase[#MyEnum#]; +// WITH_LITERAL_3-NEXT: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): MyEnum#})[#(into: inout Hasher) -> Void#]; // WITH_LITERAL_3-NEXT: End completions } } @@ -521,11 +540,13 @@ func testNonOptSet() { let x: NonOptSet x = .#^NON_OPT_SET_1^# } -// NON_OPT_SET_1: Begin completions, 4 items +// NON_OPT_SET_1: Begin completions, 6 items // NON_OPT_SET_1-DAG: Decl[StaticVar]/ExprSpecific/TypeRelation[Identical]: a[#NonOptSet#] +// NON_OPT_SET_1-DAG: Decl[StaticVar]/CurrNominal: wrongType[#Int#]; // NON_OPT_SET_1-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Identical]: init({#x: Int#}, {#y: Int#})[#NonOptSet#] // NON_OPT_SET_1-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Identical]: init()[#NonOptSet#] // NON_OPT_SET_1-DAG: Decl[StaticMethod]/ExprSpecific/TypeRelation[Identical]: b()[#NonOptSet#] +// NON_OPT_SET_1-DAG: Decl[InstanceMethod]/ExprSpecific/TypeRelation[Identical]: notStatic({#(self): NonOptSet#})[#() -> NonOptSet#]; // NON_OPT_SET_1: End completions func testNonOptSet() { @@ -562,12 +583,12 @@ struct AnotherTy: MyProtocol {} func testSubType() { var _: BaseClass = .#^SUBTYPE_1^# } -// SUBTYPE_1: Begin completions, 3 items -// SUBTYPE_1-NOT: init(failable: +// SUBTYPE_1: Begin completions, 4 items // SUBTYPE_1-NOT: Concrete1( // SUBTYPE_1-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Identical]: init()[#BaseClass#]; // SUBTYPE_1-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: SubClass()[#BaseClass.SubClass#]; // SUBTYPE_1-DAG: Decl[StaticVar]/CurrNominal/TypeRelation[Convertible]: subInstance[#BaseClass.SubClass#]; +// SUBTYPE_1-DAG: Decl[Constructor]/CurrNominal: init({#failable: Void#})[#BaseClass?#]; // SUBTYPE_1: End completions func testMemberTypealias() { @@ -618,11 +639,11 @@ struct HasCreator { func testHasStaticClosure() { let _: HasCreator = .#^STATIC_CLOSURE_1^# } -// STATIC_CLOSURE_1: Begin completions, 2 items +// STATIC_CLOSURE_1: Begin completions, 3 items // STATIC_CLOSURE_1-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Identical]: init()[#HasCreator#]; // FIXME: Suggest 'create()[#HasCreateor#]', not 'create'. // STATIC_CLOSURE_1-DAG: Decl[StaticVar]/CurrNominal: create[#() -> HasCreator#]; -// STATIC_CLOSURE_1-NOT: create_curried +// STATIC_CLOSURE_1-DAG: Decl[StaticVar]/CurrNominal: create_curried[#() -> () -> HasCreator#]; // STATIC_CLOSURE_1: End completions struct HasOverloaded { @@ -633,11 +654,13 @@ struct HasOverloaded { } func testOverload(val: HasOverloaded) { let _ = val.takeEnum(.#^OVERLOADED_METHOD_1^#) -// OVERLOADED_METHOD_1: Begin completions, 4 items +// OVERLOADED_METHOD_1: Begin completions, 6 items // OVERLOADED_METHOD_1-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: South[#SomeEnum1#]; name=South // OVERLOADED_METHOD_1-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: North[#SomeEnum1#]; name=North +// OVERLOADED_METHOD_1-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): SomeEnum1#})[#(into: inout Hasher) -> Void#]; // OVERLOADED_METHOD_1-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: East[#SomeEnum2#]; name=East // OVERLOADED_METHOD_1-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: West[#SomeEnum2#]; name=West +// OVERLOADED_METHOD_1-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): SomeEnum2#})[#(into: inout Hasher) -> Void#]; // OVERLOADED_METHOD_1: End completions let _ = HasOverloaded.init(e: .#^OVERLOADED_INIT_1^#) @@ -761,10 +784,10 @@ extension MyStruct where T: OtherProtocol { func receiveMyStructOfMyProtocol(value: MyStruct) {} func testTypeParamInContextType() { receiveMyStructOfMyProtocol(value: .#^TYPEPARAM_IN_CONTEXTTYPE_1^#) -// TYPEPARAM_IN_CONTEXTTYPE_1: Begin completions, 2 items -// TYPEPARAM_IN_CONTEXTTYPE_1-NOT: otherProtocolOption +// TYPEPARAM_IN_CONTEXTTYPE_1: Begin completions, 3 items // TYPEPARAM_IN_CONTEXTTYPE_1-DAG: Decl[Constructor]/CurrNominal: init()[#MyStruct#]; // TYPEPARAM_IN_CONTEXTTYPE_1-DAG: Decl[StaticVar]/CurrNominal/TypeRelation[Convertible]: myProtocolOption[#MyStruct#]; +// TYPEPARAM_IN_CONTEXTTYPE_1-DAG: Decl[StaticVar]/CurrNominal: otherProtocolOption[#MyStruct#]; // TYPEPARAM_IN_CONTEXTTYPE_1: End completions } @@ -795,11 +818,13 @@ func testClosureReturnTypeForOverloaded() { overloadedClosureRcv { .#^OVERLOADED_CLOSURE_RETURN^# } -// OVERLOADED_CLOSURE_RETURN: Begin completions, 4 items +// OVERLOADED_CLOSURE_RETURN: Begin completions, 6 items // OVERLOADED_CLOSURE_RETURN-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: South[#SomeEnum1#]; // OVERLOADED_CLOSURE_RETURN-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: North[#SomeEnum1#]; +// OVERLOADED_CLOSURE_RETURN-DAG: Decl[InstanceMethod]/CurrNominal: hash({#(self): SomeEnum1#})[#(into: inout Hasher) -> Void#]; // OVERLOADED_CLOSURE_RETURN-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: East[#SomeEnum2#]; // OVERLOADED_CLOSURE_RETURN-DAG: Decl[EnumElement]/CurrNominal/TypeRelation[Identical]: West[#SomeEnum2#]; +// OVERLOADED_CLOSURE_RETURN-DAG: Decl[InstanceMethod]/CurrNominal: hash({#(self): SomeEnum2#})[#(into: inout Hasher) -> Void#]; // OVERLOADED_CLOSURE_RETURN: End completions } diff --git a/test/IDE/complete_user_accessible.swift b/test/IDE/complete_user_accessible.swift new file mode 100644 index 0000000000000..551648d195f31 --- /dev/null +++ b/test/IDE/complete_user_accessible.swift @@ -0,0 +1,19 @@ +/// Check that serialized non user accessible functions are not autocompleted. +/// rdar://problem/53891642 +/// SR-7460 + +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-module %S/Inputs/complete_user_accessibility_helper.swift -module-name helper -emit-module-path %t/helper.swiftmodule +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=USER-ACCESS -I %t | %FileCheck %s -check-prefix=USER-ACCESS + +import helper + +{ + _ = MyEnum.#^USER-ACCESS^# +// USER-ACCESS: Begin completions +// USER-ACCESS-DAG: Keyword[self]/CurrNominal: self[#MyEnum.Type#]; name=self +// USER-ACCESS-DAG: Keyword/CurrNominal: Type[#MyEnum.Type#]; name=Type +// USER-ACCESS-DAG: Decl[EnumElement]/CurrNominal: foo[#MyEnum#]; name=foo +// USER-ACCESS-DAG: Decl[EnumElement]/CurrNominal: bar[#MyEnum#]; name=bar +// USER-ACCESS-NOT: __derived_enum_equals +} diff --git a/test/IDE/print_clang_objc_async.swift b/test/IDE/print_clang_objc_async.swift new file mode 100644 index 0000000000000..7d3029fff8be6 --- /dev/null +++ b/test/IDE/print_clang_objc_async.swift @@ -0,0 +1,20 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -print-module -source-filename %s -module-to-print=ObjCConcurrency -function-definitions=false -enable-experimental-concurrency > %t/ObjCConcurrency.printed.txt +// RUN: %FileCheck -input-file %t/ObjCConcurrency.printed.txt %s + +// REQUIRES: objc_interop + +// CHECK-LABEL: class SlowServer : NSObject { +// CHECK-DAG: func doSomethingSlow(_ operation: String, completionHandler handler: @escaping (Int) -> Void) +// CHECK-DAG: func doSomethingSlow(_ operation: String) async -> Int +// CHECK-DAG: func doSomethingDangerous(_ operation: String, completionHandler handler: ((String?, Error?) -> Void)? = nil) +// CHECK-DAG: func doSomethingDangerous(_ operation: String) async throws -> String? +// CHECK-DAG: func checkAvailability(completionHandler: @escaping (Bool) -> Void) +// CHECK-DAG: func checkAvailability() async -> Bool +// CHECK-DAG: func findAnswer(completionHandler handler: @escaping (String?, Error?) -> Void) +// CHECK-DAG: func findAnswer() async throws -> String? +// CHECK-DAG: func findAnswerFailingly(completionHandler handler: @escaping (String?, Error?) -> Void) throws +// CHECK-DAG: func findAnswerFailingly() async throws -> String? +// CHECK-DAG: func doSomethingFun(_ operation: String) async +// CHECK: {{^[}]$}} diff --git a/test/IRGen/Inputs/comdat1.swift b/test/IRGen/Inputs/comdat1.swift new file mode 100644 index 0000000000000..f219fa273491d --- /dev/null +++ b/test/IRGen/Inputs/comdat1.swift @@ -0,0 +1,5 @@ +private final class C {} +public func f() { + var cs: [C] = [] + cs.append(C()) +} diff --git a/test/IRGen/Inputs/comdat2.swift b/test/IRGen/Inputs/comdat2.swift new file mode 100644 index 0000000000000..96f5838138883 --- /dev/null +++ b/test/IRGen/Inputs/comdat2.swift @@ -0,0 +1,4 @@ +public func g() { + var a: [Int] = [] + a.append(1) +} diff --git a/test/IRGen/abitypes.swift b/test/IRGen/abitypes.swift index e62790d288d3c..00b804c660a23 100644 --- a/test/IRGen/abitypes.swift +++ b/test/IRGen/abitypes.swift @@ -580,7 +580,8 @@ public func testInlineAgg(_ rect: MyRect) -> Float { // arm64-ios: [[PTR0:%.*]] = getelementptr inbounds %TSo14FiveByteStructV, %TSo14FiveByteStructV* [[STRUCTPTR]], {{i.*}} 0, {{i.*}} 0 // arm64-ios: [[PTR1:%.*]] = getelementptr inbounds %T10ObjectiveC8ObjCBoolV, %T10ObjectiveC8ObjCBoolV* [[PTR0]], {{i.*}} 0, {{i.*}} 0 // arm64-ios: [[PTR2:%.*]] = getelementptr inbounds %TSb, %TSb* [[PTR1]], {{i.*}} 0, {{i.*}} 0 -// arm64-ios: store i1 false, i1* [[PTR2]], align 8 +// arm64-ios: [[BYTE_ADDR:%.*]] = bitcast i1* [[PTR2]] to i8* +// arm64-ios: store i8 0, i8* [[BYTE_ADDR]], align 8 // arm64-ios: [[ARG:%.*]] = load i64, i64* [[COERCED]] // arm64-ios: call void bitcast (void ()* @objc_msgSend to void (i8*, i8*, i64)*)(i8* {{.*}}, i8* {{.*}}, i64 [[ARG]]) // @@ -590,7 +591,8 @@ public func testInlineAgg(_ rect: MyRect) -> Float { // arm64e-ios: [[PTR0:%.*]] = getelementptr inbounds %TSo14FiveByteStructV, %TSo14FiveByteStructV* [[STRUCTPTR]], {{i.*}} 0, {{i.*}} 0 // arm64e-ios: [[PTR1:%.*]] = getelementptr inbounds %T10ObjectiveC8ObjCBoolV, %T10ObjectiveC8ObjCBoolV* [[PTR0]], {{i.*}} 0, {{i.*}} 0 // arm64e-ios: [[PTR2:%.*]] = getelementptr inbounds %TSb, %TSb* [[PTR1]], {{i.*}} 0, {{i.*}} 0 -// arm64e-ios: store i1 false, i1* [[PTR2]], align 8 +// arm64e-ios: [[BYTE_ADDR:%.*]] = bitcast i1* [[PTR2]] to i8* +// arm64e-ios: store i8 0, i8* [[BYTE_ADDR]], align 8 // arm64e-ios: [[ARG:%.*]] = load i64, i64* [[COERCED]] // arm64e-ios: call void bitcast (void ()* @objc_msgSend to void (i8*, i8*, i64)*)(i8* {{.*}}, i8* {{.*}}, i64 [[ARG]]) // arm64-macosx: define swiftcc void @"$s8abitypes14testBOOLStructyyF"() @@ -599,7 +601,8 @@ public func testInlineAgg(_ rect: MyRect) -> Float { // arm64-macosx: [[PTR0:%.*]] = getelementptr inbounds %TSo14FiveByteStructV, %TSo14FiveByteStructV* [[STRUCTPTR]], {{i.*}} 0, {{i.*}} 0 // arm64-macosx: [[PTR1:%.*]] = getelementptr inbounds %T10ObjectiveC8ObjCBoolV, %T10ObjectiveC8ObjCBoolV* [[PTR0]], {{i.*}} 0, {{i.*}} 0 // arm64-macosx: [[PTR2:%.*]] = getelementptr inbounds %TSb, %TSb* [[PTR1]], {{i.*}} 0, {{i.*}} 0 -// arm64-macosx: store i1 false, i1* [[PTR2]], align 8 +// arm64-macosx: [[BYTE_ADDR:%.*]] = bitcast i1* [[PTR2]] to i8* +// arm64-macosx: store i8 0, i8* [[BYTE_ADDR]], align 8 // arm64-macosx: [[ARG:%.*]] = load i64, i64* [[COERCED]] // arm64-macosx: call void bitcast (void ()* @objc_msgSend to void (i8*, i8*, i64)*)(i8* {{.*}}, i8* {{.*}}, i64 [[ARG]]) public func testBOOLStruct() { diff --git a/test/IRGen/big_types_corner_cases_tiny.swift b/test/IRGen/big_types_corner_cases_tiny.swift index 8a9a88b28f9b1..a4fb5a9a6929a 100644 --- a/test/IRGen/big_types_corner_cases_tiny.swift +++ b/test/IRGen/big_types_corner_cases_tiny.swift @@ -4,7 +4,7 @@ // DO NOT ADD ANY MORE CODE TO THIS FILE! -// CHECK-LABEL: define internal void @globalinit +// CHECK-LABEL: define internal void @{{.*}}WZ // CHECK: [[ALLOC:%.*]] = alloca %T27big_types_corner_cases_tiny30LoadableStructWithBiggerStringV // CHECK: call swiftcc void {{.*}}(%T27big_types_corner_cases_tiny30LoadableStructWithBiggerStringV* noalias nocapture sret [[ALLOC]] let model = ClassWithLoadableStructWithBiggerString().f() diff --git a/test/IRGen/builtins.swift b/test/IRGen/builtins.swift index d2dbff0b194c9..43adb03237981 100644 --- a/test/IRGen/builtins.swift +++ b/test/IRGen/builtins.swift @@ -235,21 +235,24 @@ func cmpxchg_test(_ ptr: Builtin.RawPointer, a: Builtin.Int32, b: Builtin.Int32) // CHECK: [[Z_VAL:%.*]] = extractvalue { i32, i1 } [[Z_RES]], 0 // CHECK: [[Z_SUCCESS:%.*]] = extractvalue { i32, i1 } [[Z_RES]], 1 // CHECK: store i32 [[Z_VAL]], i32* {{.*}}, align 4 - // CHECK: store i1 [[Z_SUCCESS]], i1* {{.*}}, align 1 + // CHECK: [[Z_SUCCESS_B:%.*]] = zext i1 [[Z_SUCCESS]] to i8 + // CHECK: store i8 [[Z_SUCCESS_B]], i8* {{.*}}, align 1 var (z, zSuccess) = Builtin.cmpxchg_acquire_acquire_Int32(ptr, a, b) // CHECK: [[Y_RES:%.*]] = cmpxchg volatile i32* {{.*}}, i32 {{.*}}, i32 {{.*}} monotonic monotonic // CHECK: [[Y_VAL:%.*]] = extractvalue { i32, i1 } [[Y_RES]], 0 // CHECK: [[Y_SUCCESS:%.*]] = extractvalue { i32, i1 } [[Y_RES]], 1 // CHECK: store i32 [[Y_VAL]], i32* {{.*}}, align 4 - // CHECK: store i1 [[Y_SUCCESS]], i1* {{.*}}, align 1 + // CHECK: [[Y_SUCCESS_B:%.*]] = zext i1 [[Y_SUCCESS]] to i8 + // CHECK: store i8 [[Y_SUCCESS_B]], i8* {{.*}}, align 1 var (y, ySuccess) = Builtin.cmpxchg_monotonic_monotonic_volatile_Int32(ptr, a, b) // CHECK: [[X_RES:%.*]] = cmpxchg volatile i32* {{.*}}, i32 {{.*}}, i32 {{.*}} syncscope("singlethread") acquire monotonic // CHECK: [[X_VAL:%.*]] = extractvalue { i32, i1 } [[X_RES]], 0 // CHECK: [[X_SUCCESS:%.*]] = extractvalue { i32, i1 } [[X_RES]], 1 // CHECK: store i32 [[X_VAL]], i32* {{.*}}, align 4 - // CHECK: store i1 [[X_SUCCESS]], i1* {{.*}}, align 1 + // CHECK: [[X_SUCCESS_B:%.*]] = zext i1 [[X_SUCCESS]] to i8 + // CHECK: store i8 [[X_SUCCESS_B]], i8* {{.*}}, align 1 var (x, xSuccess) = Builtin.cmpxchg_acquire_monotonic_volatile_singlethread_Int32(ptr, a, b) // CHECK: [[W_RES:%.*]] = cmpxchg volatile i64* {{.*}}, i64 {{.*}}, i64 {{.*}} seq_cst seq_cst @@ -257,7 +260,8 @@ func cmpxchg_test(_ ptr: Builtin.RawPointer, a: Builtin.Int32, b: Builtin.Int32) // CHECK: [[W_SUCCESS:%.*]] = extractvalue { i64, i1 } [[W_RES]], 1 // CHECK: [[W_VAL_PTR:%.*]] = inttoptr i64 [[W_VAL]] to i8* // CHECK: store i8* [[W_VAL_PTR]], i8** {{.*}}, align 8 - // CHECK: store i1 [[W_SUCCESS]], i1* {{.*}}, align 1 + // CHECK: [[W_SUCCESS_B:%.*]] = zext i1 [[W_SUCCESS]] to i8 + // CHECK: store i8 [[W_SUCCESS_B]], i8* {{.*}}, align 1 var (w, wSuccess) = Builtin.cmpxchg_seqcst_seqcst_volatile_singlethread_RawPointer(ptr, ptr, ptr) // CHECK: [[V_RES:%.*]] = cmpxchg weak volatile i64* {{.*}}, i64 {{.*}}, i64 {{.*}} seq_cst seq_cst @@ -265,7 +269,8 @@ func cmpxchg_test(_ ptr: Builtin.RawPointer, a: Builtin.Int32, b: Builtin.Int32) // CHECK: [[V_SUCCESS:%.*]] = extractvalue { i64, i1 } [[V_RES]], 1 // CHECK: [[V_VAL_PTR:%.*]] = inttoptr i64 [[V_VAL]] to i8* // CHECK: store i8* [[V_VAL_PTR]], i8** {{.*}}, align 8 - // CHECK: store i1 [[V_SUCCESS]], i1* {{.*}}, align 1 + // CHECK: [[V_SUCCESS_B:%.*]] = zext i1 [[V_SUCCESS]] to i8 + // CHECK: store i8 [[V_SUCCESS_B]], i8* {{.*}}, align 1 var (v, vSuccess) = Builtin.cmpxchg_seqcst_seqcst_weak_volatile_singlethread_RawPointer(ptr, ptr, ptr) } @@ -558,7 +563,8 @@ struct Pair { var i: Int, b: Bool } // CHECK: [[FLDI:%.*]] = getelementptr inbounds {{.*}} [[PAIR]], i32 0, i32 0 // CHECK: store i32 0, i32* [[FLDI]] // CHECK: [[FLDB:%.*]] = getelementptr inbounds {{.*}} [[PAIR]], i32 0, i32 1 -// CHECK: store i1 false, i1* [[FLDB]] +// CHECK: [[BYTE_ADDR:%.*]] = bitcast i1* [[FLDB]] to i8* +// CHECK: store i8 0, i8* [[BYTE_ADDR]] // CHECK: [[RET:%.*]] = getelementptr inbounds {{.*}} [[ALLOCA]], i32 0, i32 0 // CHECK: [[RES:%.*]] = load i64, i64* [[RET]] // CHECK: ret i64 [[RES]] @@ -575,7 +581,8 @@ func zeroInitializer() -> (Empty, Pair) { // CHECK: [[FLDI:%.*]] = getelementptr inbounds {{.*}} [[PAIR]], i32 0, i32 0 // CHECK: store i32 0, i32* [[FLDI]] // CHECK: [[FLDB:%.*]] = getelementptr inbounds {{.*}} [[PAIR]], i32 0, i32 1 -// CHECK: store i1 false, i1* [[FLDB]] +// CHECK: [[BYTE_ADDR:%.*]] = bitcast i1* [[FLDB]] to i8* +// CHECK: store i8 0, i8* [[BYTE_ADDR]] // CHECK: [[RET:%.*]] = getelementptr inbounds {{.*}} [[ALLOCA]], i32 0, i32 0 // CHECK: [[RES:%.*]] = load i64, i64* [[RET]] // CHECK: ret i64 [[RES]] @@ -695,14 +702,16 @@ func generic_ispod_test(_: T) { // CHECK-NEXT: [[FLAGS:%.*]] = load i32, i32* [[T0]] // CHECK-NEXT: [[ISNOTPOD:%.*]] = and i32 [[FLAGS]], 65536 // CHECK-NEXT: [[ISPOD:%.*]] = icmp eq i32 [[ISNOTPOD]], 0 - // CHECK-NEXT: store i1 [[ISPOD]], i1* [[S:%.*]] + // CHECK-NEXT: [[BYTE_ADDR:%.*]] = bitcast i1* [[S:%.*]] to i8* + // CHECK-NEXT: [[BYTE:%.*]] = zext i1 [[ISPOD]] to i8 + // CHECK-NEXT: store i8 [[BYTE]], i8* [[BYTE_ADDR]] var s = Builtin.ispod(T.self) } // CHECK-LABEL: define {{.*}} @{{.*}}ispod_test func ispod_test() { - // CHECK: store i1 true, i1* - // CHECK: store i1 false, i1* + // CHECK: store i8 1, i8* + // CHECK: store i8 0, i8* var t = Builtin.ispod(Int.self) var f = Builtin.ispod(Builtin.NativeObject.self) } @@ -713,17 +722,19 @@ func generic_isbitwisetakable_test(_: T) { // CHECK-NEXT: [[FLAGS:%.*]] = load i32, i32* [[T0]] // CHECK-NEXT: [[ISNOTBITWISETAKABLE:%.*]] = and i32 [[FLAGS]], 1048576 // CHECK-NEXT: [[ISBITWISETAKABLE:%.*]] = icmp eq i32 [[ISNOTBITWISETAKABLE]], 0 - // CHECK-NEXT: store i1 [[ISBITWISETAKABLE]], i1* [[S:%.*]] + // CHECK-NEXT: [[BYTE_ADDR:%.*]] = bitcast i1* [[S:%.*]] + // CHECK-NEXT: [[BYTE:%.*]] = zext i1 [[ISBITWISETAKABLE]] to i8 + // CHECK-NEXT: store i8 [[BYTE]], i8* [[BYTE_ADDR]] var s = Builtin.isbitwisetakable(T.self) } // CHECK-LABEL: define {{.*}} @{{.*}}isbitwisetakable_test func isbitwisetakable_test() { - // CHECK: store i1 true, i1* - // CHECK: store i1 true, i1* - // CHECK: store i1 true, i1* - // CHECK: store i1 true, i1* - // CHECK: store i1 false, i1* + // CHECK: store i8 1, i8* + // CHECK: store i8 1, i8* + // CHECK: store i8 1, i8* + // CHECK: store i8 1, i8* + // CHECK: store i8 0, i8* var t1 = Builtin.isbitwisetakable(Int.self) var t2 = Builtin.isbitwisetakable(C.self) var t3 = Builtin.isbitwisetakable(Abc.self) diff --git a/test/IRGen/comdat.swift b/test/IRGen/comdat.swift new file mode 100644 index 0000000000000..e85eb939af45b --- /dev/null +++ b/test/IRGen/comdat.swift @@ -0,0 +1,14 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-ir %S/Inputs/comdat1.swift %S/Inputs/comdat2.swift -O -num-threads 1 -module-name comdat -o %t/comdat1.ll -o %t/comdat2.ll +// RUN: %FileCheck -check-prefix CHECK-1 %s < %t/comdat1.ll +// RUN: %FileCheck -check-prefix CHECK-2 %s < %t/comdat2.ll + +// REQUIRES: OS=windows-msvc + +// Ensure that the definition is marked as COMDAT +// CHECK-1: "$s6comdat1C33_{{.*}}LLCMa" = comdat any +// CHECK-1: "$s6comdat1C33_{{.*}}LLCMn" = comdat any + +// Ensure that no foward declaration is emitted +// CHECK-2-NOT: "$s6comdat1C33_{{.*}}LLCMa" = comdat any +// CHECK-2-NOT: "$s6comdat1C33_{{.*}}LLCMn" = comdat any diff --git a/test/IRGen/enum.sil b/test/IRGen/enum.sil index b08f0e6587bfd..f17d1036ab376 100644 --- a/test/IRGen/enum.sil +++ b/test/IRGen/enum.sil @@ -1010,7 +1010,9 @@ entry(%0 : $Builtin.Int63): // CHECK-64: entry: // CHECK-64: [[T:%.*]] = trunc i64 %0 to i63 // CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum21SinglePayloadSpareBitO* %1 to i63* -// CHECK-64: store i63 [[T]], i63* [[DATA_ADDR]] +// CHECK-64: [[BYTE_ADDR:%.*]] = bitcast i63* [[DATA_ADDR]] to i64* +// CHECK-64: [[BYTE:%.*]] = zext i63 [[T]] to i64 +// CHECK-64: store i64 [[BYTE]], i64* [[BYTE_ADDR]] // CHECK-64: ret void // CHECK-64: } sil @single_payload_spare_bit_inject_x_indirect : $(Builtin.Int63, @inout SinglePayloadSpareBit) -> () { @@ -1784,7 +1786,9 @@ entry(%0 : $Builtin.Int62): // CHECK-64: entry: // CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i62 // CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i62* -// CHECK-64: store i62 [[NATIVECC_TRUNC]], i62* [[DATA_ADDR]] +// CHECK-64: [[BYTE_ADDR:%.*]] = bitcast i62* [[DATA_ADDR]] to i64* +// CHECK-64: [[BYTE:%.*]] = zext i62 [[NATIVECC_TRUNC]] to i64 +// CHECK-64: store i64 [[BYTE]], i64* [[BYTE_ADDR]] // CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i64* // CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]] // -- 0x7FFF_FFFF_FFFF_FFFF @@ -1825,7 +1829,9 @@ entry(%0 : $Builtin.Int63): // CHECK-64: entry: // CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i63 // CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i63* -// CHECK-64: store i63 [[NATIVECC_TRUNC]], i63* [[DATA_ADDR]] +// CHECK-64: [[BYTE_ADDR:%.*]] = bitcast i63* [[DATA_ADDR]] to i64* +// CHECK-64: [[BYTE:%.*]] = zext i63 [[NATIVECC_TRUNC]] to i64 +// CHECK-64: store i64 [[BYTE]], i64* [[BYTE_ADDR]] // CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i64* // CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]] // -- 0x7FFF_FFFF_FFFF_FFFF @@ -2024,7 +2030,9 @@ entry(%0 : $Builtin.Int62): // CHECK-64: entry: // CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i62 // CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i62* -// CHECK-64: store i62 [[NATIVECC_TRUNC]], i62* [[DATA_ADDR]] +// CHECK-64: [[BYTE_ADDR:%.*]] = bitcast i62* [[DATA_ADDR]] to i64* +// CHECK-64: [[BYTE:%.*]] = zext i62 [[NATIVECC_TRUNC]] to i64 +// CHECK-64: store i64 [[BYTE]], i64* [[BYTE_ADDR]] // CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i64* // CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]] // -- 0x3FFF_FFFF_FFFF_FFFF @@ -2060,7 +2068,9 @@ entry(%0 : $Builtin.Int60): // CHECK-64: entry: // CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i60 // CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i60* -// CHECK-64: store i60 [[NATIVECC_TRUNC]], i60* [[DATA_ADDR]] +// CHECK-64: [[BYTE_ADDR:%.*]] = bitcast i60* [[DATA_ADDR]] to i64* +// CHECK-64: [[BYTE:%.*]] = zext i60 [[NATIVECC_TRUNC]] to i64 +// CHECK-64: store i64 [[BYTE]], i64* [[BYTE_ADDR]] // CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i64* // CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]] // -- 0x3FFF_FFFF_FFFF_FFFF diff --git a/test/IRGen/enum_future.sil b/test/IRGen/enum_future.sil index b538b63093269..48cc72ee09922 100644 --- a/test/IRGen/enum_future.sil +++ b/test/IRGen/enum_future.sil @@ -1014,7 +1014,9 @@ entry(%0 : $Builtin.Int63): // CHECK-64: entry: // CHECK-64: [[T:%.*]] = trunc i64 %0 to i63 // CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T11enum_future21SinglePayloadSpareBitO* %1 to i63* -// CHECK-64: store i63 [[T]], i63* [[DATA_ADDR]] +// CHECK-64: [[BYTE_ADDR:%.*]] = bitcast i63* [[DATA_ADDR]] to i64* +// CHECK-64: [[BYTE:%.*]] = zext i63 [[T]] to i64 +// CHECK-64: store i64 [[BYTE]], i64* [[BYTE_ADDR]] // CHECK-64: ret void // CHECK-64: } sil @single_payload_spare_bit_inject_x_indirect : $(Builtin.Int63, @inout SinglePayloadSpareBit) -> () { @@ -1788,7 +1790,9 @@ entry(%0 : $Builtin.Int62): // CHECK-64: entry: // CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i62 // CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T11enum_future23MultiPayloadOneSpareBitO* %1 to i62* -// CHECK-64: store i62 [[NATIVECC_TRUNC]], i62* [[DATA_ADDR]] +// CHECK-64: [[BYTE_ADDR:%.*]] = bitcast i62* [[DATA_ADDR]] to i64* +// CHECK-64: [[VAL:%.*]] = zext i62 [[NATIVECC_TRUNC]] to i64 +// CHECK-64: store i64 [[VAL]], i64* [[BYTE_ADDR]] // CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T11enum_future23MultiPayloadOneSpareBitO* %1 to i64* // CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]] // -- 0x7FFF_FFFF_FFFF_FFFF @@ -1829,7 +1833,9 @@ entry(%0 : $Builtin.Int63): // CHECK-64: entry: // CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i63 // CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T11enum_future23MultiPayloadOneSpareBitO* %1 to i63* -// CHECK-64: store i63 [[NATIVECC_TRUNC]], i63* [[DATA_ADDR]] +// CHECK-64: [[BYTE_ADDR:%.*]] = bitcast i63* [[DATA_ADDR]] to i64* +// CHECK-64: [[VAL:%.*]] = zext i63 [[NATIVECC_TRUNC]] to i64 +// CHECK-64: store i64 [[VAL]], i64* [[BYTE_ADDR]] // CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T11enum_future23MultiPayloadOneSpareBitO* %1 to i64* // CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]] // -- 0x7FFF_FFFF_FFFF_FFFF @@ -2028,7 +2034,9 @@ entry(%0 : $Builtin.Int62): // CHECK-64: entry: // CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i62 // CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T11enum_future24MultiPayloadTwoSpareBitsO* %1 to i62* -// CHECK-64: store i62 [[NATIVECC_TRUNC]], i62* [[DATA_ADDR]] +// CHECK-64: [[BYTE_ADDR:%.*]] = bitcast i62* [[DATA_ADDR]] to i64* +// CHECK-64: [[VAL:%.*]] = zext i62 [[NATIVECC_TRUNC]] to i64 +// CHECK-64: store i64 [[VAL]], i64* [[BYTE_ADDR]] // CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T11enum_future24MultiPayloadTwoSpareBitsO* %1 to i64* // CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]] // -- 0x3FFF_FFFF_FFFF_FFFF @@ -2064,7 +2072,9 @@ entry(%0 : $Builtin.Int60): // CHECK-64: entry: // CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i60 // CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T11enum_future24MultiPayloadTwoSpareBitsO* %1 to i60* -// CHECK-64: store i60 [[NATIVECC_TRUNC]], i60* [[DATA_ADDR]] +// CHECK-64: [[BYTE_ADDR:%.*]] = bitcast i60* [[DATA_ADDR]] to i64* +// CHECK-64: [[VAL:%.*]] = zext i60 [[NATIVECC_TRUNC]] to i64 +// CHECK-64: store i64 [[VAL]], i64* [[BYTE_ADDR]] // CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T11enum_future24MultiPayloadTwoSpareBitsO* %1 to i64* // CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]] // -- 0x3FFF_FFFF_FFFF_FFFF diff --git a/test/IRGen/generic_metatypes_future.swift b/test/IRGen/generic_metatypes_future.swift index bf18d17617de0..685eaed727377 100644 --- a/test/IRGen/generic_metatypes_future.swift +++ b/test/IRGen/generic_metatypes_future.swift @@ -1,5 +1,5 @@ -// RUN: %swift -prespecialize-generic-metadata -module-name generic_metatypes -target x86_64-apple-macosx50.99 -emit-ir -disable-legacy-type-info -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-64 -DINT=i64 %s +// RUN: %swift -prespecialize-generic-metadata -module-name generic_metatypes -target x86_64-apple-macosx99.99 -emit-ir -disable-legacy-type-info -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-64 -DINT=i64 %s // RUN: %swift -prespecialize-generic-metadata -module-name generic_metatypes -target x86_64-apple-ios99.0 -emit-ir -disable-legacy-type-info -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-64 -DINT=i64 %s // RUN: %swift -prespecialize-generic-metadata -module-name generic_metatypes -target x86_64-apple-tvos99.0 -emit-ir -disable-legacy-type-info -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-64 -DINT=i64 %s // RUN: %swift -prespecialize-generic-metadata -module-name generic_metatypes -target i386-apple-watchos9.99 -emit-ir -disable-legacy-type-info -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-32 -DINT=i32 %s diff --git a/test/IRGen/globals.swift b/test/IRGen/globals.swift index 509922e9483ed..b423befb38b6d 100644 --- a/test/IRGen/globals.swift +++ b/test/IRGen/globals.swift @@ -53,6 +53,5 @@ extension A { // CHECK: define{{( dllexport)?}}{{( protected)?}} i32 @main(i32 %0, i8** %1) {{.*}} { // CHECK: store i64 {{.*}}, i64* getelementptr inbounds ([[INT]], [[INT]]* @"$s7globals2g0Sivp", i32 0, i32 0), align 8 -// FIXME: give these initializers a real mangled name -// CHECK: define internal void @globalinit_{{.*}}func0() {{.*}} { +// CHECK: define internal void @"{{.*}}WZ"() {{.*}} { // CHECK: store i64 5, i64* getelementptr inbounds (%TSi, %TSi* @"$s7globals1AV3fooSivpZ", i32 0, i32 0), align 8 diff --git a/test/IRGen/lazy_globals.swift b/test/IRGen/lazy_globals.swift index ce0f387d9e485..8b1d761c70e40 100644 --- a/test/IRGen/lazy_globals.swift +++ b/test/IRGen/lazy_globals.swift @@ -2,12 +2,12 @@ // REQUIRES: CPU=x86_64 -// CHECK: @globalinit_[[T:.*]]_token0 = internal global i64 0, align 8 +// CHECK: @"[[T:.*]]Wz" = internal global i64 0, align 8 // CHECK: @"$s12lazy_globals1xSivp" = hidden global %TSi zeroinitializer, align 8 // CHECK: @"$s12lazy_globals1ySivp" = hidden global %TSi zeroinitializer, align 8 // CHECK: @"$s12lazy_globals1zSivp" = hidden global %TSi zeroinitializer, align 8 -// CHECK: define internal void @globalinit_[[T]]_func0() {{.*}} { +// CHECK: define internal void @"[[T]]WZ"() {{.*}} { // CHECK: entry: // CHECK: store i64 1, i64* getelementptr inbounds (%TSi, %TSi* @"$s12lazy_globals1xSivp", i32 0, i32 0), align 8 // CHECK: store i64 2, i64* getelementptr inbounds (%TSi, %TSi* @"$s12lazy_globals1ySivp", i32 0, i32 0), align 8 @@ -17,17 +17,17 @@ // CHECK: define hidden swiftcc i8* @"$s12lazy_globals1xSivau"() {{.*}} { // CHECK: entry: -// CHECK: call void @swift_once(i64* @globalinit_[[T]]_token0, i8* bitcast (void ()* @globalinit_[[T]]_func0 to i8*), i8* undef) +// CHECK: call void @swift_once(i64* @"[[T]]Wz", i8* bitcast (void ()* @"[[T]]WZ" to i8*), i8* undef) // CHECK: } // CHECK: define hidden swiftcc i8* @"$s12lazy_globals1ySivau"() {{.*}} { // CHECK: entry: -// CHECK: call void @swift_once(i64* @globalinit_[[T]]_token0, i8* bitcast (void ()* @globalinit_[[T]]_func0 to i8*), i8* undef) +// CHECK: call void @swift_once(i64* @"[[T]]Wz", i8* bitcast (void ()* @"[[T]]WZ" to i8*), i8* undef) // CHECK: } // CHECK: define hidden swiftcc i8* @"$s12lazy_globals1zSivau"() {{.*}} { // CHECK: entry: -// CHECK: call void @swift_once(i64* @globalinit_[[T]]_token0, i8* bitcast (void ()* @globalinit_[[T]]_func0 to i8*), i8* undef) +// CHECK: call void @swift_once(i64* @"[[T]]Wz", i8* bitcast (void ()* @"[[T]]WZ" to i8*), i8* undef) // CHECK: } var (x, y, z) = (1, 2, 3) diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-2argument-1_distinct_use-1st_argument_generic_class-2nd_argument_distinct_generic_class.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-2argument-1_distinct_use-1st_argument_generic_class-2nd_argument_distinct_generic_class.swift index 4343391e57e12..8e087b91ceed0 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-2argument-1_distinct_use-1st_argument_generic_class-2nd_argument_distinct_generic_class.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-2argument-1_distinct_use-1st_argument_generic_class-2nd_argument_distinct_generic_class.swift @@ -238,90 +238,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_ARGUMENT1:%[0-9]+]] = bitcast %swift.type* [[ARGUMENT1_METADATA]] to i8* // CHECK: [[ERASED_ARGUMENT2:%[0-9]+]] = bitcast %swift.type* [[ARGUMENT2_METADATA]] to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE_1:%[0-9]+]] = icmp eq i8* bitcast ( -// : %swift.type* getelementptr inbounds ( -// : %swift.full_heapmetadata, -// : %swift.full_heapmetadata* bitcast ( -// : <{ -// : void ( -// : %T4main9Argument1[[UNIQUE_ID_1]]LLC* -// : )*, -// : i8**, -// : [[INT]], -// : %objc_class*, -// : %swift.opaque*, -// : %swift.opaque*, -// : [[INT]], -// : i32, -// : i32, -// : i32, -// : i16, -// : i16, -// : i32, -// : i32, -// : %swift.type_descriptor*, -// : i8*, -// : %swift.type*, -// : [[INT]], -// : %T4main9Argument1[[UNIQUE_ID_1]]LLC* ( -// : %swift.opaque*, -// : %swift.type* -// : )* -// : }>* -// CHECK-SAME: @"$s4main9Argument1[[UNIQUE_ID_1]]LLCySiGMf" -// : to %swift.full_heapmetadata* -// : ), -// : i32 0, -// : i32 2 -// : ) to i8* -// CHECK-SAME: ), [[ERASED_ARGUMENT1]] -// CHECK: [[EQUAL_TYPES_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1]] -// CHECK: [[EQUAL_TYPE_2:%[0-9]+]] = icmp eq i8* bitcast ( -// : %swift.type* getelementptr inbounds ( -// : %swift.full_heapmetadata, -// : %swift.full_heapmetadata* bitcast ( -// : <{ -// : void ( -// : %T4main9Argument2[[UNIQUE_ID_1]]LLC* -// : )*, -// : i8**, -// : [[INT]], -// : %objc_class*, -// : %swift.opaque*, -// : %swift.opaque*, -// : [[INT]], -// : i32, -// : i32, -// : i32, -// : i16, -// : i16, -// : i32, -// : i32, -// : %swift.type_descriptor*, -// : i8*, -// : %swift.type*, -// : [[INT]], -// : %T4main9Argument2[[UNIQUE_ID_1]]LLC* ( -// : %swift.opaque*, -// : %swift.type* -// : )* -// CHECK-SAME: }>* @"$s4main9Argument2[[UNIQUE_ID_1]]LLCySSGMf" to %swift.full_heapmetadata* -// : ), -// : i32 0, -// : i32 2 -// : ) to i8* -// : ), [[ERASED_ARGUMENT2]] -// CHECK: [[EQUAL_TYPES_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1]], [[EQUAL_TYPE_2]] -// CHECK: br i1 [[EQUAL_TYPES_2]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_3:[0-9A-Z_]+]]LLCyAA9Argument1ACLLCySiGAA9Argument2ACLLCySSGGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK: [[INT]] [[METADATA_REQUEST]], // CHECK: i8* [[ERASED_ARGUMENT1]], diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-2argument-1_distinct_use-1st_argument_generic_class-2nd_argument_same_generic_class_different_value.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-2argument-1_distinct_use-1st_argument_generic_class-2nd_argument_same_generic_class_different_value.swift index 782a1c22d4cc7..bc1dd0c10b5fc 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-2argument-1_distinct_use-1st_argument_generic_class-2nd_argument_same_generic_class_different_value.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-2argument-1_distinct_use-1st_argument_generic_class-2nd_argument_same_generic_class_different_value.swift @@ -228,90 +228,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_ARGUMENT1:%[0-9]+]] = bitcast %swift.type* [[ARGUMENT1_METADATA]] to i8* // CHECK: [[ERASED_ARGUMENT2:%[0-9]+]] = bitcast %swift.type* [[ARGUMENT2_METADATA]] to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE_1:%[0-9]+]] = icmp eq i8* bitcast ( -// : %swift.type* getelementptr inbounds ( -// : %swift.full_heapmetadata, -// : %swift.full_heapmetadata* bitcast ( -// : <{ -// : void ( -// : %T4main9Argument1[[UNIQUE_ID_1]]LLC* -// : )*, -// : i8**, -// : [[INT]], -// : %objc_class*, -// : %swift.opaque*, -// : %swift.opaque*, -// : [[INT]], -// : i32, -// : i32, -// : i32, -// : i16, -// : i16, -// : i32, -// : i32, -// : %swift.type_descriptor*, -// : i8*, -// : %swift.type*, -// : [[INT]], -// : %T4main9Argument1[[UNIQUE_ID_1]]LLC* ( -// : %swift.opaque*, -// : %swift.type* -// : )* -// : }>* -// CHECK-SAME: @"$s4main9Argument1[[UNIQUE_ID_1]]LLCySiGMf" -// : to %swift.full_heapmetadata* -// : ), -// : i32 0, -// : i32 2 -// : ) to i8* -// CHECK-SAME: ), [[ERASED_ARGUMENT1]] -// CHECK: [[EQUAL_TYPES_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1]] -// CHECK: [[EQUAL_TYPE_2:%[0-9]+]] = icmp eq i8* bitcast ( -// : %swift.type* getelementptr inbounds ( -// : %swift.full_heapmetadata, -// : %swift.full_heapmetadata* bitcast ( -// : <{ -// : void ( -// : %T4main9Argument1[[UNIQUE_ID_1]]LLC* -// : )*, -// : i8**, -// : [[INT]], -// : %objc_class*, -// : %swift.opaque*, -// : %swift.opaque*, -// : [[INT]], -// : i32, -// : i32, -// : i32, -// : i16, -// : i16, -// : i32, -// : i32, -// : %swift.type_descriptor*, -// : i8*, -// : %swift.type*, -// : [[INT]], -// : %T4main9Argument1[[UNIQUE_ID_1]]LLC* ( -// : %swift.opaque*, -// : %swift.type* -// : )* -// CHECK-SAME: }>* @"$s4main9Argument1[[UNIQUE_ID_1]]LLCySSGMf" to %swift.full_heapmetadata* -// : ), -// : i32 0, -// : i32 2 -// : ) to i8* -// : ), [[ERASED_ARGUMENT2]] -// CHECK: [[EQUAL_TYPES_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1]], [[EQUAL_TYPE_2]] -// CHECK: br i1 [[EQUAL_TYPES_2]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_3:[0-9A-Z_]+]]LLCyAA9Argument1ACLLCySiGAFySSGGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK: [[INT]] [[METADATA_REQUEST]], // CHECK: i8* [[ERASED_ARGUMENT1]], diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-2argument-1_distinct_use-1st_argument_generic_class-2nd_argument_same_generic_class_same_value.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-2argument-1_distinct_use-1st_argument_generic_class-2nd_argument_same_generic_class_same_value.swift index 063e19e254d90..d0122ee20739d 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-2argument-1_distinct_use-1st_argument_generic_class-2nd_argument_same_generic_class_same_value.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-2argument-1_distinct_use-1st_argument_generic_class-2nd_argument_same_generic_class_same_value.swift @@ -228,90 +228,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_ARGUMENT1:%[0-9]+]] = bitcast %swift.type* [[ARGUMENT1_METADATA]] to i8* // CHECK: [[ERASED_ARGUMENT2:%[0-9]+]] = bitcast %swift.type* [[ARGUMENT2_METADATA]] to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE_1:%[0-9]+]] = icmp eq i8* bitcast ( -// : %swift.type* getelementptr inbounds ( -// : %swift.full_heapmetadata, -// : %swift.full_heapmetadata* bitcast ( -// : <{ -// : void ( -// : %T4main9Argument1[[UNIQUE_ID_1]]LLC* -// : )*, -// : i8**, -// : [[INT]], -// : %objc_class*, -// : %swift.opaque*, -// : %swift.opaque*, -// : [[INT]], -// : i32, -// : i32, -// : i32, -// : i16, -// : i16, -// : i32, -// : i32, -// : %swift.type_descriptor*, -// : i8*, -// : %swift.type*, -// : [[INT]], -// : %T4main9Argument1[[UNIQUE_ID_1]]LLC* ( -// : %swift.opaque*, -// : %swift.type* -// : )* -// : }>* -// CHECK-SAME: @"$s4main9Argument1[[UNIQUE_ID_1]]LLCySiGMf" -// : to %swift.full_heapmetadata* -// : ), -// : i32 0, -// : i32 2 -// : ) to i8* -// CHECK-SAME: ), [[ERASED_ARGUMENT1]] -// CHECK: [[EQUAL_TYPES_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1]] -// CHECK: [[EQUAL_TYPE_2:%[0-9]+]] = icmp eq i8* bitcast ( -// : %swift.type* getelementptr inbounds ( -// : %swift.full_heapmetadata, -// : %swift.full_heapmetadata* bitcast ( -// : <{ -// : void ( -// : %T4main9Argument1[[UNIQUE_ID_1]]LLC* -// : )*, -// : i8**, -// : [[INT]], -// : %objc_class*, -// : %swift.opaque*, -// : %swift.opaque*, -// : [[INT]], -// : i32, -// : i32, -// : i32, -// : i16, -// : i16, -// : i32, -// : i32, -// : %swift.type_descriptor*, -// : i8*, -// : %swift.type*, -// : [[INT]], -// : %T4main9Argument1[[UNIQUE_ID_1]]LLC* ( -// : %swift.opaque*, -// : %swift.type* -// : )* -// CHECK-SAME: }>* @"$s4main9Argument1[[UNIQUE_ID_1]]LLCySiGMf" to %swift.full_heapmetadata* -// : ), -// : i32 0, -// : i32 2 -// : ) to i8* -// : ), [[ERASED_ARGUMENT2]] -// CHECK: [[EQUAL_TYPES_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1]], [[EQUAL_TYPE_2]] -// CHECK: br i1 [[EQUAL_TYPES_2]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_3:[0-9A-Z_]+]]LLCyAA9Argument1ACLLCySiGAGGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK: [[INT]] [[METADATA_REQUEST]], // CHECK: i8* [[ERASED_ARGUMENT1]], diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_con_double.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_con_double.swift index 04e01f00adbc6..a6e82b06a8531 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_con_double.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_con_double.swift @@ -239,20 +239,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main9Ancestor2[[UNIQUE_ID_1]]CMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: @"$sSdN" -// CHECK-SAME: ), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main9Ancestor2[[UNIQUE_ID_3:[0-9A-Z_]+]]CySdGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] [[METADATA_REQUEST]], // CHECK-SAME: i8* [[ERASED_TYPE]], @@ -270,20 +256,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main9Ancestor1[[UNIQUE_ID_1]]CMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: @"$sSiN" -// CHECK-SAME: ), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main9Ancestor1[[UNIQUE_ID_3:[0-9A-Z_]+]]CySiGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] [[METADATA_REQUEST]], // CHECK-SAME: i8* [[ERASED_TYPE]], @@ -301,20 +273,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]CMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: @"$sSSN" -// CHECK-SAME: ), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_3:[0-9A-Z_]+]]CySSGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] [[METADATA_REQUEST]], // CHECK-SAME: i8* [[ERASED_TYPE]], diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_subclass_arg.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_subclass_arg.swift index 1441ee49f2a05..d31da831d35b7 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_subclass_arg.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_subclass_arg.swift @@ -224,20 +224,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main9Ancestor2[[UNIQUE_ID_1]]CMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: @"$sSiN" -// CHECK-SAME: ), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main9Ancestor2[[UNIQUE_ID_3:[0-9A-Z_]+]]CySiGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] [[METADATA_REQUEST]], // CHECK-SAME: i8* [[ERASED_TYPE]], @@ -255,20 +241,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main9Ancestor1[[UNIQUE_ID_1]]CMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: @"$sSiN" -// CHECK-SAME: ), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main9Ancestor1[[UNIQUE_ID_3:[0-9A-Z_]+]]CySiGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] [[METADATA_REQUEST]], // CHECK-SAME: i8* [[ERASED_TYPE]], @@ -286,20 +258,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]CMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: @"$sSSN" -// CHECK-SAME: ), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_3:[0-9A-Z_]+]]CySSGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] [[METADATA_REQUEST]], // CHECK-SAME: i8* [[ERASED_TYPE]], diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_subclass_arg-2nd_anc_gen-1st-arg_con_int.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_subclass_arg-2nd_anc_gen-1st-arg_con_int.swift index 9cca1c2489be4..571080fd0c496 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_subclass_arg-2nd_anc_gen-1st-arg_con_int.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_subclass_arg-2nd_anc_gen-1st-arg_con_int.swift @@ -228,20 +228,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main9Ancestor2[[UNIQUE_ID_1]]LLCMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: @"$sSiN" -// CHECK-SAME: ), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main9Ancestor2[[UNIQUE_ID_3:[0-9A-Z_]+]]LLCySiGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] [[METADATA_REQUEST]], // CHECK-SAME: i8* [[ERASED_TYPE]], @@ -259,20 +245,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main9Ancestor1[[UNIQUE_ID_1]]LLCMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: @"$sSSN" -// CHECK-SAME: ), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main9Ancestor1[[UNIQUE_ID_3:[0-9A-Z_]+]]LLCySSGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] [[METADATA_REQUEST]], // CHECK-SAME: i8* [[ERASED_TYPE]], @@ -290,20 +262,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]LLCMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: @"$sSSN" -// CHECK-SAME: ), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_3:[0-9A-Z_]+]]LLCySSGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] [[METADATA_REQUEST]], // CHECK-SAME: i8* [[ERASED_TYPE]], diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_subcls_arg-2nd_anc_gen-1st-arg_subcls_arg.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_subcls_arg-2nd_anc_gen-1st-arg_subcls_arg.swift index 1558d95bea74a..0cf8847101f25 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_subcls_arg-2nd_anc_gen-1st-arg_subcls_arg.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_subcls_arg-2nd_anc_gen-1st-arg_subcls_arg.swift @@ -216,20 +216,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main9Ancestor2[[UNIQUE_ID_1]]LLCMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* [[ARGUMENT:%[0-9]+]]) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* [[ARGUMENT]] to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: @"$sSiN" -// CHECK-SAME: ), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main9Ancestor2[[UNIQUE_ID_3:[0-9A-Z_]+]]LLCySiGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] [[METADATA_REQUEST]], // CHECK-SAME: i8* [[ERASED_TYPE]], @@ -247,20 +233,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main9Ancestor1[[UNIQUE_ID_1]]LLCMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* [[ARGUMENT:%[0-9]+]]) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* [[ARGUMENT]] to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: @"$sSiN" -// CHECK-SAME: ), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main9Ancestor1[[UNIQUE_ID_3:[0-9A-Z_]+]]LLCySiGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] [[METADATA_REQUEST]], // CHECK-SAME: i8* [[ERASED_TYPE]], @@ -278,20 +250,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]LLCMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* [[ARGUMENT:%[0-9]+]]) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* [[ARGUMENT]] to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: @"$sSiN" -// CHECK-SAME: ), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_3:[0-9A-Z_]+]]LLCySiGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] [[METADATA_REQUEST]], // CHECK-SAME: i8* [[ERASED_TYPE]], diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use-1st_argument_generic_class-1argument.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use-1st_argument_generic_class-1argument.swift index 1648484f0de4c..8bf4826b10b70 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use-1st_argument_generic_class-1argument.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use-1st_argument_generic_class-1argument.swift @@ -256,20 +256,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]CMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: @"$s4main9Argument1[[UNIQUE_ID_1]]CySiGMf" -// CHECK-SAME: ), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_3:[0-9A-Z_]+]]CyAA9Argument1ACLLCySiGGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK: [[INT]] [[METADATA_REQUEST]], // CHECK: i8* [[ERASED_TYPE]], diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use.swift index d1b52bed77166..8ba996f2c6243 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use.swift @@ -101,18 +101,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]CMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_3:[0-9A-Z_]+]]CySiGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK: [[INT]] [[METADATA_REQUEST]], // CHECK: i8* [[ERASED_TYPE]], diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_class.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_class.swift index 2cf41486a5b49..b792ac6dfb932 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_class.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_class.swift @@ -193,55 +193,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]LLCMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// : %swift.type* getelementptr inbounds ( -// : %swift.full_heapmetadata, -// : %swift.full_heapmetadata* bitcast ( -// : <{ -// : void ( -// : %T4main3Box[[UNIQUE_ID_2]]LLC* -// : )*, -// : i8**, -// : [[INT]], -// : %objc_class*, -// : %swift.opaque*, -// : %swift.opaque*, -// : [[INT]], -// : i32, -// : i32, -// : i32, -// : i16, -// : i16, -// : i32, -// : i32, -// : %swift.type_descriptor*, -// : i8*, -// : %swift.type*, -// : [[INT]], -// : %T4main3Box[[UNIQUE_ID_2]]LLC* ( -// : %swift.opaque*, -// : %swift.type* -// : )* -// : }>* -// CHECK-SAME: @"$s4main3Box[[UNIQUE_ID_1]]LLCySiGMf" -// : to %swift.full_heapmetadata* -// : ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 2 -// CHECK-SAME: ) to i8* -// CHECK-SAME: ), -// CHECK-SAME: [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_3:[0-9A-Z_]+]]LLCyAA3BoxACLLCySiGGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK: [[INT]] [[METADATA_REQUEST]], // CHECK: i8* [[ERASED_TYPE]], diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_class_specialized_at_generic_class.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_class_specialized_at_generic_class.swift index 8579ac2e32306..0bdef4eb2cf22 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_class_specialized_at_generic_class.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_class_specialized_at_generic_class.swift @@ -200,55 +200,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]LLCMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// : %swift.type* getelementptr inbounds ( -// : %swift.full_heapmetadata, -// : %swift.full_heapmetadata* bitcast ( -// : <{ -// : void ( -// : %T4main3Box[[UNIQUE_ID_2]]LLC* -// : )*, -// : i8**, -// : [[INT]], -// : %objc_class*, -// : %swift.opaque*, -// : %swift.opaque*, -// : [[INT]], -// : i32, -// : i32, -// : i32, -// : i16, -// : i16, -// : i32, -// : i32, -// : %swift.type_descriptor*, -// : i8*, -// : %swift.type*, -// : [[INT]], -// : %T4main3Box[[UNIQUE_ID_2]]LLC* ( -// : %swift.opaque*, -// : %swift.type* -// : )* -// : }>* -// CHECK-SAME: @"$s4main3Box[[UNIQUE_ID_1]]LLCyAA5InnerACLLCySiGGMf" -// : to %swift.full_heapmetadata* -// : ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 2 -// CHECK-SAME: ) to i8* -// CHECK-SAME: ), -// CHECK-SAME: [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_3:[0-9A-Z_]+]]LLCyAA3BoxACLLCyAA5InnerACLLCySiGGGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK: [[INT]] [[METADATA_REQUEST]], // CHECK: i8* [[ERASED_TYPE]], diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_enum.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_enum.swift index 73d90d620d033..5bbc41092198d 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_enum.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_enum.swift @@ -171,35 +171,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]CMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: [[INT]], -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main6Either[[UNIQUE_ID_1]]OySiGMf" to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ) to i8* -// CHECK-SAME: ), -// CHECK-SAME: [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_3:[0-9A-Z_]+]]CyAA6EitherACLLOySiGGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK: [[INT]] [[METADATA_REQUEST]], // CHECK: i8* [[ERASED_TYPE]], diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_struct.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_struct.swift index 5d0d352c4716d..fc7680e252c20 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_struct.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use_generic_struct.swift @@ -173,38 +173,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]CMa"([[INT]] [[METADATA_REQUEST:%[0-9]+]], %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: i32, -// : [ -// : 4 x i8 -// : ], -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main4Left[[UNIQUE_ID_1]]VySiGMf" to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ) to i8* -// CHECK-SAME: ), -// CHECK-SAME: [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK-NEXT: [[METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_3:[0-9A-Z_]+]]CyAA4LeftACLLVySiGGMb"([[INT]] [[METADATA_REQUEST]]) -// CHECK: [[METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0 -// CHECK: [[PARTIAL_RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response undef, %swift.type* [[METADATA]], 0 -// CHECK: [[RESULT_METADATA:%[\" a-zA-Z0-9]+]] = insertvalue %swift.metadata_response [[PARTIAL_RESULT_METADATA]], [[INT]] 0, 1 -// CHECK: ret %swift.metadata_response [[RESULT_METADATA]] -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK: [[INT]] [[METADATA_REQUEST]], // CHECK: i8* [[ERASED_TYPE]], diff --git a/test/IRGen/prespecialized-metadata/enum-fileprivate-inmodule-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/enum-fileprivate-inmodule-1argument-1distinct_use.swift index 8a7e7f5b64002..3a494d17e3fa8 100644 --- a/test/IRGen/prespecialized-metadata/enum-fileprivate-inmodule-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/enum-fileprivate-inmodule-1argument-1distinct_use.swift @@ -58,31 +58,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]OMa"([[INT]] %0, %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main5Value[[UNIQUE_ID_1]]OySiGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE]], diff --git a/test/IRGen/prespecialized-metadata/enum-inmodule-0argument-within-class-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/enum-inmodule-0argument-within-class-1argument-1distinct_use.swift index 944f264a0642c..f79e24b3e4d70 100644 --- a/test/IRGen/prespecialized-metadata/enum-inmodule-0argument-within-class-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/enum-inmodule-0argument-within-class-1argument-1distinct_use.swift @@ -65,31 +65,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main9NamespaceC5ValueOMa"([[INT]] %0, %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: br i1 [[EQUAL_TYPES_1_1]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main9NamespaceC5ValueOySi_GMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE_1]], diff --git a/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-1conformance-1distinct_use.swift b/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-1conformance-1distinct_use.swift index 75f5f86c789c5..630518893d0eb 100644 --- a/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-1conformance-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-1conformance-1distinct_use.swift @@ -68,55 +68,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TABLE:%[0-9]+]] = bitcast i8** %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: [[ARGUMENT_BUFFER:%[0-9]+]] = bitcast i8* [[ERASED_TABLE]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR:%[0-9]+]] = load i8*, i8** [[ARGUMENT_BUFFER]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1PAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS:%[0-9]+]] = and i1 [[EQUAL_TYPES]], [[EQUAL_DESCRIPTORS]] -// CHECK: br i1 [[EQUAL_ARGUMENTS]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: i8**, -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main5ValueOySiGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE]], diff --git a/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-1conformance-public-1distinct_use.swift b/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-1conformance-public-1distinct_use.swift index 06214ca5a0df9..9687535123ac3 100644 --- a/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-1conformance-public-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-1conformance-public-1distinct_use.swift @@ -68,55 +68,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TABLE:%[0-9]+]] = bitcast i8** %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: [[ARGUMENT_BUFFER:%[0-9]+]] = bitcast i8* [[ERASED_TABLE]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR:%[0-9]+]] = load i8*, i8** [[ARGUMENT_BUFFER]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1PAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS:%[0-9]+]] = and i1 [[EQUAL_TYPES]], [[EQUAL_DESCRIPTORS]] -// CHECK: br i1 [[EQUAL_ARGUMENTS]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: i8**, -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main5ValueOySiGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE]], diff --git a/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-1distinct_use.swift index 2a779835e9856..6e84589deff53 100644 --- a/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-1distinct_use.swift @@ -62,14 +62,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main5ValueOMa"([[INT]] %0, %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i64 }>* @"$s4main5ValueOySiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* %2, diff --git a/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-within-class-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-within-class-1argument-1distinct_use.swift index 9b30b71caf0cf..21a955c1e2231 100644 --- a/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-within-class-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-within-class-1argument-1distinct_use.swift @@ -66,34 +66,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: br i1 [[EQUAL_TYPES_1_2]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main9NamespaceC5ValueOySS_SiGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE_1]], diff --git a/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-within-enum-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-within-enum-1argument-1distinct_use.swift index 26b68649a8ab9..c1e0c869f9516 100644 --- a/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-within-enum-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-within-enum-1argument-1distinct_use.swift @@ -66,34 +66,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: br i1 [[EQUAL_TYPES_1_2]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main9NamespaceO5ValueOySS_SiGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE_1]], diff --git a/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-within-struct-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-within-struct-1argument-1distinct_use.swift index 31a2ac1032fcc..5919bbbca14f2 100644 --- a/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-within-struct-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/enum-inmodule-1argument-within-struct-1argument-1distinct_use.swift @@ -66,33 +66,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: br i1 [[EQUAL_TYPES_1_2]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, %swift.type*, -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main9NamespaceV5ValueOySS_SiGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE_1]], diff --git a/test/IRGen/prespecialized-metadata/enum-inmodule-2argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/enum-inmodule-2argument-1distinct_use.swift index 456565a9e6d8e..a37bd8d51a0f4 100644 --- a/test/IRGen/prespecialized-metadata/enum-inmodule-2argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/enum-inmodule-2argument-1distinct_use.swift @@ -81,34 +81,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: br i1 [[EQUAL_TYPES_1_2]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, %swift.type*, -// CHECK-SAME: [[INT]], -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main5ValueOyS2iGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE_1]], diff --git a/test/IRGen/prespecialized-metadata/enum-inmodule-3argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/enum-inmodule-3argument-1distinct_use.swift index 5d7a94d8356ec..b354662dc6f2f 100644 --- a/test/IRGen/prespecialized-metadata/enum-inmodule-3argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/enum-inmodule-3argument-1distinct_use.swift @@ -86,38 +86,6 @@ doit() // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* %2 to i8* // CHECK: [[ERASED_TYPE_3:%[0-9]+]] = bitcast %swift.type* %3 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: [[EQUAL_TYPE_1_3:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_3]] -// CHECK: [[EQUAL_TYPES_1_3:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_2]], [[EQUAL_TYPE_1_3]] -// CHECK: br i1 [[EQUAL_TYPES_1_3]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: [[INT]], -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main5ValueOyS3iGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE_1]], diff --git a/test/IRGen/prespecialized-metadata/enum-inmodule-4argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/enum-inmodule-4argument-1distinct_use.swift index 1bdf941808ad3..52928f5303254 100644 --- a/test/IRGen/prespecialized-metadata/enum-inmodule-4argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/enum-inmodule-4argument-1distinct_use.swift @@ -87,49 +87,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main5ValueOMa"([[INT]] %0, i8** %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_BUFFER:%[0-9]+]] = bitcast i8** %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[ERASED_TYPE_ADDRESS_1:%[0-9]+]] = getelementptr i8*, i8** %1, i64 0 -// CHECK: [[ERASED_TYPE_1:%\".*\"]] = load i8*, i8** [[ERASED_TYPE_ADDRESS_1]] -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[ERASED_TYPE_ADDRESS_2:%[0-9]+]] = getelementptr i8*, i8** %1, i64 1 -// CHECK: [[ERASED_TYPE_2:%\".*\"]] = load i8*, i8** [[ERASED_TYPE_ADDRESS_2]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: [[ERASED_TYPE_ADDRESS_3:%[0-9]+]] = getelementptr i8*, i8** %1, i64 2 -// CHECK: [[ERASED_TYPE_3:%\".*\"]] = load i8*, i8** [[ERASED_TYPE_ADDRESS_3]] -// CHECK: [[EQUAL_TYPE_1_3:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_3]] -// CHECK: [[EQUAL_TYPES_1_3:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_2]], [[EQUAL_TYPE_1_3]] -// CHECK: [[ERASED_TYPE_ADDRESS_4:%[0-9]+]] = getelementptr i8*, i8** %1, i64 3 -// CHECK: [[ERASED_TYPE_4:%\".*\"]] = load i8*, i8** [[ERASED_TYPE_ADDRESS_4]] -// CHECK: [[EQUAL_TYPE_1_4:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_4]] -// CHECK: [[EQUAL_TYPES_1_4:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_3]], [[EQUAL_TYPE_1_4]] -// CHECK: br i1 [[EQUAL_TYPES_1_4]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: [[INT]], -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main5ValueOyS4iGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @swift_getGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_BUFFER]], diff --git a/test/IRGen/prespecialized-metadata/enum-inmodule-5argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/enum-inmodule-5argument-1distinct_use.swift index 2749bacd8e23f..7ff26cd1f62d2 100644 --- a/test/IRGen/prespecialized-metadata/enum-inmodule-5argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/enum-inmodule-5argument-1distinct_use.swift @@ -86,54 +86,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main5ValueOMa"([[INT]] %0, i8** %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_BUFFER:%[0-9]+]] = bitcast i8** %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[ERASED_TYPE_ADDRESS_1:%[0-9]+]] = getelementptr i8*, i8** %1, i64 0 -// CHECK: [[ERASED_TYPE_1:%\".*\"]] = load i8*, i8** [[ERASED_TYPE_ADDRESS_1]] -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[ERASED_TYPE_ADDRESS_2:%[0-9]+]] = getelementptr i8*, i8** %1, i64 1 -// CHECK: [[ERASED_TYPE_2:%\".*\"]] = load i8*, i8** [[ERASED_TYPE_ADDRESS_2]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: [[ERASED_TYPE_ADDRESS_3:%[0-9]+]] = getelementptr i8*, i8** %1, i64 2 -// CHECK: [[ERASED_TYPE_3:%\".*\"]] = load i8*, i8** [[ERASED_TYPE_ADDRESS_3]] -// CHECK: [[EQUAL_TYPE_1_3:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_3]] -// CHECK: [[EQUAL_TYPES_1_3:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_2]], [[EQUAL_TYPE_1_3]] -// CHECK: [[ERASED_TYPE_ADDRESS_4:%[0-9]+]] = getelementptr i8*, i8** %1, i64 3 -// CHECK: [[ERASED_TYPE_4:%\".*\"]] = load i8*, i8** [[ERASED_TYPE_ADDRESS_4]] -// CHECK: [[EQUAL_TYPE_1_4:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_4]] -// CHECK: [[EQUAL_TYPES_1_4:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_3]], [[EQUAL_TYPE_1_4]] -// CHECK: [[ERASED_TYPE_ADDRESS_5:%[0-9]+]] = getelementptr i8*, i8** %1, i64 4 -// CHECK: [[ERASED_TYPE_5:%\".*\"]] = load i8*, i8** [[ERASED_TYPE_ADDRESS_5]] -// CHECK: [[EQUAL_TYPE_1_5:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_5]] -// CHECK: [[EQUAL_TYPES_1_5:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_4]], [[EQUAL_TYPE_1_5]] -// CHECK: br i1 [[EQUAL_TYPES_1_5]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: [[INT]], -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main5ValueOyS5iGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @swift_getGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_BUFFER]], diff --git a/test/IRGen/prespecialized-metadata/enum-inmodule-evolution-1argument-1distinct_use-external_resilient-frozen.swift b/test/IRGen/prespecialized-metadata/enum-inmodule-evolution-1argument-1distinct_use-external_resilient-frozen.swift index 9e45d4f245786..5215223884858 100644 --- a/test/IRGen/prespecialized-metadata/enum-inmodule-evolution-1argument-1distinct_use-external_resilient-frozen.swift +++ b/test/IRGen/prespecialized-metadata/enum-inmodule-evolution-1argument-1distinct_use-external_resilient-frozen.swift @@ -66,31 +66,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main5ValueOMa"([[INT]] %0, %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$s10TestModule7IntegerVN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main5ValueOy10TestModule7IntegerVGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* %2, diff --git a/test/IRGen/prespecialized-metadata/enum-inmodule-evolution-1argument-1distinct_use-payload_size.swift b/test/IRGen/prespecialized-metadata/enum-inmodule-evolution-1argument-1distinct_use-payload_size.swift index 5b944e2618b4a..6a200c420543a 100644 --- a/test/IRGen/prespecialized-metadata/enum-inmodule-evolution-1argument-1distinct_use-payload_size.swift +++ b/test/IRGen/prespecialized-metadata/enum-inmodule-evolution-1argument-1distinct_use-payload_size.swift @@ -78,31 +78,6 @@ doit() // CHECK: define{{( protected)?}} swiftcc %swift.metadata_response @"$s4main5ValueOMa"([[INT]] %0, %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: [[INT]], -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main5ValueOySiGMf" to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* %2, diff --git a/test/IRGen/prespecialized-metadata/struct-fileprivate-inmodule-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-fileprivate-inmodule-1argument-1distinct_use.swift index cdddc211799bb..071cdb03e2b80 100644 --- a/test/IRGen/prespecialized-metadata/struct-fileprivate-inmodule-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-fileprivate-inmodule-1argument-1distinct_use.swift @@ -44,14 +44,6 @@ doit() // CHECK: define internal swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]VMa"([[INT]] %0, %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5Value[[UNIQUE_ID_1]]VySiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE]], i8* undef, i8* undef, %swift.type_descriptor* bitcast ({{.+}}$s4main5Value[[UNIQUE_ID_1]]VMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-0argument-within-class-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-0argument-within-class-1argument-1distinct_use.swift index 02abab0244ef8..fa465d41a8544 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-0argument-within-class-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-0argument-within-class-1argument-1distinct_use.swift @@ -46,14 +46,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main9NamespaceC5ValueVMa"([[INT]] %0, %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: br i1 [[EQUAL_TYPES_1_1]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main9NamespaceC5ValueVySi_GMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE_1]], i8* undef, i8* undef, %swift.type_descriptor* bitcast ({{.+}}$s4main9NamespaceC5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-1conformance-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-1conformance-1distinct_use.swift index 9e811bba493b3..80febc5946810 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-1conformance-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-1conformance-1distinct_use.swift @@ -51,37 +51,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TABLE:%[0-9]+]] = bitcast i8** %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: [[ARGUMENT_BUFFER:%[0-9]+]] = bitcast i8* [[ERASED_TABLE]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR:%[0-9]+]] = load i8*, i8** [[ARGUMENT_BUFFER]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1PAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS:%[0-9]+]] = and i1 [[EQUAL_TYPES]], [[EQUAL_DESCRIPTORS]] -// CHECK: br i1 [[EQUAL_ARGUMENTS]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i8**, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE]], i8* [[ERASED_TABLE]], i8* undef, %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-1distinct_generic_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-1distinct_generic_use.swift index 7dc812bb048c3..7798990de8678 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-1distinct_generic_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-1distinct_generic_use.swift @@ -54,53 +54,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main5OuterVMa"([[INT]] %0, %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast ( -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: i32, -// CHECK-SAME: {{(\[4 x i8\],)?}} -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main5InnerVySiGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ) -// CHECK-SAME: to i8* -// CHECK-SAME: ), -// CHECK-SAME: [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: i32, -// CHECK-SAME: {{(\[4 x i8\],)?}} -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main5OuterVyAA5InnerVySiGGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE]], @@ -117,33 +70,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main5InnerVMa"([[INT]] %0, %swift.type* [[TYPE:%[0-9]+]]) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* [[TYPE]] to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: i32, -// CHECK-SAME: {{(\[4 x i8\],)?}} -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main5InnerVySiGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE]], diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-1distinct_use.swift index fc8e54dcce67a..605c568ca8596 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-1distinct_use.swift @@ -44,14 +44,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main5ValueVMa"([[INT]] %0, %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE]], i8* undef, i8* undef, %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-2conformance-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-2conformance-1distinct_use.swift index 18faf8c91f44a..93446c7633952 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-2conformance-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-2conformance-1distinct_use.swift @@ -56,60 +56,6 @@ doit() // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TABLE_1:%[0-9]+]] = bitcast i8** %2 to i8* // CHECK: [[ERASED_TABLE_2:%[0-9]+]] = bitcast i8** %3 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: [[UNERASED_TABLE_1:%[0-9]+]] = bitcast i8* [[ERASED_TABLE_1]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_1:%[0-9]+]] = load i8*, i8** [[UNERASED_TABLE_1]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR_1:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_1]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT_1:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE_1]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE_1:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT_1]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_1:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE_1]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_1:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_1]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_1:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_1]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_1:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_1]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_1:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_1]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS_1:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_1]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1PAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS_1:%[0-9]+]] = and i1 [[EQUAL_TYPES]], [[EQUAL_DESCRIPTORS_1]] -// CHECK: [[UNERASED_TABLE_2:%[0-9]+]] = bitcast i8* [[ERASED_TABLE_2]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_2:%[0-9]+]] = load i8*, i8** [[UNERASED_TABLE_2]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR_2:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_2]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT_2:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE_2]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE_2:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT_2]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_2:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE_2]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_2:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_2]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_2:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_2]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_2:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_2]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_2:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_2]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS_2:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_2]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1QAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS_2:%[0-9]+]] = and i1 [[EQUAL_ARGUMENTS_1]], [[EQUAL_DESCRIPTORS_2]] -// CHECK: br i1 [[EQUAL_ARGUMENTS_2]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i8**, i8**, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE]], i8* [[ERASED_TABLE_1]], i8* [[ERASED_TABLE_2]], %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-2distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-2distinct_use.swift index 09d7aea9c2cc5..4ddadcc18122b 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-2distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-2distinct_use.swift @@ -63,20 +63,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main5ValueVMa"([[INT]] %0, %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1]] -// CHECK: br i1 [[EQUAL_TYPES_1]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[TYPE_COMPARISON_2:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_2]]: -// CHECK: [[EQUAL_TYPE_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSdN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES_2:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_2]] -// CHECK: br i1 [[EQUAL_TYPES_2]], label %[[EXIT_PRESPECIALIZED_2:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_2]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySdGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE]], i8* undef, i8* undef, %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-3conformance-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-3conformance-1distinct_use.swift index 43342719fb133..be61faa0c9c05 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-3conformance-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-3conformance-1distinct_use.swift @@ -58,91 +58,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main5ValueVMa"([[INT]] %0, i8** %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_ARGUMENT_BUFFER:%[0-9]+]] = bitcast i8** %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[ERASED_TYPE_ADDRESS:%[0-9]+]] = getelementptr i8*, i8** %1, i64 0 -// CHECK: %"load argument at index 0 from buffer" = load i8*, i8** [[ERASED_TYPE_ADDRESS]] -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), %"load argument at index 0 from buffer" -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: [[POINTER_TO_ERASED_TABLE_1:%[0-9]+]] = getelementptr i8*, i8** %1, i64 1 -// CHECK: [[ERASED_TABLE_1:%"load argument at index 1 from buffer"]] = load i8*, i8** [[POINTER_TO_ERASED_TABLE_1]], align 1 -// CHECK: [[UNERASED_TABLE_1:%[0-9]+]] = bitcast i8* [[ERASED_TABLE_1]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_1:%[0-9]+]] = load i8*, i8** [[UNERASED_TABLE_1]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR_1:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_1]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT_1:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE_1]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE_1:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT_1]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_1:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE_1]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_1:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_1]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_1:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_1]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_1:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_1]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_1:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_1]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS_1:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_1]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1PAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS_1:%[0-9]+]] = and i1 [[EQUAL_TYPES]], [[EQUAL_DESCRIPTORS_1]] -// CHECK: [[POINTER_TO_ERASED_TABLE_2:%[0-9]+]] = getelementptr i8*, i8** %1, i64 2 -// CHECK: [[ERASED_TABLE_2:%"load argument at index 2 from buffer"]] = load i8*, i8** [[POINTER_TO_ERASED_TABLE_2]], align 1 -// CHECK: [[UNERASED_TABLE_2:%[0-9]+]] = bitcast i8* [[ERASED_TABLE_2]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_2:%[0-9]+]] = load i8*, i8** [[UNERASED_TABLE_2]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR_2:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_2]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT_2:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE_2]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE_2:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT_2]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_2:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE_2]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_2:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_2]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_2:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_2]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_2:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_2]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_2:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_2]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS_2:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_2]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1QAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS_2:%[0-9]+]] = and i1 [[EQUAL_ARGUMENTS_1]], [[EQUAL_DESCRIPTORS_2]] -// CHECK: [[POINTER_TO_ERASED_TABLE_3:%[0-9]+]] = getelementptr i8*, i8** %1, i64 3 -// CHECK: [[ERASED_TABLE_3:%"load argument at index 3 from buffer"]] = load i8*, i8** [[POINTER_TO_ERASED_TABLE_3]], align 1 -// CHECK: [[UNERASED_TABLE_3:%[0-9]+]] = bitcast i8* [[ERASED_TABLE_3]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_3:%[0-9]+]] = load i8*, i8** [[UNERASED_TABLE_3]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR_3:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_3]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT_3:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE_3]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE_3:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT_3]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_3:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE_3]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_3:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_3]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_3:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_3]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_3:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_3]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_3:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_3]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS_3:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_3]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1RAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS_3:%[0-9]+]] = and i1 [[EQUAL_ARGUMENTS_2]], [[EQUAL_DESCRIPTORS_3]] -// CHECK: br i1 [[EQUAL_ARGUMENTS_3]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i8**, i8**, i8**, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @swift_getGenericMetadata([[INT]] %0, i8* [[ERASED_ARGUMENT_BUFFER]], %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-3distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-3distinct_use.swift index 614d85ee5a084..94acd09f2848d 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-3distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-3distinct_use.swift @@ -84,26 +84,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main5ValueVMa"([[INT]] %0, %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1]] -// CHECK: br i1 [[EQUAL_TYPES_1]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[TYPE_COMPARISON_2:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_2]]: -// CHECK: [[EQUAL_TYPE_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSdN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES_2:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_2]] -// CHECK: br i1 [[EQUAL_TYPES_2]], label %[[EXIT_PRESPECIALIZED_2:[0-9]+]], label %[[TYPE_COMPARISON_3:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_3]]: -// CHECK: [[EQUAL_TYPE_3:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES_3:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_3]] -// CHECK: br i1 [[EQUAL_TYPES_3]], label %[[EXIT_PRESPECIALIZED_3:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_2]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySdGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_3]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySSGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE]], i8* undef, i8* undef, %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-4conformance-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-4conformance-1distinct_use.swift index 2a680000ea99e..ecc6525d7f0c7 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-4conformance-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-4conformance-1distinct_use.swift @@ -62,116 +62,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main5ValueVMa"([[INT]] %0, i8** %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_ARGUMENT_BUFFER:%[0-9]+]] = bitcast i8** %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[ERASED_TYPE_ADDRESS:%[0-9]+]] = getelementptr i8*, i8** %1, i64 0 -// CHECK: %"load argument at index 0 from buffer" = load i8*, i8** [[ERASED_TYPE_ADDRESS]] -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), %"load argument at index 0 from buffer" -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: [[POINTER_TO_ERASED_TABLE_1:%[0-9]+]] = getelementptr i8*, i8** %1, i64 1 -// CHECK: [[ERASED_TABLE_1:%"load argument at index 1 from buffer"]] = load i8*, i8** [[POINTER_TO_ERASED_TABLE_1]], align 1 -// CHECK: [[UNERASED_TABLE_1:%[0-9]+]] = bitcast i8* [[ERASED_TABLE_1]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_1:%[0-9]+]] = load i8*, i8** [[UNERASED_TABLE_1]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR_1:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_1]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT_1:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE_1]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE_1:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT_1]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_1:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE_1]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_1:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_1]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_1:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_1]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_1:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_1]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_1:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_1]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS_1:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_1]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1PAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS_1:%[0-9]+]] = and i1 [[EQUAL_TYPES]], [[EQUAL_DESCRIPTORS_1]] -// CHECK: [[POINTER_TO_ERASED_TABLE_2:%[0-9]+]] = getelementptr i8*, i8** %1, i64 2 -// CHECK: [[ERASED_TABLE_2:%"load argument at index 2 from buffer"]] = load i8*, i8** [[POINTER_TO_ERASED_TABLE_2]], align 1 -// CHECK: [[UNERASED_TABLE_2:%[0-9]+]] = bitcast i8* [[ERASED_TABLE_2]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_2:%[0-9]+]] = load i8*, i8** [[UNERASED_TABLE_2]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR_2:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_2]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT_2:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE_2]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE_2:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT_2]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_2:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE_2]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_2:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_2]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_2:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_2]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_2:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_2]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_2:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_2]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS_2:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_2]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1QAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS_2:%[0-9]+]] = and i1 [[EQUAL_ARGUMENTS_1]], [[EQUAL_DESCRIPTORS_2]] -// CHECK: [[POINTER_TO_ERASED_TABLE_3:%[0-9]+]] = getelementptr i8*, i8** %1, i64 3 -// CHECK: [[ERASED_TABLE_3:%"load argument at index 3 from buffer"]] = load i8*, i8** [[POINTER_TO_ERASED_TABLE_3]], align 1 -// CHECK: [[UNERASED_TABLE_3:%[0-9]+]] = bitcast i8* [[ERASED_TABLE_3]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_3:%[0-9]+]] = load i8*, i8** [[UNERASED_TABLE_3]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR_3:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_3]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT_3:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE_3]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE_3:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT_3]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_3:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE_3]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_3:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_3]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_3:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_3]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_3:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_3]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_3:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_3]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS_3:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_3]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1RAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS_3:%[0-9]+]] = and i1 [[EQUAL_ARGUMENTS_2]], [[EQUAL_DESCRIPTORS_3]] -// CHECK: [[POINTER_TO_ERASED_TABLE_4:%[0-9]+]] = getelementptr i8*, i8** %1, i64 4 -// CHECK: [[ERASED_TABLE_4:%"load argument at index 4 from buffer"]] = load i8*, i8** [[POINTER_TO_ERASED_TABLE_4]], align 1 -// CHECK: [[UNERASED_TABLE_4:%[0-9]+]] = bitcast i8* [[ERASED_TABLE_4]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_4:%[0-9]+]] = load i8*, i8** [[UNERASED_TABLE_4]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR_4:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_4]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT_4:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE_4]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE_4:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT_4]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_4:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE_4]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_4:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_4]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_4:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_4]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_4:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_4]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_4:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_4]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS_4:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_4]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1SAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS_4:%[0-9]+]] = and i1 [[EQUAL_ARGUMENTS_3]], [[EQUAL_DESCRIPTORS_4]] -// CHECK: br i1 [[EQUAL_ARGUMENTS_4]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i8**, i8**, i8**, i8**, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @swift_getGenericMetadata([[INT]] %0, i8* [[ERASED_ARGUMENT_BUFFER]], %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-4distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-4distinct_use.swift index a60f667a627fe..22eee9e0055db 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-4distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-4distinct_use.swift @@ -85,32 +85,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main5ValueVMa"([[INT]] %0, %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1]] -// CHECK: br i1 [[EQUAL_TYPES_1]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[TYPE_COMPARISON_2:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_2]]: -// CHECK: [[EQUAL_TYPE_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSdN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES_2:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_2]] -// CHECK: br i1 [[EQUAL_TYPES_2]], label %[[EXIT_PRESPECIALIZED_2:[0-9]+]], label %[[TYPE_COMPARISON_3:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_3]]: -// CHECK: [[EQUAL_TYPE_3:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES_3:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_3]] -// CHECK: br i1 [[EQUAL_TYPES_3]], label %[[EXIT_PRESPECIALIZED_3:[0-9]+]], label %[[TYPE_COMPARISON_4:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_4]]: -// CHECK: [[EQUAL_TYPE_4:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$ss5UInt8VN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES_4:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_4]] -// CHECK: br i1 [[EQUAL_TYPES_4]], label %[[EXIT_PRESPECIALIZED_4:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_2]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySdGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_3]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySSGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_4]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVys5UInt8VGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE]], i8* undef, i8* undef, %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-5conformance-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-5conformance-1distinct_use.swift index 3bfa8c5834da9..f4dc38b7bdb7f 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-5conformance-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-5conformance-1distinct_use.swift @@ -66,141 +66,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main5ValueVMa"([[INT]] %0, i8** %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_ARGUMENT_BUFFER:%[0-9]+]] = bitcast i8** %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[ERASED_TYPE_ADDRESS:%[0-9]+]] = getelementptr i8*, i8** %1, i64 0 -// CHECK: %"load argument at index 0 from buffer" = load i8*, i8** [[ERASED_TYPE_ADDRESS]] -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), %"load argument at index 0 from buffer" -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: [[POINTER_TO_ERASED_TABLE_1:%[0-9]+]] = getelementptr i8*, i8** %1, i64 1 -// CHECK: [[ERASED_TABLE_1:%"load argument at index 1 from buffer"]] = load i8*, i8** [[POINTER_TO_ERASED_TABLE_1]], align 1 -// CHECK: [[UNERASED_TABLE_1:%[0-9]+]] = bitcast i8* [[ERASED_TABLE_1]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_1:%[0-9]+]] = load i8*, i8** [[UNERASED_TABLE_1]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR_1:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_1]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT_1:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE_1]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE_1:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT_1]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_1:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE_1]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_1:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_1]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_1:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_1]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_1:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_1]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_1:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_1]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS_1:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_1]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1PAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS_1:%[0-9]+]] = and i1 [[EQUAL_TYPES]], [[EQUAL_DESCRIPTORS_1]] -// CHECK: [[POINTER_TO_ERASED_TABLE_2:%[0-9]+]] = getelementptr i8*, i8** %1, i64 2 -// CHECK: [[ERASED_TABLE_2:%"load argument at index 2 from buffer"]] = load i8*, i8** [[POINTER_TO_ERASED_TABLE_2]], align 1 -// CHECK: [[UNERASED_TABLE_2:%[0-9]+]] = bitcast i8* [[ERASED_TABLE_2]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_2:%[0-9]+]] = load i8*, i8** [[UNERASED_TABLE_2]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR_2:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_2]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT_2:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE_2]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE_2:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT_2]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_2:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE_2]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_2:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_2]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_2:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_2]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_2:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_2]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_2:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_2]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS_2:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_2]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1QAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS_2:%[0-9]+]] = and i1 [[EQUAL_ARGUMENTS_1]], [[EQUAL_DESCRIPTORS_2]] -// CHECK: [[POINTER_TO_ERASED_TABLE_3:%[0-9]+]] = getelementptr i8*, i8** %1, i64 3 -// CHECK: [[ERASED_TABLE_3:%"load argument at index 3 from buffer"]] = load i8*, i8** [[POINTER_TO_ERASED_TABLE_3]], align 1 -// CHECK: [[UNERASED_TABLE_3:%[0-9]+]] = bitcast i8* [[ERASED_TABLE_3]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_3:%[0-9]+]] = load i8*, i8** [[UNERASED_TABLE_3]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR_3:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_3]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT_3:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE_3]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE_3:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT_3]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_3:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE_3]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_3:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_3]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_3:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_3]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_3:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_3]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_3:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_3]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS_3:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_3]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1RAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS_3:%[0-9]+]] = and i1 [[EQUAL_ARGUMENTS_2]], [[EQUAL_DESCRIPTORS_3]] -// CHECK: [[POINTER_TO_ERASED_TABLE_4:%[0-9]+]] = getelementptr i8*, i8** %1, i64 4 -// CHECK: [[ERASED_TABLE_4:%"load argument at index 4 from buffer"]] = load i8*, i8** [[POINTER_TO_ERASED_TABLE_4]], align 1 -// CHECK: [[UNERASED_TABLE_4:%[0-9]+]] = bitcast i8* [[ERASED_TABLE_4]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_4:%[0-9]+]] = load i8*, i8** [[UNERASED_TABLE_4]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR_4:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_4]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT_4:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE_4]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE_4:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT_4]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_4:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE_4]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_4:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_4]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_4:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_4]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_4:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_4]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_4:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_4]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS_4:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_4]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1SAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS_4:%[0-9]+]] = and i1 [[EQUAL_ARGUMENTS_3]], [[EQUAL_DESCRIPTORS_4]] -// CHECK: [[POINTER_TO_ERASED_TABLE_5:%[0-9]+]] = getelementptr i8*, i8** %1, i64 5 -// CHECK: [[ERASED_TABLE_5:%"load argument at index 5 from buffer"]] = load i8*, i8** [[POINTER_TO_ERASED_TABLE_5]], align 1 -// CHECK: [[UNERASED_TABLE_5:%[0-9]+]] = bitcast i8* [[ERASED_TABLE_5]] to i8** -// CHECK: [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_5:%[0-9]+]] = load i8*, i8** [[UNERASED_TABLE_5]], align 1 -// CHECK: [[PROVIDED_PROTOCOL_DESCRIPTOR_5:%[0-9]+]] = bitcast i8* [[UNCAST_PROVIDED_PROTOCOL_DESCRIPTOR_5]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[ERASED_TABLE_INT_5:%[0-9]+]] = ptrtoint i8* [[ERASED_TABLE_5]] to i64 -// CHECK-arm64e: [[TABLE_SIGNATURE_5:%[0-9]+]] = call i64 @llvm.ptrauth.blend.i64(i64 [[ERASED_TABLE_INT_5]], i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_5:%[0-9]+]] = call i64 @llvm.ptrauth.auth.i64(i64 %13, i32 2, i64 [[TABLE_SIGNATURE_5]]) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_5:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_5]] to %swift.protocol_conformance_descriptor* -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_5:%[0-9]+]] = ptrtoint %swift.protocol_conformance_descriptor* [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_5]] to i64 -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_5:%[0-9]+]] = call i64 @llvm.ptrauth.sign.i64(i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_AUTHED_PTR_INT_5]], i32 2, i64 50923) -// CHECK-arm64e: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_5:%[0-9]+]] = inttoptr i64 [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_INT_5]] to %swift.protocol_conformance_descriptor* -// CHECK: [[EQUAL_DESCRIPTORS_5:%[0-9]+]] = call swiftcc i1 @swift_compareProtocolConformanceDescriptors( -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-arm64e-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR_SIGNED_5]], -// CHECK-i386-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-x86_64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7s-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-armv7k-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-arm64-SAME: [[PROVIDED_PROTOCOL_DESCRIPTOR]], -// CHECK-SAME: %swift.protocol_conformance_descriptor* -// CHECK-SAME: $sSi4main1TAAMc -// CHECK-SAME: ) -// CHECK: [[EQUAL_ARGUMENTS_5:%[0-9]+]] = and i1 [[EQUAL_ARGUMENTS_4]], [[EQUAL_DESCRIPTORS_5]] -// CHECK: br i1 [[EQUAL_ARGUMENTS_5]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i8**, i8**, i8**, i8**, i8**, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @swift_getGenericMetadata([[INT]] %0, i8* [[ERASED_ARGUMENT_BUFFER]], %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-5distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-5distinct_use.swift index 3a98fe75c3016..01ce8938f9e44 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-5distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-5distinct_use.swift @@ -123,38 +123,6 @@ doit() // CHECK: define hidden swiftcc %swift.metadata_response @"$s4main5ValueVMa"([[INT]] %0, %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1]] -// CHECK: br i1 [[EQUAL_TYPES_1]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[TYPE_COMPARISON_2:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_2]]: -// CHECK: [[EQUAL_TYPE_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSdN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES_2:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_2]] -// CHECK: br i1 [[EQUAL_TYPES_2]], label %[[EXIT_PRESPECIALIZED_2:[0-9]+]], label %[[TYPE_COMPARISON_3:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_3]]: -// CHECK: [[EQUAL_TYPE_3:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES_3:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_3]] -// CHECK: br i1 [[EQUAL_TYPES_3]], label %[[EXIT_PRESPECIALIZED_3:[0-9]+]], label %[[TYPE_COMPARISON_4:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_4]]: -// CHECK: [[EQUAL_TYPE_4:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$ss5UInt8VN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES_4:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_4]] -// CHECK: br i1 [[EQUAL_TYPES_4]], label %[[EXIT_PRESPECIALIZED_4:[0-9]+]], label %[[TYPE_COMPARISON_5:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_5]]: -// CHECK: [[EQUAL_TYPE_5:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$ss4Int8VN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES_5:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_5]] -// CHECK: br i1 [[EQUAL_TYPES_5]], label %[[EXIT_PRESPECIALIZED_5:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_2]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySdGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_3]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySSGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_4]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVys5UInt8VGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_5]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVys4Int8VGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE]], i8* undef, i8* undef, %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-class-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-class-1argument-1distinct_use.swift index f4e8311a2ebf1..8353f4754477b 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-class-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-class-1argument-1distinct_use.swift @@ -70,35 +70,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: br i1 [[EQUAL_TYPES_1_2]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: i32{{(, \[4 x i8\])?}}, -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main9NamespaceC5ValueVySS_SiGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE_1]], diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-enum-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-enum-1argument-1distinct_use.swift index 1a789c3b3e237..823d3363802d7 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-enum-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-enum-1argument-1distinct_use.swift @@ -70,35 +70,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: br i1 [[EQUAL_TYPES_1_2]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: i32{{(, \[4 x i8\])?}}, -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main9NamespaceO5ValueVySS_SiGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE_1]], diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-struct-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-struct-1argument-1distinct_use.swift index 2a28be73413a7..f0146c3df4869 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-struct-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-struct-1argument-1distinct_use.swift @@ -70,34 +70,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: br i1 [[EQUAL_TYPES_1_2]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, %swift.type*, -// CHECK-SAME: i32{{(, \[4 x i8\])?}}, -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main9NamespaceV5ValueVySS_SiGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE_1]], diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-struct-2argument-constrained_extension-equal_arguments-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-struct-2argument-constrained_extension-equal_arguments-1distinct_use.swift index 9d8885fb6b3da..ce004e7edd3b3 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-struct-2argument-constrained_extension-equal_arguments-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-1argument-within-struct-2argument-constrained_extension-equal_arguments-1distinct_use.swift @@ -77,36 +77,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* [[TYPE_1]] to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* [[TYPE_2]] to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: br i1 [[EQUAL_TYPES_1_2]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { -// CHECK-SAME: %swift.type* getelementptr inbounds ( -// CHECK-SAME: %swift.full_type, -// CHECK-SAME: %swift.full_type* bitcast ( -// CHECK-SAME: <{ -// CHECK-SAME: i8**, -// CHECK-SAME: [[INT]], -// CHECK-SAME: %swift.type_descriptor*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: %swift.type*, -// CHECK-SAME: i32, -// CHECK-SAME: {{(\[4 x i8\],)?}} -// CHECK-SAME: i64 -// CHECK-SAME: }>* @"$s4main9NamespaceVAAq_RszrlE5ValueVyS2i_SSGMf" -// CHECK-SAME: to %swift.full_type* -// CHECK-SAME: ), -// CHECK-SAME: i32 0, -// CHECK-SAME: i32 1 -// CHECK-SAME: ), -// CHECK-SAME: [[INT]] 0 -// CHECK-SAME: } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata( // CHECK-SAME: [[INT]] %0, // CHECK-SAME: i8* [[ERASED_TYPE_1]], diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-1distinct_use.swift index eba0602f76ed8..f05de23860d43 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-1distinct_use.swift @@ -47,16 +47,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: br i1 [[EQUAL_TYPES_1_2]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVyS2iGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE_1]], i8* [[ERASED_TYPE_2]], i8* undef, %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-2distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-2distinct_use.swift index 4e862e3793f8b..ecd49ed9f9acd 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-2distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-2distinct_use.swift @@ -68,24 +68,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: br i1 [[EQUAL_TYPES_1_2]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[TYPE_COMPARISON_2:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_2]]: -// CHECK: [[EQUAL_TYPE_2_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSdN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_2_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_2_1]] -// CHECK: [[EQUAL_TYPE_2_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_2_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_2_1]], [[EQUAL_TYPE_2_2]] -// CHECK: br i1 [[EQUAL_TYPES_2_2]], label %[[EXIT_PRESPECIALIZED_2:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVyS2iGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_2]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVySdSiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE_1]], i8* [[ERASED_TYPE_2]], i8* undef, %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-3distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-3distinct_use.swift index c3ca169770277..76c86eeca2c56 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-3distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-3distinct_use.swift @@ -89,32 +89,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: br i1 [[EQUAL_TYPES_1_2]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[TYPE_COMPARISON_2:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_2]]: -// CHECK: [[EQUAL_TYPE_2_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSdN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_2_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_2_1]] -// CHECK: [[EQUAL_TYPE_2_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_2_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_2_1]], [[EQUAL_TYPE_2_2]] -// CHECK: br i1 [[EQUAL_TYPES_2_2]], label %[[EXIT_PRESPECIALIZED_2:[0-9]+]], label %[[TYPE_COMPARISON_3:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_3]]: -// CHECK: [[EQUAL_TYPE_3_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_3_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_3_1]] -// CHECK: [[EQUAL_TYPE_3_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSdN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_3_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_3_1]], [[EQUAL_TYPE_3_2]] -// CHECK: br i1 [[EQUAL_TYPES_3_2]], label %[[EXIT_PRESPECIALIZED_3:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVyS2iGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_2]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVySdSiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_3]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVySSSdGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE_1]], i8* [[ERASED_TYPE_2]], i8* undef, %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-4distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-4distinct_use.swift index 47ba39cc3dd87..2f3d4fb8f9fd3 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-4distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-4distinct_use.swift @@ -110,40 +110,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: br i1 [[EQUAL_TYPES_1_2]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[TYPE_COMPARISON_2:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_2]]: -// CHECK: [[EQUAL_TYPE_2_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSdN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_2_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_2_1]] -// CHECK: [[EQUAL_TYPE_2_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_2_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_2_1]], [[EQUAL_TYPE_2_2]] -// CHECK: br i1 [[EQUAL_TYPES_2_2]], label %[[EXIT_PRESPECIALIZED_2:[0-9]+]], label %[[TYPE_COMPARISON_3:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_3]]: -// CHECK: [[EQUAL_TYPE_3_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_3_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_3_1]] -// CHECK: [[EQUAL_TYPE_3_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSdN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_3_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_3_1]], [[EQUAL_TYPE_3_2]] -// CHECK: br i1 [[EQUAL_TYPES_3_2]], label %[[EXIT_PRESPECIALIZED_3:[0-9]+]], label %[[TYPE_COMPARISON_4:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_4]]: -// CHECK: [[EQUAL_TYPE_4_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$ss5UInt8VN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_4_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_4_1]] -// CHECK: [[EQUAL_TYPE_4_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_4_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_4_1]], [[EQUAL_TYPE_4_2]] -// CHECK: br i1 [[EQUAL_TYPES_4_2]], label %[[EXIT_PRESPECIALIZED_4:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVyS2iGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_2]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVySdSiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_3]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVySSSdGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_4]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVys5UInt8VSSGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE_1]], i8* [[ERASED_TYPE_2]], i8* undef, %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-5distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-5distinct_use.swift index d71408f206a8a..e0b53ad251296 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-5distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-5distinct_use.swift @@ -184,48 +184,6 @@ doit() // CHECK: entry: // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* %2 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: br i1 [[EQUAL_TYPES_1_2]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[TYPE_COMPARISON_2:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_2]]: -// CHECK: [[EQUAL_TYPE_2_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSdN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_2_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_2_1]] -// CHECK: [[EQUAL_TYPE_2_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_2_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_2_1]], [[EQUAL_TYPE_2_2]] -// CHECK: br i1 [[EQUAL_TYPES_2_2]], label %[[EXIT_PRESPECIALIZED_2:[0-9]+]], label %[[TYPE_COMPARISON_3:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_3]]: -// CHECK: [[EQUAL_TYPE_3_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_3_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_3_1]] -// CHECK: [[EQUAL_TYPE_3_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSdN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_3_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_3_1]], [[EQUAL_TYPE_3_2]] -// CHECK: br i1 [[EQUAL_TYPES_3_2]], label %[[EXIT_PRESPECIALIZED_3:[0-9]+]], label %[[TYPE_COMPARISON_4:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_4]]: -// CHECK: [[EQUAL_TYPE_4_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$ss5UInt8VN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_4_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_4_1]] -// CHECK: [[EQUAL_TYPE_4_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_4_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_4_1]], [[EQUAL_TYPE_4_2]] -// CHECK: br i1 [[EQUAL_TYPES_4_2]], label %[[EXIT_PRESPECIALIZED_4:[0-9]+]], label %[[TYPE_COMPARISON_5:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_5]]: -// CHECK: [[EQUAL_TYPE_5_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$ss4Int8VN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_5_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_5_1]] -// CHECK: [[EQUAL_TYPE_5_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$ss5UInt8VN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_5_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_5_1]], [[EQUAL_TYPE_5_2]] -// CHECK: br i1 [[EQUAL_TYPES_5_2]], label %[[EXIT_PRESPECIALIZED_5:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVyS2iGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_2]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVySdSiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_3]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVySSSdGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_4]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVys5UInt8VSSGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_PRESPECIALIZED_5]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main5ValueVys4Int8Vs5UInt8VGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE_1]], i8* [[ERASED_TYPE_2]], i8* undef, %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-within-class-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-within-class-1argument-1distinct_use.swift index 670d11205f865..1ebeb321ede26 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-within-class-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-2argument-within-class-1argument-1distinct_use.swift @@ -50,18 +50,6 @@ doit() // CHECK: [[ERASED_TYPE_1:%[0-9]+]] = bitcast %swift.type* %1 to i8* // CHECK: [[ERASED_TYPE_2:%[0-9]+]] = bitcast %swift.type* %2 to i8* // CHECK: [[ERASED_TYPE_3:%[0-9]+]] = bitcast %swift.type* %3 to i8* -// CHECK: br label %[[TYPE_COMPARISON_1:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_1]]: -// CHECK: [[EQUAL_TYPE_1_1:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSSN" to i8*), [[ERASED_TYPE_1]] -// CHECK: [[EQUAL_TYPES_1_1:%[0-9]+]] = and i1 true, [[EQUAL_TYPE_1_1]] -// CHECK: [[EQUAL_TYPE_1_2:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE_2]] -// CHECK: [[EQUAL_TYPES_1_2:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_1]], [[EQUAL_TYPE_1_2]] -// CHECK: [[EQUAL_TYPE_1_3:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSdN" to i8*), [[ERASED_TYPE_3]] -// CHECK: [[EQUAL_TYPES_1_3:%[0-9]+]] = and i1 [[EQUAL_TYPES_1_2]], [[EQUAL_TYPE_1_3]] -// CHECK: br i1 [[EQUAL_TYPES_1_3]], label %[[EXIT_PRESPECIALIZED_1:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED_1]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, %swift.type*, %swift.type*, i32, i32, i64 }>* @"$s4main9NamespaceC5ValueVySS_SiSdGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE_1]], i8* [[ERASED_TYPE_2]], i8* [[ERASED_TYPE_3]], %swift.type_descriptor* bitcast ({{.+}}$s4main9NamespaceC5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-1argument-1distinct_use-struct-outmodule-othermodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-1argument-1distinct_use-struct-outmodule-othermodule.swift index 62294db3ba1c6..b870255458401 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-1argument-1distinct_use-struct-outmodule-othermodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-1argument-1distinct_use-struct-outmodule-othermodule.swift @@ -3,12 +3,38 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-0argument.swift -emit-library -o %t/%target-library-name(Argument) -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lGeneric -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios -// CHECK-NOT: @"$s7Generic11OneArgumentVy0C07IntegerVGMN" = +// CHECK: @"$s7Generic11OneArgumentVy0C07IntegerVGMN" = linkonce_odr hidden constant <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }> <{ +// : i8** getelementptr inbounds ( +// : %swift.vwtable, +// : %swift.vwtable* @" +// CHECK-SAME: $s7Generic11OneArgumentVy0C07IntegerVGWV +// : ", +// : i32 0, +// : i32 0 +// : ), +// CHECK-SAME: [[INT]] 512, +// : %swift.type_descriptor* @" +// CHECK-SAME: $s7Generic11OneArgumentVMn +// : ", +// CHECK-SAME: %swift.type* @"$s8Argument7IntegerVN", +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 {{4|8}}, +// CHECK-SAME: i64 1 +// CHECK-SAME: }>, +// CHECK-SAME: align [[ALIGNMENT]] @inline(never) func consume(_ t: T) { @@ -20,8 +46,31 @@ import Generic import Argument // CHECK: define hidden swiftcc void @"$s4main4doityyF"() #{{[0-9]+}} { -// CHECK: [[METADATA:%[0-9]+]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s7Generic11OneArgumentVy0C07IntegerVGMD") -// CHECK: call swiftcc void @"$s4main7consumeyyxlF"(%swift.opaque* noalias nocapture {{%[0-9]+}}, %swift.type* [[METADATA]]) +// CHECK: [[CANONICALIZED_METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @swift_getCanonicalSpecializedMetadata( +// CHECK-SAME: [[INT]] 0, +// CHECK-SAME: %swift.type* getelementptr inbounds ( +// CHECK-SAME: %swift.full_type, +// CHECK-SAME: %swift.full_type* bitcast ( +// CHECK-SAME: <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }>* @"$s7Generic11OneArgumentVy0C07IntegerVGMN" to %swift.full_type* +// CHECK-SAME: ), +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 1 +// CHECK-SAME: ), +// CHECK-SAME: %swift.type** @"$s7Generic11OneArgumentVy0C07IntegerVGMJ" +// CHECK-SAME: ) +// CHECK-NEXT: [[CANONICALIZED_METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[CANONICALIZED_METADATA_RESPONSE]], 0 +// CHECK-NEXT: call swiftcc void @"$s4main7consumeyyxlF"( +// CHECK-SAME: %swift.opaque* noalias nocapture {{%[0-9]+}}, +// CHECK-SAME: %swift.type* [[CANONICALIZED_METADATA]] +// CHECK-SAME: ) // CHECK: } func doit() { consume( OneArgument(Integer(13)) ) diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-1argument-1distinct_use-struct-outmodule-samemodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-1argument-1distinct_use-struct-outmodule-samemodule.swift index acb5c56c5b943..7eb0f7a6cbc60 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-1argument-1distinct_use-struct-outmodule-samemodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-1argument-1distinct_use-struct-outmodule-samemodule.swift @@ -2,12 +2,38 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-1argument.swift %S/Inputs/struct-public-nonfrozen-0argument.swift -emit-library -o %t/%target-library-name(Argument) -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios -// CHECK-NOT: @"$s8Argument03OneA0VyAA7IntegerVGMN" = +// CHECK: @"$s8Argument03OneA0VyAA7IntegerVGMN" = linkonce_odr hidden constant <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }> <{ +// : i8** getelementptr inbounds ( +// : %swift.vwtable, +// : %swift.vwtable* @" +// CHECK-SAME: $s8Argument03OneA0VyAA7IntegerVGWV +// : ", +// : i32 0, +// : i32 0 +// : ), +// CHECK-SAME: [[INT]] 512, +// : %swift.type_descriptor* @" +// CHECK-SAME: $s8Argument03OneA0VMn +// : ", +// CHECK-SAME: %swift.type* @"$s8Argument7IntegerVN", +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 {{4|8}}, +// CHECK-SAME: i64 1 +// CHECK-SAME: }>, +// CHECK-SAME: align [[ALIGNMENT]] @inline(never) func consume(_ t: T) { @@ -18,8 +44,31 @@ func consume(_ t: T) { import Argument // CHECK: define hidden swiftcc void @"$s4main4doityyF"() #{{[0-9]+}} { -// CHECK: [[METADATA:%[0-9]+]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s8Argument03OneA0VyAA7IntegerVGMD") -// CHECK: call swiftcc void @"$s4main7consumeyyxlF"(%swift.opaque* noalias nocapture {{%[0-9]+}}, %swift.type* [[METADATA]]) +// CHECK: [[CANONICALIZED_METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @swift_getCanonicalSpecializedMetadata( +// CHECK-SAME: [[INT]] 0, +// CHECK-SAME: %swift.type* getelementptr inbounds ( +// CHECK-SAME: %swift.full_type, +// CHECK-SAME: %swift.full_type* bitcast ( +// CHECK-SAME: <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }>* @"$s8Argument03OneA0VyAA7IntegerVGMN" to %swift.full_type* +// CHECK-SAME: ), +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 1 +// CHECK-SAME: ), +// CHECK-SAME: %swift.type** @"$s8Argument03OneA0VyAA7IntegerVGMJ" +// CHECK-SAME: ) +// CHECK-NEXT: [[CANONICALIZED_METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[CANONICALIZED_METADATA_RESPONSE]], 0 +// CHECK-NEXT: call swiftcc void @"$s4main7consumeyyxlF"( +// CHECK-SAME: %swift.opaque* noalias nocapture {{%[0-9]+}}, +// CHECK-SAME: %swift.type* [[CANONICALIZED_METADATA]] +// CHECK-SAME: ) // CHECK: } func doit() { consume( OneArgument(Integer(13)) ) diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_protocol_inmodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_protocol_inmodule.swift index 2718c56287e14..7c7b6fee27917 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_protocol_inmodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_protocol_inmodule.swift @@ -2,12 +2,40 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-1argument-1constraint.swift %S/Inputs/protocol-public-empty.swift %S/Inputs/struct-public-nonfrozen-0argument.swift %S/Inputs/struct-public-nonfrozen-0argument-conformance-empty.swift -emit-library -o %t/%target-library-name(Argument) -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios -// CHECK-NOT: @"$s8Argument03OneA0VyAA7IntegerVGMN" = +// CHECK: @"$s8Argument03OneA0VyAA7IntegerVGMN" = linkonce_odr hidden constant <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i8**, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }> <{ +// : i8** getelementptr inbounds ( +// : %swift.vwtable, +// : %swift.vwtable* @" +// CHECK-SAME: $s8Argument03OneA0VyAA7IntegerVGWV +// : ", +// : i32 0, +// : i32 0 +// : ), +// CHECK-SAME: [[INT]] 512, +// : %swift.type_descriptor* @" +// CHECK-SAME: $s8Argument03OneA0VMn +// : ", +// CHECK-SAME: %swift.type* @"$s8Argument7IntegerVN", +// CHECK-SAME: i8** @"$s8Argument7IntegerVAA1PAAWP", +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 {{4|8}}, +// CHECK-SAME: i64 1 +// CHECK-SAME: }>, +// CHECK-SAME: align [[ALIGNMENT]] @inline(never) func consume(_ t: T) { @@ -18,8 +46,31 @@ func consume(_ t: T) { import Argument // CHECK: define hidden swiftcc void @"$s4main4doityyF"() #{{[0-9]+}} { -// CHECK: [[METADATA:%[0-9]+]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s8Argument03OneA0VyAA7IntegerVGMD") -// CHECK: call swiftcc void @"$s4main7consumeyyxlF"(%swift.opaque* noalias nocapture {{%[0-9]+}}, %swift.type* [[METADATA]]) +// CHECK: [[CANONICALIZED_METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @swift_getCanonicalSpecializedMetadata( +// CHECK-SAME: [[INT]] 0, +// CHECK-SAME: %swift.type* getelementptr inbounds ( +// CHECK-SAME: %swift.full_type, +// CHECK-SAME: %swift.full_type* bitcast ( +// CHECK-SAME: <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }>* @"$s8Argument03OneA0VyAA7IntegerVGMN" to %swift.full_type* +// CHECK-SAME: ), +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 1 +// CHECK-SAME: ), +// CHECK-SAME: %swift.type** @"$s8Argument03OneA0VyAA7IntegerVGMJ" +// CHECK-SAME: ) +// CHECK-NEXT: [[CANONICALIZED_METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[CANONICALIZED_METADATA_RESPONSE]], 0 +// CHECK-NEXT: call swiftcc void @"$s4main7consumeyyxlF"( +// CHECK-SAME: %swift.opaque* noalias nocapture {{%[0-9]+}}, +// CHECK-SAME: %swift.type* [[CANONICALIZED_METADATA]] +// CHECK-SAME: ) // CHECK: } func doit() { consume( OneArgument(Integer(13)) ) diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_protocol_outmodule_othermodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_protocol_outmodule_othermodule.swift index 1cb2721fcc829..72abaf85836c3 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_protocol_outmodule_othermodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_protocol_outmodule_othermodule.swift @@ -3,12 +3,40 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-0argument-conformance-empty.swift -emit-library -o %t/%target-library-name(Argument) -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule -DIMPORT_MODULE -L %t -I %t -lModule // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lModule -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios -// CHECK-NOT: @"$s6Module11OneArgumentVyAA7IntegerVAeA1P0C0yHCg_GMN" = +// CHECK: @"$s6Module11OneArgumentVyAA7IntegerVAeA1P0C0yHCg_GMN" = linkonce_odr hidden constant <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i8**, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME:}> <{ +// : i8** getelementptr inbounds ( +// : %swift.vwtable, +// : %swift.vwtable* @" +// CHECK-SAME: $s6Module11OneArgumentVyAA7IntegerVAeA1P0C0yHCg_GWV +// : ", +// : i32 0, +// : i32 0 +// : ), +// CHECK-SAME: [[INT]] 512, +// : %swift.type_descriptor* @" +// CHECK-SAME: $s6Module11OneArgumentVMn +// : ", +// CHECK-SAME: %swift.type* @"$s6Module7IntegerVN", +// CHECK-SAME: i8** @"$s6Module7IntegerVAA1P8ArgumentWP", +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 {{4|8}}, +// CHECK-SAME: i64 1 +// CHECK-SAME:}>, +// CHECK-SAME:align [[ALIGNMENT]] @inline(never) func consume(_ t: T) { @@ -20,8 +48,31 @@ import Module import Argument // CHECK: define hidden swiftcc void @"$s4main4doityyF"() #{{[0-9]+}} { -// CHECK: [[METADATA:%[0-9]+]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s6Module11OneArgumentVyAA7IntegerVAeA1P0C0yHCg_GMD") -// CHECK: call swiftcc void @"$s4main7consumeyyxlF"(%swift.opaque* noalias nocapture {{%[0-9]+}}, %swift.type* [[METADATA]]) +// CHECK: [[CANONICALIZED_METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @swift_getCanonicalSpecializedMetadata( +// CHECK-SAME: [[INT]] 0, +// CHECK-SAME: %swift.type* getelementptr inbounds ( +// CHECK-SAME: %swift.full_type, +// CHECK-SAME: %swift.full_type* bitcast ( +// CHECK-SAME: <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }>* @"$s6Module11OneArgumentVyAA7IntegerVAeA1P0C0yHCg_GMN" to %swift.full_type* +// CHECK-SAME: ), +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 1 +// CHECK-SAME: ), +// CHECK-SAME: %swift.type** @"$s6Module11OneArgumentVyAA7IntegerVAeA1P0C0yHCg_GMJ" +// CHECK-SAME: ) +// CHECK-NEXT: [[CANONICALIZED_METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[CANONICALIZED_METADATA_RESPONSE]], 0 +// CHECK-NEXT: call swiftcc void @"$s4main7consumeyyxlF"( +// CHECK-SAME: %swift.opaque* noalias nocapture {{%[0-9]+}}, +// CHECK-SAME: %swift.type* [[CANONICALIZED_METADATA]] +// CHECK-SAME: ) // CHECK: } func doit() { consume( OneArgument(Integer(13)) ) diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_protocol_outmodule_samemodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_protocol_outmodule_samemodule.swift index ed8be0746ef1c..fa2a5a13b909b 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_protocol_outmodule_samemodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_protocol_outmodule_samemodule.swift @@ -2,12 +2,40 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-1argument-1constraint.swift %S/Inputs/protocol-public-empty.swift %S/Inputs/struct-public-nonfrozen-0argument.swift %S/Inputs/struct-public-nonfrozen-0argument-conformance-empty.swift -emit-library -o %t/%target-library-name(Argument) -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios -// CHECK-NOT: @"$s8Argument03OneA0VyAA7IntegerVGMN" = +// CHECK: @"$s8Argument03OneA0VyAA7IntegerVGMN" = linkonce_odr hidden constant <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i8**, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }> <{ +// : i8** getelementptr inbounds ( +// : %swift.vwtable, +// : %swift.vwtable* @" +// CHECK-SAME: $s8Argument03OneA0VyAA7IntegerVGWV +// : ", +// : i32 0, +// : i32 0 +// : ), +// CHECK-SAME: [[INT]] 512, +// : %swift.type_descriptor* @" +// CHECK-SAME: $s8Argument03OneA0VMn +// : ", +// CHECK-SAME: %swift.type* @"$s8Argument7IntegerVN", +// CHECK-SAME: i8** @"$s8Argument7IntegerVAA1PAAWP", +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 {{4|8}}, +// CHECK-SAME: i64 1 +// CHECK-SAME: }>, +// CHECK-SAME: align [[ALIGNMENT]] @inline(never) func consume(_ t: T) { @@ -18,8 +46,31 @@ func consume(_ t: T) { import Argument // CHECK: define hidden swiftcc void @"$s4main4doityyF"() #{{[0-9]+}} { -// CHECK: [[METADATA:%[0-9]+]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s8Argument03OneA0VyAA7IntegerVGMD") -// CHECK: call swiftcc void @"$s4main7consumeyyxlF"(%swift.opaque* noalias nocapture {{%[0-9]+}}, %swift.type* [[METADATA]]) +// CHECK: [[CANONICALIZED_METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @swift_getCanonicalSpecializedMetadata( +// CHECK-SAME: [[INT]] 0, +// CHECK-SAME: %swift.type* getelementptr inbounds ( +// CHECK-SAME: %swift.full_type, +// CHECK-SAME: %swift.full_type* bitcast ( +// CHECK-SAME: <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }>* @"$s8Argument03OneA0VyAA7IntegerVGMN" to %swift.full_type* +// CHECK-SAME: ), +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 1 +// CHECK-SAME: ), +// CHECK-SAME: %swift.type** @"$s8Argument03OneA0VyAA7IntegerVGMJ" +// CHECK-SAME: ) +// CHECK-NEXT: [[CANONICALIZED_METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[CANONICALIZED_METADATA_RESPONSE]], 0 +// CHECK-NEXT: call swiftcc void @"$s4main7consumeyyxlF"( +// CHECK-SAME: %swift.opaque* noalias nocapture {{%[0-9]+}}, +// CHECK-SAME: %swift.type* [[CANONICALIZED_METADATA]] +// CHECK-SAME: ) // CHECK: } func doit() { consume( OneArgument(Integer(13)) ) diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_struct_inmodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_struct_inmodule.swift index 8eb393cff6030..27e8384319d0e 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_struct_inmodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_struct_inmodule.swift @@ -2,7 +2,7 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-1argument-1constraint.swift %S/Inputs/struct-public-nonfrozen-0argument.swift %S/Inputs/protocol-public-empty.swift -emit-library -o %t/%target-library-name(Module) -emit-module -module-name Module -emit-module-path %t/Module.swiftmodule // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s %S/Inputs/main.swift %S/Inputs/struct-public-nonfrozen-0argument-conformance-empty.swift -module-name main -L %t -I %t -lModule -DIMPORT_MODULE | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_struct_outmodule_othermodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_struct_outmodule_othermodule.swift index bf23059dbf86f..274c6720d5d4f 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_struct_outmodule_othermodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_struct_outmodule_othermodule.swift @@ -3,12 +3,48 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-0argument.swift -emit-library -o %t/%target-library-name(Argument) -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios -// CHECK-NOT: @"$s6Module11TwoArgumentVyAA7IntegerV0C0ADVGMN" = +// CHECK: @"$s6Module11TwoArgumentVyAA7IntegerV0C0ADVGMN" = linkonce_odr hidden constant <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// : [ +// : 4 x i8 +// : ], +// CHECK-SAME: i64 +// CHECK-SAME: }> <{ +// : i8** getelementptr inbounds ( +// : %swift.vwtable, +// : %swift.vwtable* @" +// CHECK-SAME: $s6Module11TwoArgumentVyAA7IntegerV0C0ADVGWV +// : ", +// : i32 0, +// : i32 0 +// : ), +// CHECK-SAME: [[INT]] 512, +// : %swift.type_descriptor* @" +// CHECK-SAME: $s6Module11TwoArgumentVMn +// : ", +// CHECK-SAME: %swift.type* @"$s6Module7IntegerVN", +// CHECK-SAME: %swift.type* @"$s8Argument7IntegerVN", +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 {{4|8}}, +// CHECK-SAME: i32 {{8|16}}, +// : [ +// : 4 x i8 +// : ] zeroinitializer, +// CHECK-SAME: i64 1 +// CHECK-SAME: }>, +// CHECK-SAME: align [[ALIGNMENT]] @inline(never) func consume(_ t: T) { @@ -20,8 +56,31 @@ import Module import Argument // CHECK: define hidden swiftcc void @"$s4main4doityyF"() #{{[0-9]+}} { -// CHECK: [[METADATA:%[0-9]+]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s6Module11TwoArgumentVyAA7IntegerV0C0ADVGMD") -// CHECK: call swiftcc void @"$s4main7consumeyyxlF"(%swift.opaque* noalias nocapture {{%[0-9]+}}, %swift.type* [[METADATA]]) +// CHECK: [[CANONICALIZED_METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @swift_getCanonicalSpecializedMetadata( +// CHECK-SAME: [[INT]] 0, +// CHECK-SAME: %swift.type* getelementptr inbounds ( +// CHECK-SAME: %swift.full_type, +// CHECK-SAME: %swift.full_type* bitcast ( +// CHECK-SAME: <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }>* @"$s6Module11TwoArgumentVyAA7IntegerV0C0ADVGMN" to %swift.full_type* +// CHECK-SAME: ), +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 1 +// CHECK-SAME: ), +// CHECK-SAME: %swift.type** @"$s6Module11TwoArgumentVyAA7IntegerV0C0ADVGMJ" +// CHECK-SAME: ) +// CHECK-NEXT: [[CANONICALIZED_METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[CANONICALIZED_METADATA_RESPONSE]], 0 +// CHECK-NEXT: call swiftcc void @"$s4main7consumeyyxlF"( +// CHECK-SAME: %swift.opaque* noalias nocapture {{%[0-9]+}}, +// CHECK-SAME: %swift.type* [[CANONICALIZED_METADATA]] +// CHECK-SAME: ) // CHECK: } func doit() { consume( TwoArgument(Module.Integer(13), Argument.Integer(17)) ) diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_struct_outmodule_samemodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_struct_outmodule_samemodule.swift index b751ee9562f7e..969903ee58540 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_struct_outmodule_samemodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-2argument-1du-1arg_struct_outmodule_samemodule-2arg_struct_outmodule_samemodule.swift @@ -2,12 +2,48 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-2argument.swift %S/Inputs/struct-public-nonfrozen-0argument.swift -emit-library -o %t/%target-library-name(Argument) -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios -// CHECK-NOT: @"$s8Argument03TwoA0VyAA7IntegerVGMN" = +// CHECK: @"$s8Argument03TwoA0VyAA7IntegerVAEGMN" = linkonce_odr hidden constant <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// : [ +// : 4 x i8 +// : ], +// CHECK-SAME: i64 +// CHECK-SAME: }> <{ +// : i8** getelementptr inbounds ( +// : %swift.vwtable, +// : %swift.vwtable* @" +// CHECK-SAME: $s8Argument03TwoA0VyAA7IntegerVAEGWV +// : ", +// : i32 0, +// : i32 0 +// : ), +// CHECK-SAME: [[INT]] 512, +// : %swift.type_descriptor* @" +// CHECK-SAME: $s8Argument03TwoA0VMn +// : ", +// CHECK-SAME: %swift.type* @"$s8Argument7IntegerVN", +// CHECK-SAME: %swift.type* @"$s8Argument7IntegerVN", +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 {{4|8}}, +// CHECK-SAME: i32 {{8|16}}, +// : [ +// : 4 x i8 +// : ] zeroinitializer, +// CHECK-SAME: i64 1 +// CHECK-SAME: }>, +// CHECK-SAME: align [[ALIGNMENT]] @inline(never) func consume(_ t: T) { @@ -18,8 +54,31 @@ func consume(_ t: T) { import Argument // CHECK: define hidden swiftcc void @"$s4main4doityyF"() #{{[0-9]+}} { -// CHECK: [[METADATA:%[0-9]+]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s8Argument03TwoA0VyAA7IntegerVAEGMD") -// CHECK: call swiftcc void @"$s4main7consumeyyxlF"(%swift.opaque* noalias nocapture {{%[0-9]+}}, %swift.type* [[METADATA]]) +// CHECK: [[CANONICALIZED_METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @swift_getCanonicalSpecializedMetadata( +// CHECK-SAME: [[INT]] 0, +// CHECK-SAME: %swift.type* getelementptr inbounds ( +// CHECK-SAME: %swift.full_type, +// CHECK-SAME: %swift.full_type* bitcast ( +// CHECK-SAME: <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }>* @"$s8Argument03TwoA0VyAA7IntegerVAEGMN" to %swift.full_type* +// CHECK-SAME: ), +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 1 +// CHECK-SAME: ), +// CHECK-SAME: %swift.type** @"$s8Argument03TwoA0VyAA7IntegerVAEGMJ" +// CHECK-SAME: ) +// CHECK-NEXT: [[CANONICALIZED_METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[CANONICALIZED_METADATA_RESPONSE]], 0 +// CHECK-NEXT: call swiftcc void @"$s4main7consumeyyxlF"( +// CHECK-SAME: %swift.opaque* noalias nocapture {{%[0-9]+}}, +// CHECK-SAME: %swift.type* [[CANONICALIZED_METADATA]] +// CHECK-SAME: ) // CHECK: } func doit() { consume( TwoArgument(Integer(13), Integer(17)) ) diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-inmodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-inmodule.swift index 1a265a9b0f50e..d7aa427dc3a29 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-inmodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-inmodule.swift @@ -2,7 +2,7 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-frozen-1argument.swift -emit-library -o %t/%target-library-name(Generic) -emit-module -module-name Generic -emit-module-path %t/Generic.swiftmodule -enable-library-evolution // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lGeneric | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-frozen-othermodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-frozen-othermodule.swift index cf8a51c1899c2..7c5fff2d942b0 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-frozen-othermodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-frozen-othermodule.swift @@ -3,12 +3,38 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-frozen-0argument.swift -emit-library -o %t/%target-library-name(Argument) -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule -enable-library-evolution // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lGeneric -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios -// CHECK-NOT: @"$s7Generic11OneArgumentVy0C07IntegerVGMN" = +// CHECK: @"$s7Generic11OneArgumentVy0C07IntegerVGMN" = linkonce_odr hidden constant <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }> <{ +// : i8** getelementptr inbounds ( +// : %swift.vwtable, +// : %swift.vwtable* @" +// CHECK-SAME: $s7Generic11OneArgumentVy0C07IntegerVGWV +// : ", +// : i32 0, +// : i32 0 +// : ), +// CHECK-SAME: [[INT]] 512, +// : %swift.type_descriptor* @" +// CHECK-SAME: $s7Generic11OneArgumentVMn +// : ", +// CHECK-SAME: %swift.type* @"$s8Argument7IntegerVN", +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 {{4|8}}, +// CHECK-SAME: i64 1 +// CHECK-SAME: }>, +// CHECK-SAME: align [[ALIGNMENT]] @inline(never) func consume(_ t: T) { @@ -20,8 +46,31 @@ import Generic import Argument // CHECK: define hidden swiftcc void @"$s4main4doityyF"() #{{[0-9]+}} { -// CHECK: [[METADATA:%[0-9]+]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s7Generic11OneArgumentVy0C07IntegerVGMD") -// CHECK: call swiftcc void @"$s4main7consumeyyxlF"(%swift.opaque* noalias nocapture {{%[0-9]+}}, %swift.type* [[METADATA]]) +// CHECK: [[CANONICALIZED_METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @swift_getCanonicalSpecializedMetadata( +// CHECK-SAME: [[INT]] 0, +// CHECK-SAME: %swift.type* getelementptr inbounds ( +// CHECK-SAME: %swift.full_type, +// CHECK-SAME: %swift.full_type* bitcast ( +// CHECK-SAME: <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }>* @"$s7Generic11OneArgumentVy0C07IntegerVGMN" to %swift.full_type* +// CHECK-SAME: ), +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 1 +// CHECK-SAME: ), +// CHECK-SAME: %swift.type** @"$s7Generic11OneArgumentVy0C07IntegerVGMJ" +// CHECK-SAME: ) +// CHECK-NEXT: [[CANONICALIZED_METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[CANONICALIZED_METADATA_RESPONSE]], 0 +// CHECK-NEXT: call swiftcc void @"$s4main7consumeyyxlF"( +// CHECK-SAME: %swift.opaque* noalias nocapture {{%[0-9]+}}, +// CHECK-SAME: %swift.type* [[CANONICALIZED_METADATA]] +// CHECK-SAME: ) // CHECK: } func doit() { consume( OneArgument(Integer(13)) ) diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-frozen-samemodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-frozen-samemodule.swift index c7f22edd10d3d..c04ed4041ee8b 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-frozen-samemodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-frozen-samemodule.swift @@ -2,12 +2,38 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-frozen-1argument.swift %S/Inputs/struct-public-frozen-0argument.swift -emit-library -o %t/%target-library-name(Generic) -emit-module -module-name Generic -emit-module-path %t/Generic.swiftmodule -enable-library-evolution // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lGeneric | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios -// CHECK-NOT: @"$s7Generic11OneArgumentVyAA7IntegerVGMN" = +// CHECK: @"$s7Generic11OneArgumentVyAA7IntegerVGMN" = linkonce_odr hidden constant <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }> <{ +// : i8** getelementptr inbounds ( +// : %swift.vwtable, +// : %swift.vwtable* @" +// CHECK-SAME: $s7Generic11OneArgumentVyAA7IntegerVGWV +// : ", +// : i32 0, +// : i32 0 +// : ), +// CHECK-SAME: [[INT]] 512, +// : %swift.type_descriptor* @" +// CHECK-SAME: $s7Generic11OneArgumentVMn +// : ", +// CHECK-SAME: %swift.type* @"$s7Generic7IntegerVN", +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 {{4|8}}, +// CHECK-SAME: i64 1 +// CHECK-SAME: }>, +// CHECK-SAME: align [[ALIGNMENT]] @inline(never) func consume(_ t: T) { @@ -18,8 +44,31 @@ func consume(_ t: T) { import Generic // CHECK: define hidden swiftcc void @"$s4main4doityyF"() #{{[0-9]+}} { -// CHECK: [[METADATA:%[0-9]+]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s7Generic11OneArgumentVyAA7IntegerVGMD") -// CHECK: call swiftcc void @"$s4main7consumeyyxlF"(%swift.opaque* noalias nocapture {{%[0-9]+}}, %swift.type* [[METADATA]]) +// CHECK: [[CANONICALIZED_METADATA_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @swift_getCanonicalSpecializedMetadata( +// CHECK-SAME: [[INT]] 0, +// CHECK-SAME: %swift.type* getelementptr inbounds ( +// CHECK-SAME: %swift.full_type, +// CHECK-SAME: %swift.full_type* bitcast ( +// CHECK-SAME: <{ +// CHECK-SAME: i8**, +// CHECK-SAME: [[INT]], +// CHECK-SAME: %swift.type_descriptor*, +// CHECK-SAME: %swift.type*, +// CHECK-SAME: i32, +// CHECK-SAME: i32, +// CHECK-SAME: i64 +// CHECK-SAME: }>* @"$s7Generic11OneArgumentVyAA7IntegerVGMN" to %swift.full_type* +// CHECK-SAME: ), +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 1 +// CHECK-SAME: ), +// CHECK-SAME: %swift.type** @"$s7Generic11OneArgumentVyAA7IntegerVGMJ" +// CHECK-SAME: ) +// CHECK-NEXT: [[CANONICALIZED_METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[CANONICALIZED_METADATA_RESPONSE]], 0 +// CHECK-NEXT: call swiftcc void @"$s4main7consumeyyxlF"( +// CHECK-SAME: %swift.opaque* noalias nocapture {{%[0-9]+}}, +// CHECK-SAME: %swift.type* [[CANONICALIZED_METADATA]] +// CHECK-SAME: ) // CHECK: } func doit() { consume( OneArgument(Integer(13)) ) diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-resilient-othermodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-resilient-othermodule.swift index ea1bea95dedea..f74fe5876a098 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-resilient-othermodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-resilient-othermodule.swift @@ -3,7 +3,7 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-0argument.swift -emit-library -o %t/%target-library-name(Argument) -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule -enable-library-evolution // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lGeneric -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-resilient-samemodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-resilient-samemodule.swift index d22e9c5cd0b6c..996489fc04bce 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-resilient-samemodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-frozen-1argument-1distinct_use-struct-outmodule-resilient-samemodule.swift @@ -2,7 +2,7 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-frozen-1argument.swift %S/Inputs/struct-public-nonfrozen-0argument.swift -emit-library -o %t/%target-library-name(Generic) -emit-module -module-name Generic -emit-module-path %t/Generic.swiftmodule -enable-library-evolution // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lGeneric -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-inmodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-inmodule.swift index 61c1b5ad442c9..6771fb3b0cd83 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-inmodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-inmodule.swift @@ -2,7 +2,7 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-1argument.swift -emit-library -o %t/%target-library-name(Generic) -emit-module -module-name Generic -emit-module-path %t/Generic.swiftmodule -enable-library-evolution // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lGeneric -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-frozen-othermodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-frozen-othermodule.swift index 134583e4f087f..e5208842c7af0 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-frozen-othermodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-frozen-othermodule.swift @@ -3,7 +3,7 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-frozen-0argument.swift -emit-library -o %t/%target-library-name(Argument) -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule -enable-library-evolution // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lGeneric -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-frozen-samemodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-frozen-samemodule.swift index e39afa70a6c25..bba412fdb884c 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-frozen-samemodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-frozen-samemodule.swift @@ -2,7 +2,7 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-1argument.swift %S/Inputs/struct-public-frozen-0argument.swift -emit-library -o %t/%target-library-name(Generic) -emit-module -module-name Generic -emit-module-path %t/Generic.swiftmodule -enable-library-evolution // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lGeneric | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-othermodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-othermodule.swift index 1e22b5a2e2881..40f664a6485c5 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-othermodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-othermodule.swift @@ -3,7 +3,7 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-0argument.swift -emit-library -o %t/%target-library-name(Argument) -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lGeneric -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-resilient-othermodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-resilient-othermodule.swift index 6748988669cfc..30f5516f3e4e0 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-resilient-othermodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-resilient-othermodule.swift @@ -3,7 +3,7 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-0argument.swift -emit-library -o %t/%target-library-name(Argument) -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule -enable-library-evolution // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lGeneric -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios diff --git a/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-resilient-samemodule.swift b/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-resilient-samemodule.swift index 82a8faad31f3a..13e49953570e0 100644 --- a/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-resilient-samemodule.swift +++ b/test/IRGen/prespecialized-metadata/struct-outmodule-resilient-1argument-1distinct_use-struct-outmodule-resilient-samemodule.swift @@ -2,7 +2,7 @@ // RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-1argument.swift %S/Inputs/struct-public-nonfrozen-0argument.swift -emit-library -o %t/%target-library-name(Generic) -emit-module -module-name Generic -emit-module-path %t/Generic.swiftmodule -enable-library-evolution // RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lGeneric | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment -// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu +// REQUIRES: VENDOR=apple || OS=linux-gnu // UNSUPPORTED: CPU=i386 && OS=ios // UNSUPPORTED: CPU=armv7 && OS=ios // UNSUPPORTED: CPU=armv7s && OS=ios diff --git a/test/IRGen/prespecialized-metadata/struct-public-inmodule-1argument-1distinct_use.swift b/test/IRGen/prespecialized-metadata/struct-public-inmodule-1argument-1distinct_use.swift index e02b67617cea8..99d00c6711936 100644 --- a/test/IRGen/prespecialized-metadata/struct-public-inmodule-1argument-1distinct_use.swift +++ b/test/IRGen/prespecialized-metadata/struct-public-inmodule-1argument-1distinct_use.swift @@ -45,14 +45,6 @@ doit() // CHECK: define{{( protected| dllexport)?}} swiftcc %swift.metadata_response @"$s4main5ValueVMa"([[INT]] %0, %swift.type* %1) #{{[0-9]+}} { // CHECK: entry: // CHECK: [[ERASED_TYPE:%[0-9]+]] = bitcast %swift.type* %1 to i8* -// CHECK: br label %[[TYPE_COMPARISON_LABEL:[0-9]+]] -// CHECK: [[TYPE_COMPARISON_LABEL]]: -// CHECK: [[EQUAL_TYPE:%[0-9]+]] = icmp eq i8* bitcast (%swift.type* @"$sSiN" to i8*), [[ERASED_TYPE]] -// CHECK: [[EQUAL_TYPES:%[0-9]+]] = and i1 true, [[EQUAL_TYPE]] -// CHECK: br i1 [[EQUAL_TYPES]], label %[[EXIT_PRESPECIALIZED:[0-9]+]], label %[[EXIT_NORMAL:[0-9]+]] -// CHECK: [[EXIT_PRESPECIALIZED]]: -// CHECK: ret %swift.metadata_response { %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* bitcast (<{ i8**, [[INT]], %swift.type_descriptor*, %swift.type*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVySiGMf" to %swift.full_type*), i32 0, i32 1), [[INT]] 0 } -// CHECK: [[EXIT_NORMAL]]: // CHECK: {{%[0-9]+}} = call swiftcc %swift.metadata_response @__swift_instantiateGenericMetadata([[INT]] %0, i8* [[ERASED_TYPE]], i8* undef, i8* undef, %swift.type_descriptor* bitcast ({{.+}}$s4main5ValueVMn{{.+}} to %swift.type_descriptor*)) #{{[0-9]+}} // CHECK: ret %swift.metadata_response {{%[0-9]+}} // CHECK: } diff --git a/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h b/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h new file mode 100644 index 0000000000000..b03e3530a4968 --- /dev/null +++ b/test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h @@ -0,0 +1,16 @@ +@import Foundation; +@import ctypes; + +#pragma clang assume_nonnull begin + +@interface SlowServer : NSObject +-(void)doSomethingSlow:(NSString *)operation completionHandler:(void (^)(NSInteger))handler; +-(void)doSomethingDangerous:(NSString *)operation completionHandler:(void (^ _Nullable)(NSString *_Nullable, NSError * _Nullable))handler; +-(void)checkAvailabilityWithCompletionHandler:(void (^)(BOOL isAvailable))completionHandler; +-(void)findAnswerAsynchronously:(void (^)(NSString *_Nullable, NSError * _Nullable))handler __attribute__((swift_name("findAnswer(completionHandler:)"))); +-(BOOL)findAnswerFailinglyWithError:(NSError * _Nullable * _Nullable)error completion:(void (^)(NSString *_Nullable, NSError * _Nullable))handler __attribute__((swift_name("findAnswerFailingly(completionHandler:)"))); +-(void)doSomethingFun:(NSString *)operation then:(void (^)(void))completionHandler; +@property(readwrite) void (^completionHandler)(NSInteger); +@end + +#pragma clang assume_nonnull end diff --git a/test/Inputs/clang-importer-sdk/usr/include/module.map b/test/Inputs/clang-importer-sdk/usr/include/module.map index 61b062ab524eb..366101cbbb723 100644 --- a/test/Inputs/clang-importer-sdk/usr/include/module.map +++ b/test/Inputs/clang-importer-sdk/usr/include/module.map @@ -136,3 +136,8 @@ module WinBOOL { header "winbool.h" export * } + +module ObjCConcurrency { + header "ObjCConcurrency.h" + export * +} \ No newline at end of file diff --git a/test/Interop/Cxx/class/type-classification-non-trivial-irgen.swift b/test/Interop/Cxx/class/type-classification-non-trivial-irgen.swift index fcbf32cff73d5..c0a48574a1493 100644 --- a/test/Interop/Cxx/class/type-classification-non-trivial-irgen.swift +++ b/test/Interop/Cxx/class/type-classification-non-trivial-irgen.swift @@ -29,7 +29,6 @@ public func testStructWithCopyConstructorAndValue() -> Bool { // CHECK: [[MEMBER_ELEMENT:%.*]] = getelementptr inbounds %TSo33StructWithCopyConstructorAndValueV, %TSo33StructWithCopyConstructorAndValueV* [[MEMBER]], i32 0, i32 0 // CHECK: [[MEMBER_VALUE:%.*]] = getelementptr inbounds %Ts5Int32V, %Ts5Int32V* [[MEMBER_ELEMENT]], i32 0, i32 0 // CHECK: store i32 42, i32* [[MEMBER_VALUE]] -// CHECK: %obj.member = getelementptr inbounds %TSo42StructWithSubobjectCopyConstructorAndValueV, %TSo42StructWithSubobjectCopyConstructorAndValueV* [[OBJ]], i32 0, i32 0 // CHECK: [[TEMP_MEMBER:%.*]] = getelementptr inbounds %TSo33StructWithCopyConstructorAndValueV, %TSo33StructWithCopyConstructorAndValueV* [[TMP]], i32 0, i32 0 // CHECK: [[TEMP_MEMBER_VALUE:%.*]] = getelementptr inbounds %Ts5Int32V, %Ts5Int32V* [[TEMP_MEMBER]], i32 0, i32 0 // CHECK: [[LHS:%.*]] = load i32, i32* [[TEMP_MEMBER_VALUE]] diff --git a/test/Interop/Cxx/reference/reference.swift b/test/Interop/Cxx/reference/reference.swift index 71d211b04761c..278f06a23281e 100644 --- a/test/Interop/Cxx/reference/reference.swift +++ b/test/Interop/Cxx/reference/reference.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) // RUN: %target-clang -c %S/Inputs/reference.cpp -I %S/Inputs -o %t/reference.o -std=c++17 -// RUN: %target-build-swift %s -I %S/Inputs -o %t/reference %t/reference.o -Xfrontend -enable-cxx-interop -Xcc -std=c++17 +// RUN: %target-build-swift %s -I %S/Inputs -o %t/reference %t/reference.o -Xfrontend -enable-cxx-interop // RUN: %target-codesign %t/reference // RUN: %target-run %t/reference // diff --git a/test/Interop/Cxx/static/constexpr-static-member-var.swift b/test/Interop/Cxx/static/constexpr-static-member-var.swift index e40cddf397282..77f15f321666f 100644 --- a/test/Interop/Cxx/static/constexpr-static-member-var.swift +++ b/test/Interop/Cxx/static/constexpr-static-member-var.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) // RUN: %target-clang -c %S/Inputs/static-member-var.cpp -I %S/Inputs -o %t/static-member-var.o -std=c++17 -// RUN: %target-build-swift %s -I %S/Inputs -o %t/statics %t/static-member-var.o -Xfrontend -enable-cxx-interop -Xcc -std=c++17 +// RUN: %target-build-swift %s -I %S/Inputs -o %t/statics %t/static-member-var.o -Xfrontend -enable-cxx-interop // RUN: %target-codesign %t/statics // RUN: %target-run %t/statics // diff --git a/test/Interop/Cxx/static/inline-static-member-var.swift b/test/Interop/Cxx/static/inline-static-member-var.swift index 76e7a1d9b09f0..052f362840329 100644 --- a/test/Interop/Cxx/static/inline-static-member-var.swift +++ b/test/Interop/Cxx/static/inline-static-member-var.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) // RUN: %target-clang -c %S/Inputs/inline-static-member-var.cpp -I %S/Inputs -o %t/inline-static-member-var.o -std=c++17 -// RUN: %target-build-swift %s -I %S/Inputs -o %t/statics %t/inline-static-member-var.o -Xfrontend -enable-cxx-interop -Xcc -std=c++17 +// RUN: %target-build-swift %s -I %S/Inputs -o %t/statics %t/inline-static-member-var.o -Xfrontend -enable-cxx-interop // RUN: %target-codesign %t/statics // RUN: %target-run %t/statics 2&>1 // diff --git a/test/Interop/Cxx/static/static-var.swift b/test/Interop/Cxx/static/static-var.swift index 0528af17f35a2..9b66cadf22501 100644 --- a/test/Interop/Cxx/static/static-var.swift +++ b/test/Interop/Cxx/static/static-var.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) // RUN: %target-clang -c %S/Inputs/static-var.cpp -I %S/Inputs -o %t/static-var.o -std=c++17 -// RUN: %target-build-swift %s -I %S/Inputs -o %t/statics %t/static-var.o -Xfrontend -enable-cxx-interop -Xcc -std=c++17 +// RUN: %target-build-swift %s -I %S/Inputs -o %t/statics %t/static-var.o -Xfrontend -enable-cxx-interop // RUN: %target-codesign %t/statics // RUN: %target-run %t/statics // diff --git a/test/Interop/Cxx/templates/Inputs/canonical-types.h b/test/Interop/Cxx/templates/Inputs/canonical-types.h new file mode 100644 index 0000000000000..865c85a882cf9 --- /dev/null +++ b/test/Interop/Cxx/templates/Inputs/canonical-types.h @@ -0,0 +1,18 @@ +#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_CANONICAL_TYPES_H +#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_CANONICAL_TYPES_H + +template +struct MagicWrapper { + T t; + int getValuePlusArg(int arg) const { return t.getValue() + arg; } +}; + +struct IntWrapper { + int value; + int getValue() const { return value; } +}; + +typedef MagicWrapper WrappedMagicNumberA; +typedef MagicWrapper WrappedMagicNumberB; + +#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_CANONICAL_TYPES_H diff --git a/test/Interop/Cxx/templates/Inputs/decl-with-definition-including-members.h b/test/Interop/Cxx/templates/Inputs/decl-with-definition-including-members.h new file mode 100644 index 0000000000000..4c772c9dfaca0 --- /dev/null +++ b/test/Interop/Cxx/templates/Inputs/decl-with-definition-including-members.h @@ -0,0 +1,26 @@ +#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_INCLUDING_MEMBERS_H +#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_INCLUDING_MEMBERS_H + +template +struct MagicWrapper { + T t; + int getValuePlusArg(int arg) const { return t.getValue() + arg; } +}; + +struct IntWrapper { + int value; + int getValue() const { return value; } +}; + +inline int forceInstantiation() { + auto t = MagicWrapper(); + return t.getValuePlusArg(14); +} + +// The ClassTemplateSpecializationDecl node for MagicWrapper already has a definition +// because function above forced the instantiation. Its members are fully +// instantiated, so nothing needs to be explicitly instantiated by the Swift +// compiler. +typedef MagicWrapper FullyDefinedMagicallyWrappedInt; + +#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_INCLUDING_MEMBERS_H diff --git a/test/Interop/Cxx/templates/Inputs/decl-with-definition.h b/test/Interop/Cxx/templates/Inputs/decl-with-definition.h new file mode 100644 index 0000000000000..d8fb7b56f676b --- /dev/null +++ b/test/Interop/Cxx/templates/Inputs/decl-with-definition.h @@ -0,0 +1,24 @@ +#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_H +#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_H + +template +struct MagicWrapper { + T t; + int getValuePlusArg(int arg) const { return t.getValue() + arg; } +}; + +struct IntWrapper { + int value; + int getValue() const { return value; } +}; + +inline MagicWrapper forceInstantiation() { + return MagicWrapper(); +} + +// The ClassTemplateSpecializationDecl node for MagicWrapper already has a definition +// because function above forced the instantiation. Its members are not +// instantiated though, the Swift compiler needs to instantiate them. +typedef MagicWrapper PartiallyDefinedMagicallyWrappedInt; + +#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_H diff --git a/test/Interop/Cxx/templates/Inputs/decl-with-primitive-argument.h b/test/Interop/Cxx/templates/Inputs/decl-with-primitive-argument.h new file mode 100644 index 0000000000000..2bba7d493e342 --- /dev/null +++ b/test/Interop/Cxx/templates/Inputs/decl-with-primitive-argument.h @@ -0,0 +1,12 @@ +#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_PRIMITIVE_ARGUMENT_H +#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_PRIMITIVE_ARGUMENT_H + +template +struct MagicWrapper { + T t; + int getValuePlusArg(int arg) const { return t + arg; } +}; + +typedef MagicWrapper WrappedMagicInt; + +#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_PRIMITIVE_ARGUMENT_H diff --git a/test/Interop/Cxx/templates/Inputs/decl-without-definition.h b/test/Interop/Cxx/templates/Inputs/decl-without-definition.h new file mode 100644 index 0000000000000..a4eb3506672b2 --- /dev/null +++ b/test/Interop/Cxx/templates/Inputs/decl-without-definition.h @@ -0,0 +1,20 @@ +#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITHOUT_DEFINITION_H +#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITHOUT_DEFINITION_H + +template +struct MagicWrapper { + T t; + int getValuePlusArg(int arg) const { return t.getValue() + arg; } +}; + +struct IntWrapper { + int value; + int getValue() const { return value; } +}; + +// The ClassTemplateSpecializationDecl node for MagicWrapper doesn't have a +// definition in Clang because nothing in this header required the +// instantiation. Therefore, the Swift compiler must trigger instantiation. +typedef MagicWrapper MagicallyWrappedIntWithoutDefinition; + +#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITHOUT_DEFINITION_H diff --git a/test/Interop/Cxx/templates/Inputs/eager-instantiation-problems.h b/test/Interop/Cxx/templates/Inputs/eager-instantiation-problems.h new file mode 100644 index 0000000000000..5992054ae9d3d --- /dev/null +++ b/test/Interop/Cxx/templates/Inputs/eager-instantiation-problems.h @@ -0,0 +1,24 @@ +#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_EAGER_INSTANTIATION_PROBLEMS_H +#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_EAGER_INSTANTIATION_PROBLEMS_H + +struct MagicNumber { + int getInt() const { return 42; } +}; + +template +struct MagicWrapper { + void callGetInt() const { + T::getIntDoesNotExist(); + } + + template int sfinaeGetInt(A a, decltype(&A::getInt)) { + return a.getInt(); + } + template int sfinaeGetInt(A a, ...) { + return -42; + } +}; + +typedef MagicWrapper BrokenMagicWrapper; + +#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_EAGER_INSTANTIATION_PROBLEMS_H diff --git a/test/Interop/Cxx/templates/Inputs/explicit-specialization.h b/test/Interop/Cxx/templates/Inputs/explicit-specialization.h new file mode 100644 index 0000000000000..62b9f7aa030af --- /dev/null +++ b/test/Interop/Cxx/templates/Inputs/explicit-specialization.h @@ -0,0 +1,29 @@ +#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_EXPLICIT_SPECIALIZATION_H +#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_EXPLICIT_SPECIALIZATION_H + +struct SpecializedIntWrapper { + int value; + int getValue() const { return value; } +}; + +struct NonSpecializedIntWrapper { + int value; + int getValue() const { return value; } +}; + +template +struct MagicWrapper { + T t; + int doubleIfSpecializedElseTriple() const { return 3 * t.getValue(); } +}; + +template <> +struct MagicWrapper { + SpecializedIntWrapper t; + int doubleIfSpecializedElseTriple() const { return 2 * t.getValue(); } +}; + +typedef MagicWrapper WrapperWithSpecialization; +typedef MagicWrapper WrapperWithoutSpecialization; + +#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_EXPLICIT_SPECIALIZATION_H diff --git a/test/Interop/Cxx/templates/Inputs/linkage-of-swift-symbols-for-imported-types.h b/test/Interop/Cxx/templates/Inputs/linkage-of-swift-symbols-for-imported-types.h new file mode 100644 index 0000000000000..d700209d93873 --- /dev/null +++ b/test/Interop/Cxx/templates/Inputs/linkage-of-swift-symbols-for-imported-types.h @@ -0,0 +1,21 @@ +#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_LINKAGE_OF_SWIFT_SYMBOLS_FOR_IMPORTED_TYPES_H +#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_LINKAGE_OF_SWIFT_SYMBOLS_FOR_IMPORTED_TYPES_H + +template +struct MagicWrapper { + T t; + int callGetInt() const { + return t.getInt() + 5; + } +}; + +struct MagicNumber { + // Swift runtime defines many value witness tables for types with some common layouts. + // This struct's uncommon size forces the compiler to define a new value witness table instead of reusing one from the runtime. + char forceVWTableCreation[57]; + int getInt() const { return 12; } +}; + +typedef MagicWrapper WrappedMagicNumber; + +#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_LINKAGE_OF_SWIFT_SYMBOLS_FOR_IMPORTED_TYPES_H diff --git a/test/Interop/Cxx/templates/Inputs/mangling.h b/test/Interop/Cxx/templates/Inputs/mangling.h new file mode 100644 index 0000000000000..f135b52747600 --- /dev/null +++ b/test/Interop/Cxx/templates/Inputs/mangling.h @@ -0,0 +1,11 @@ +#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_MANGLING_H +#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_MANGLING_H + +template +struct MagicWrapper {}; + +typedef MagicWrapper WrappedMagicInt; +typedef MagicWrapper WrappedMagicBool; + + +#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_MANGLING_H diff --git a/test/Interop/Cxx/templates/Inputs/module.modulemap b/test/Interop/Cxx/templates/Inputs/module.modulemap new file mode 100644 index 0000000000000..af6d28e675a40 --- /dev/null +++ b/test/Interop/Cxx/templates/Inputs/module.modulemap @@ -0,0 +1,39 @@ +module DeclWithPrimitiveArgument { + header "decl-with-primitive-argument.h" +} + +module DeclWithoutDefinition { + header "decl-without-definition.h" +} + +module DeclWithDefinition { + header "decl-with-definition.h" +} + +module DeclWithDefinitionIncludingMembers { + header "decl-with-definition-including-members.h" +} + +module CanonicalTypes { + header "canonical-types.h" +} + +module ExplicitSpecialization { + header "explicit-specialization.h" +} + +module UsingDirective { + header "using-directive.h" +} + +module EagerInstantiationProblems { + header "eager-instantiation-problems.h" +} + +module Mangling { + header "mangling.h" +} + +module LinkageOfSwiftSymbolsForImportedTypes { + header "linkage-of-swift-symbols-for-imported-types.h" +} diff --git a/test/Interop/Cxx/templates/Inputs/using-directive.h b/test/Interop/Cxx/templates/Inputs/using-directive.h new file mode 100644 index 0000000000000..076660e8a19e4 --- /dev/null +++ b/test/Interop/Cxx/templates/Inputs/using-directive.h @@ -0,0 +1,17 @@ +#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_USING_DIRECTIVE_H +#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_USING_DIRECTIVE_H + +template +struct MagicWrapper { + T t; + int getValuePlusArg(int arg) const { return t.getValue() + arg; } +}; + +struct IntWrapper { + int value; + int getValue() const { return value; } +}; + +using UsingWrappedMagicNumber = MagicWrapper; + +#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_USING_DIRECTIVE_H diff --git a/test/Interop/Cxx/templates/canonical-types-module-interface.swift b/test/Interop/Cxx/templates/canonical-types-module-interface.swift new file mode 100644 index 0000000000000..3a90d1d44311a --- /dev/null +++ b/test/Interop/Cxx/templates/canonical-types-module-interface.swift @@ -0,0 +1,15 @@ +// RUN: %target-swift-ide-test -print-module -module-to-print=CanonicalTypes -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s + +// CHECK: struct __CxxTemplateInst12MagicWrapperI10IntWrapperE { +// CHECK: var t: IntWrapper +// CHECK: init() +// CHECK: init(t: IntWrapper) +// CHECK: mutating func getValuePlusArg(_ arg: Int32) -> Int32 +// CHECK: } +// CHECK: struct IntWrapper { +// CHECK: var value: Int32 +// CHECK: init() +// CHECK: mutating func getValue() -> Int32 +// CHECK: } +// CHECK: typealias WrappedMagicNumberA = __CxxTemplateInst12MagicWrapperI10IntWrapperE +// CHECK: typealias WrappedMagicNumberB = __CxxTemplateInst12MagicWrapperI10IntWrapperE diff --git a/test/Interop/Cxx/templates/canonical-types.swift b/test/Interop/Cxx/templates/canonical-types.swift new file mode 100644 index 0000000000000..6f11ea61ca8e5 --- /dev/null +++ b/test/Interop/Cxx/templates/canonical-types.swift @@ -0,0 +1,15 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import CanonicalTypes +import StdlibUnittest + +var TemplatesTestSuite = TestSuite("TemplatesTestSuite") + +TemplatesTestSuite.test("canonical-types") { + // Different typedefs with the same C++ canonical type must have the same type from Swift's perspective as well. + expectEqualType(WrappedMagicNumberA.self, WrappedMagicNumberB.self) +} + +runAllTests() diff --git a/test/Interop/Cxx/templates/decl-with-definition-including-members.swift b/test/Interop/Cxx/templates/decl-with-definition-including-members.swift new file mode 100644 index 0000000000000..8c7dcf7013557 --- /dev/null +++ b/test/Interop/Cxx/templates/decl-with-definition-including-members.swift @@ -0,0 +1,16 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import DeclWithDefinitionIncludingMembers +import StdlibUnittest + +var TemplatesTestSuite = TestSuite("TemplatesTestSuite") + +TemplatesTestSuite.test("fully-defined") { + let myInt = IntWrapper(value: 10) + var magicInt = FullyDefinedMagicallyWrappedInt(t: myInt) + expectEqual(magicInt.getValuePlusArg(5), 15) +} + +runAllTests() diff --git a/test/Interop/Cxx/templates/decl-with-definition-irgen.swift b/test/Interop/Cxx/templates/decl-with-definition-irgen.swift new file mode 100644 index 0000000000000..d69ece5914b55 --- /dev/null +++ b/test/Interop/Cxx/templates/decl-with-definition-irgen.swift @@ -0,0 +1,33 @@ +// RUN: %target-swift-emit-ir %s -I %S/Inputs -enable-cxx-interop | %FileCheck %s +// REQUIRES: rdar67257133 +import DeclWithDefinition + +public func getWrappedMagicInt() -> CInt { + let myInt = IntWrapper(value: 7) + var magicInt = PartiallyDefinedMagicallyWrappedInt(t: myInt) + return magicInt.getValuePlusArg(13) +} + +// CHECK: define {{(protected |dllexport )?}}swiftcc i32 @"$s4main18getWrappedMagicInts5Int32VyF"() +// CHECK: %magicInt = alloca %TSo037__CxxTemplateInst12MagicWrapperI10IntE1EV, align 4 +// CHECK: %magicInt.t = getelementptr inbounds %TSo037__CxxTemplateInst12MagicWrapperI10IntE1EV, %TSo037__CxxTemplateInst12MagicWrapperI10IntE1EV* %magicInt, i32 0, i32 0 +// CHECK: [[MAGIC_WRAPPER:%.*]] = bitcast %TSo037__CxxTemplateInst12MagicWrapperI10IntE1EV* %magicInt to %struct.MagicWrapper* +// CHECK: call i32 @{{_ZNK12MagicWrapperI10IntWrapperE15getValuePlusArgEi|"\?getValuePlusArg@\?\$MagicWrapper@UIntWrapper@@@@QEBAHH@Z"}}(%struct.MagicWrapper* [[MAGIC_WRAPPER]], i32 13) + +// CHECK: define weak_odr{{( dso_local)?}} i32 @{{_ZNK12MagicWrapperI10IntWrapperE15getValuePlusArgEi|"\?getValuePlusArg@\?\$MagicWrapper@UIntWrapper@@@@QEBAHH@Z"}}(%struct.MagicWrapper* %this, i32 %arg) +// CHECK: %this.addr = alloca %struct.MagicWrapper*, align {{4|8}} +// CHECK: store %struct.MagicWrapper* %this, %struct.MagicWrapper** %this.addr, align {{4|8}} +// CHECK: %this1 = load %struct.MagicWrapper*, %struct.MagicWrapper** %this.addr, align {{4|8}} +// CHECK: %t = getelementptr inbounds %struct.MagicWrapper, %struct.MagicWrapper* %this1, i32 0, i32 0 +// CHECK: %call = call i32 @{{_ZNK10IntWrapper8getValueEv|"\?getValue@IntWrapper@@QEBAHXZ"}}(%struct.IntWrapper* %t) +// CHECK: [[ARG:%.*]] = load i32, i32* %arg.addr, align 4 +// CHECK: %add = add nsw i32 %call, [[ARG]] +// CHECK: ret i32 %add + +// CHECK: define linkonce_odr{{( dso_local)?}} i32 @{{_ZNK10IntWrapper8getValueEv|"\?getValue@IntWrapper@@QEBAHXZ"}}(%struct.IntWrapper* %this) +// CHECK: %this.addr = alloca %struct.IntWrapper*, align {{4|8}} +// CHECK: store %struct.IntWrapper* %this, %struct.IntWrapper** %this.addr, align {{4|8}} +// CHECK: %this1 = load %struct.IntWrapper*, %struct.IntWrapper** %this.addr, align {{4|8}} +// CHECK: %value = getelementptr inbounds %struct.IntWrapper, %struct.IntWrapper* %this1, i32 0, i32 0 +// CHECK: [[VALUE:%.*]] = load i32, i32* %value, align 4 +// CHECK: ret i32 [[VALUE]] diff --git a/test/Interop/Cxx/templates/decl-with-definition-silgen.swift b/test/Interop/Cxx/templates/decl-with-definition-silgen.swift new file mode 100644 index 0000000000000..a9481f6ac9d6c --- /dev/null +++ b/test/Interop/Cxx/templates/decl-with-definition-silgen.swift @@ -0,0 +1,21 @@ +// RUN: %target-swift-emit-sil %s -I %S/Inputs -enable-cxx-interop | %FileCheck %s + +import DeclWithDefinition + +public func getWrappedMagicInt() -> CInt { + let myInt = IntWrapper(value: 21) + var magicInt = PartiallyDefinedMagicallyWrappedInt(t: myInt) + return magicInt.getValuePlusArg(32) +} + +// CHECK: // getWrappedMagicInt() +// CHECK: sil @$s4main18getWrappedMagicInts5Int32VyF : $@convention(thin) () -> Int32 { +// CHECK: [[INT_WRAPPER:%.*]] = struct $IntWrapper ([[_:%.*]] : $Int32) +// CHECK: [[_:%.*]] = struct $__CxxTemplateInst12MagicWrapperI10IntWrapperE ([[INT_WRAPPER]] : $IntWrapper) +// CHECK: // function_ref {{_ZNK12MagicWrapperI10IntWrapperE15getValuePlusArgEi|\?getValuePlusArg@\?\$MagicWrapper@UIntWrapper@@@@QEBAHH@Z}} +// CHECK: [[_:%.*]] = function_ref @{{_ZNK12MagicWrapperI10IntWrapperE15getValuePlusArgEi|\?getValuePlusArg@\?\$MagicWrapper@UIntWrapper@@@@QEBAHH@Z}} : $@convention(c) (@inout __CxxTemplateInst12MagicWrapperI10IntWrapperE, Int32) -> Int32 + +// CHECK: // {{_ZNK12MagicWrapperI10IntWrapperE15getValuePlusArgEi|\?getValuePlusArg@\?\$MagicWrapper@UIntWrapper@@@@QEBAHH@Z}} +// CHECK: MagicWrapper::getValuePlusArg + +// CHECK: sil [clang __CxxTemplateInst12MagicWrapperI10IntWrapperE.getValuePlusArg] @{{_ZNK12MagicWrapperI10IntWrapperE15getValuePlusArgEi|\?getValuePlusArg@\?\$MagicWrapper@UIntWrapper@@@@QEBAHH@Z}} : $@convention(c) (@inout __CxxTemplateInst12MagicWrapperI10IntWrapperE, Int32) -> Int32 diff --git a/test/Interop/Cxx/templates/decl-with-definition.swift b/test/Interop/Cxx/templates/decl-with-definition.swift new file mode 100644 index 0000000000000..3772cd4f7a99a --- /dev/null +++ b/test/Interop/Cxx/templates/decl-with-definition.swift @@ -0,0 +1,16 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import DeclWithDefinition +import StdlibUnittest + +var TemplatesTestSuite = TestSuite("TemplatesTestSuite") + +TemplatesTestSuite.test("has-partial-definition") { + let myInt = IntWrapper(value: 32) + var magicInt = PartiallyDefinedMagicallyWrappedInt(t: myInt) + expectEqual(magicInt.getValuePlusArg(5), 37) +} + +runAllTests() diff --git a/test/Interop/Cxx/templates/decl-with-primitive-argument.swift b/test/Interop/Cxx/templates/decl-with-primitive-argument.swift new file mode 100644 index 0000000000000..951c49c0fb814 --- /dev/null +++ b/test/Interop/Cxx/templates/decl-with-primitive-argument.swift @@ -0,0 +1,15 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import DeclWithPrimitiveArgument +import StdlibUnittest + +var TemplatesTestSuite = TestSuite("TemplatesTestSuite") + +TemplatesTestSuite.test("int-argument") { + var wrappedMagicInt = WrappedMagicInt(t: 42) + expectEqual(wrappedMagicInt.getValuePlusArg(5), 47) +} + +runAllTests() diff --git a/test/Interop/Cxx/templates/decl-without-definition-module-interface.swift b/test/Interop/Cxx/templates/decl-without-definition-module-interface.swift new file mode 100644 index 0000000000000..ca12841f96cb9 --- /dev/null +++ b/test/Interop/Cxx/templates/decl-without-definition-module-interface.swift @@ -0,0 +1,15 @@ +// RUN: %target-swift-ide-test -print-module -module-to-print=DeclWithoutDefinition -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s + +// CHECK: struct __CxxTemplateInst12MagicWrapperI10IntWrapperE { +// CHECK: var t: IntWrapper +// CHECK: init() +// CHECK: init(t: IntWrapper) +// CHECK: mutating func getValuePlusArg(_ arg: Int32) -> Int32 +// CHECK: } +// CHECK: struct IntWrapper { +// CHECK: var value: Int32 +// CHECK: init() +// CHECK: init(value: Int32) +// CHECK: mutating func getValue() -> Int32 +// CHECK: } +// CHECK: typealias MagicallyWrappedIntWithoutDefinition = __CxxTemplateInst12MagicWrapperI10IntWrapperE diff --git a/test/Interop/Cxx/templates/decl-without-definition.swift b/test/Interop/Cxx/templates/decl-without-definition.swift new file mode 100644 index 0000000000000..23eca83c31d85 --- /dev/null +++ b/test/Interop/Cxx/templates/decl-without-definition.swift @@ -0,0 +1,16 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import DeclWithoutDefinition +import StdlibUnittest + +var TemplatesTestSuite = TestSuite("TemplatesTestSuite") + +TemplatesTestSuite.test("without-definition") { + let myInt = IntWrapper(value: 17) + var magicInt = MagicallyWrappedIntWithoutDefinition(t: myInt) + expectEqual(magicInt.getValuePlusArg(11), 28) +} + +runAllTests() diff --git a/test/Interop/Cxx/templates/eager-instatiation-problems.swift b/test/Interop/Cxx/templates/eager-instatiation-problems.swift new file mode 100644 index 0000000000000..f341c8c68c87c --- /dev/null +++ b/test/Interop/Cxx/templates/eager-instatiation-problems.swift @@ -0,0 +1,32 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import EagerInstantiationProblems +import StdlibUnittest + +var TemplatesTestSuite = TestSuite("TemplatesTestSuite") + +TemplatesTestSuite.test("eager-instantiation-of-members") { + // This will fail with: + // + // error: type 'int' cannot be used prior to '::' because it has no members + // T::getIntDoesNotExist(); + // + // whereas in C++ this compiles. This is caused by ClangImporter eagerly + // instantiating typedeffed templates and also their members. + // TODO(scentini): Fix this + // let _brokenMagicWrapper = BrokenMagicWrapper() +} + +TemplatesTestSuite.test("sfinae-example") { + // This will fail since we are currently not instantiating function templates. + // In C++ the first sfinaeGetInt should fail to instantiate, therefore get + // ignored, and only the second sfinaeGetInt is used. + // TODO(SR-12541): Fix this + // let magicNumber = MagicNumber() + // var brokenMagicWrapper = BrokenMagicWrapper() + // expectEqual(42, brokenMagicWrapper.sfinaeGetInt(magicNumber, 0)) +} + +runAllTests() diff --git a/test/Interop/Cxx/templates/explicit-specialization.swift b/test/Interop/Cxx/templates/explicit-specialization.swift new file mode 100644 index 0000000000000..b8e02faefe85b --- /dev/null +++ b/test/Interop/Cxx/templates/explicit-specialization.swift @@ -0,0 +1,20 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import ExplicitSpecialization +import StdlibUnittest + +var TemplatesTestSuite = TestSuite("TemplatesTestSuite") + +TemplatesTestSuite.test("explicit-specialization") { + let specializedInt = SpecializedIntWrapper(value: 7) + var specializedMagicInt = WrapperWithSpecialization(t: specializedInt) + expectEqual(specializedMagicInt.doubleIfSpecializedElseTriple(), 14) + + let nonSpecializedInt = NonSpecializedIntWrapper(value: 7) + var nonSpecializedMagicInt = WrapperWithoutSpecialization(t: nonSpecializedInt) + expectEqual(nonSpecializedMagicInt.doubleIfSpecializedElseTriple(), 21) +} + +runAllTests() diff --git a/test/Interop/Cxx/templates/linkage-of-swift-symbols-for-imported-types-irgen.swift b/test/Interop/Cxx/templates/linkage-of-swift-symbols-for-imported-types-irgen.swift new file mode 100644 index 0000000000000..f3a2ae75d69ba --- /dev/null +++ b/test/Interop/Cxx/templates/linkage-of-swift-symbols-for-imported-types-irgen.swift @@ -0,0 +1,28 @@ +// RUN: %target-swift-emit-ir %s -I %S/Inputs -enable-cxx-interop | %FileCheck %s + +import LinkageOfSwiftSymbolsForImportedTypes + +public func forceValueWitnessTableCreation() -> Any { + let magicNumber = MagicNumber() + return WrappedMagicNumber(t: magicNumber) +} + +public func getMagicNumberForLinkageComparison() -> Any { + return MagicNumber() +} + +// CHECK: $sSo11MagicNumberVWV" = linkonce_odr hidden constant +// CHECK: $sSo11MagicNumberVMn" = linkonce_odr hidden constant +// CHECK: $sSo11MagicNumberVMf" = linkonce_odr hidden constant +// CHECK: $sSo11MagicNumberVML" = linkonce_odr hidden global + +// CHECK: $sSo034__CxxTemplateInst12MagicWrapperI11D7NumberEVWV" = linkonce_odr hidden constant +// CHECK: $sSo034__CxxTemplateInst12MagicWrapperI11D7NumberEVMn" = linkonce_odr hidden constant +// CHECK: $sSo034__CxxTemplateInst12MagicWrapperI11D7NumberEVMf" = linkonce_odr hidden constant +// CHECK: $sSo034__CxxTemplateInst12MagicWrapperI11D7NumberEVML" = linkonce_odr hidden global + +// CHECK: $sSo11MagicNumberVMB" = linkonce_odr hidden constant +// CHECK: $sSo11MagicNumberVMF" = linkonce_odr hidden constant + +// CHECK: $sSo034__CxxTemplateInst12MagicWrapperI11D7NumberEVMB" = linkonce_odr hidden constant +// CHECK: $sSo034__CxxTemplateInst12MagicWrapperI11D7NumberEVMF" = linkonce_odr hidden constant diff --git a/test/Interop/Cxx/templates/mangling-irgen.swift b/test/Interop/Cxx/templates/mangling-irgen.swift new file mode 100644 index 0000000000000..c55feb8b5dc47 --- /dev/null +++ b/test/Interop/Cxx/templates/mangling-irgen.swift @@ -0,0 +1,20 @@ +// RUN: %target-swift-emit-ir %s -I %S/Inputs -enable-cxx-interop | %FileCheck %s + +import Mangling + +public func receiveInstantiation(_ i: inout WrappedMagicInt) {} + +// Don't forget to update manglings.txt when changing s4main20receiveInstantiationyySo34__CxxTemplateInst12MagicWrapperIiEVzF +// CHECK: define {{(protected |dllexport )?}}swiftcc void @"$s4main20receiveInstantiationyySo34__CxxTemplateInst12MagicWrapperIiEVzF"(%TSo34__CxxTemplateInst12MagicWrapperIiEV* nocapture dereferenceable(1) %0) + +public func receiveInstantiation(_ i: inout WrappedMagicBool) {} + +// CHECK: define {{(protected |dllexport )?}}swiftcc void @"$s4main20receiveInstantiationyySo34__CxxTemplateInst12MagicWrapperIbEVzF"(%TSo34__CxxTemplateInst12MagicWrapperIbEV* nocapture dereferenceable(1) %0) + +public func returnInstantiation() -> WrappedMagicInt { + return WrappedMagicInt() +} + +// Don't forget to update manglings.txt when changing s4main19returnInstantiationSo34__CxxTemplateInst12MagicWrapperIiEVyF +// CHECK: define {{(protected |dllexport )?}}swiftcc void @"$s4main19returnInstantiationSo34__CxxTemplateInst12MagicWrapperIiEVyF"() + diff --git a/test/Interop/Cxx/templates/mangling-silgen.swift b/test/Interop/Cxx/templates/mangling-silgen.swift new file mode 100644 index 0000000000000..7d4cc6f7e3c39 --- /dev/null +++ b/test/Interop/Cxx/templates/mangling-silgen.swift @@ -0,0 +1,20 @@ +// RUN: %target-swift-emit-sil %s -I %S/Inputs -enable-cxx-interop | %FileCheck %s + +import Mangling + +public func recvInstantiation(_ i: inout WrappedMagicInt) {} + +// CHECK: // recvInstantiation(_:) +// CHECK: sil @$s4main17recvInstantiationyySo34__CxxTemplateInst12MagicWrapperIiEVzF : $@convention(thin) (@inout __CxxTemplateInst12MagicWrapperIiE) -> () + +public func recvInstantiation(_ i: inout WrappedMagicBool) {} + +// CHECK: // recvInstantiation(_:) +// CHECK: sil @$s4main17recvInstantiationyySo34__CxxTemplateInst12MagicWrapperIbEVzF : $@convention(thin) (@inout __CxxTemplateInst12MagicWrapperIbE) -> () + +public func returnInstantiation() -> WrappedMagicInt { + return WrappedMagicInt() +} + +// CHECK: // returnInstantiation() +// CHECK: sil @$s4main19returnInstantiationSo34__CxxTemplateInst12MagicWrapperIiEVyF : $@convention(thin) () -> __CxxTemplateInst12MagicWrapperIiE diff --git a/test/Interop/Cxx/templates/using-directive-module-interface.swift b/test/Interop/Cxx/templates/using-directive-module-interface.swift new file mode 100644 index 0000000000000..81b445d21e3d7 --- /dev/null +++ b/test/Interop/Cxx/templates/using-directive-module-interface.swift @@ -0,0 +1,15 @@ +// RUN: %target-swift-ide-test -print-module -module-to-print=UsingDirective -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s + +// CHECK: struct __CxxTemplateInst12MagicWrapperI10IntWrapperE { +// CHECK: var t: IntWrapper +// CHECK: init() +// CHECK: init(t: IntWrapper) +// CHECK: mutating func getValuePlusArg(_ arg: Int32) -> Int32 +// CHECK: } +// CHECK: struct IntWrapper { +// CHECK: var value: Int32 +// CHECK: init() +// CHECK: init(value: Int32) +// CHECK: mutating func getValue() -> Int32 +// CHECK: } +// CHECK: typealias UsingWrappedMagicNumber = __CxxTemplateInst12MagicWrapperI10IntWrapperE diff --git a/test/Interop/Cxx/templates/using-directive.swift b/test/Interop/Cxx/templates/using-directive.swift new file mode 100644 index 0000000000000..3bae7a8454b33 --- /dev/null +++ b/test/Interop/Cxx/templates/using-directive.swift @@ -0,0 +1,16 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import StdlibUnittest +import UsingDirective + +var TemplatesTestSuite = TestSuite("TemplatesTestSuite") + +TemplatesTestSuite.test("using-directive") { + let myInt = IntWrapper(value: 333) + var magicInt = UsingWrappedMagicNumber(t: myInt) + expectEqual(magicInt.getValuePlusArg(111), 444) +} + +runAllTests() diff --git a/test/Interpreter/SDK/protocol_lookup_foreign.swift b/test/Interpreter/SDK/protocol_lookup_foreign.swift index e0836c4cfa31d..f0565dc042a65 100644 --- a/test/Interpreter/SDK/protocol_lookup_foreign.swift +++ b/test/Interpreter/SDK/protocol_lookup_foreign.swift @@ -1,4 +1,4 @@ -// RUN: %target-run-simple-swift | %FileCheck %s +// RUN: %target-run-simple-swift // REQUIRES: executable_test // REQUIRES: objc_interop @@ -10,38 +10,62 @@ // XFAIL: swift_test_mode_optimize_unchecked import Foundation +import StdlibUnittest protocol Fooable { - func foo() + func foo() -> String } -func fooify(_ x: T) { +func fooify(_ x: T) -> String { if let foo = x as? Fooable { - foo.foo() + return foo.foo() } else { - print("not fooable") + return "not fooable" } } extension NSRect: Fooable { - func foo() { print("NSRect") } + func foo() -> String { return "NSRect" } } extension CFSet: Fooable { - func foo() { print("CFSet") } + func foo() -> String { return "CFSet" } } extension NSString: Fooable { - func foo() { print("NSString") } + func foo() -> String { return "NSString" } } -fooify(NSRect()) // CHECK: NSRect -fooify(NSPoint()) // CHECK-NEXT: not fooable -// FIXME: CF types get their ObjC class dynamically looked up during dynamic -// casting. -fooify(CFSetCreate(kCFAllocatorDefault, nil, 0, nil)!) // TODO-NEXT: CFSet CHECK-NEXT: not fooable -fooify(CFArrayCreate(kCFAllocatorDefault, nil, 0, nil)!) // CHECK-NEXT: not fooable -fooify(NSString()) // CHECK-NEXT: NSString -fooify(NSMutableString()) // CHECK-NEXT: NSString -fooify(NSSet()) // CHECK-NEXT: not fooable +var ProtocolLookupForeign = TestSuite("ProtocolLookupForeign") +ProtocolLookupForeign.test("NSRect") { + expectEqual("NSRect", fooify(NSRect())) +} + +ProtocolLookupForeign.test("NSPoint") { + expectEqual("not fooable", fooify(NSPoint())) +} + +ProtocolLookupForeign.test("CFSet") { + if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) { + expectEqual("CFSet", fooify(CFSetCreate(kCFAllocatorDefault, nil, 0, nil)!)) + } +} + +ProtocolLookupForeign.test("CFArray") { + expectEqual("not fooable", fooify(CFArrayCreate(kCFAllocatorDefault, nil, 0, nil)!)) +} + +ProtocolLookupForeign.test("NSString") { + expectEqual("NSString", fooify(NSString())) +} + +ProtocolLookupForeign.test("NSMutableString") { + expectEqual("NSString", fooify(NSMutableString())) +} + +ProtocolLookupForeign.test("NSSet") { + expectEqual("not fooable", fooify(NSSet())) +} + +runAllTests() diff --git a/test/Interpreter/enum.swift b/test/Interpreter/enum.swift index da9f6c4b17cf6..b2b66b761e743 100644 --- a/test/Interpreter/enum.swift +++ b/test/Interpreter/enum.swift @@ -698,3 +698,49 @@ func testCase() { // CHECK: Container(storage: a.MultiIndirectRef.ind(5)) testCase() + + +enum BitEnum { + case first + case second +} +protocol Init { + init() +} +struct TrailingByte : Init { + var x = 2 + var y = BitEnum.first + init() { + x = 2 + y = BitEnum.first + } +} + +@inline(never) +func capture(_ t: inout T) { + print("captured \(t)") +} + +@inline(never) +func reproduction(_ x: Int, _ y: Int, _ t: T) { + var o : Optional = nil + + + for i in 0 ..< x { + if i == y { + o = T() + } + } + + capture(&o) + + if var byte = o { + print("there is a byte (failure)") + print(byte) + } else { + print("there is no byte") + } +} + +// CHECK: there is no byte +reproduction(2, 3, TrailingByte()) diff --git a/test/Interpreter/tuple_casts.swift b/test/Interpreter/tuple_casts.swift index 4c0dacafa57f9..0f662932ed6e7 100644 --- a/test/Interpreter/tuple_casts.swift +++ b/test/Interpreter/tuple_casts.swift @@ -1,7 +1,13 @@ // RUN: %target-run-simple-swift -// RUN: %target-build-swift -O %s -o %t/a.out.optimized -// RUN: %target-codesign %t/a.out.optimized -// RUN: %target-run %t/a.out.optimized +// +// RUN: %target-build-swift -swift-version 5 -O %s -o %t/a.swift5.O.out +// RUN: %target-codesign %t/a.swift5.O.out +// RUN: %target-run %t/a.swift5.O.out +// +// RUN: %target-build-swift -swift-version 5 -Onone %s -o %t/a.swift5.Onone.out +// RUN: %target-codesign %t/a.swift5.Onone.out +// RUN: %target-run %t/a.swift5.Onone.out +// // REQUIRES: executable_test import StdlibUnittest @@ -31,15 +37,31 @@ tupleCastTests.test("Adding/removing labels") { String(describing: anyToIntPoint((3, 4)))) expectEqual("(x: 5, y: 6)", String(describing: anyToIntPoint((x: 5, 6)))) + expectEqual("(x: 5, y: 6)", + String(describing: anyToIntPoint((5, y: 6)))) expectEqual("(1, 2)", String(describing: anyToInt2((1, 2)))) expectEqual("(3, 4)", String(describing: anyToInt2((x: 3, y: 4)))) expectEqual("(5, 6)", String(describing: anyToInt2((x: 5, 6)))) + expectEqual("(7, 8)", String(describing: anyToInt2((7, y: 8)))) expectEqual("(first: 1, 2, third: 3)", String(describing: anyToPartlyLabeled((1, 2, 3)))) } +tupleCastTests.test("Label checks on casting") { + expectTrue((x: 1, y: 2) is (Int, Int)) + expectTrue((x: 1, y: 2) is (x: Int, Int)) + expectTrue((x: 1, y: 2) is (Int, y: Int)) + expectTrue((x: 1, y: 2) is (x: Int, y: Int)) + + expectFalse((x: 1, y: 2) is (x: Int, z: Int)) + expectFalse((x: 1, y: 2) is (a: Int, y: Int)) + expectFalse((x: 1, y: 2) is (a: Int, z: Int)) + expectFalse((x: 1, y: 2) is (Int, z: Int)) + expectFalse((x: 1, y: 2) is (a: Int, Int)) +} + tupleCastTests.test("Incorrect labels conditional cast") { expectNil(anyToIntPointOpt((x: 1, z: 2))) expectEqual("Optional((x: 1, y: 2))", diff --git a/test/ModuleInterface/empty-extension.swift b/test/ModuleInterface/empty-extension.swift new file mode 100644 index 0000000000000..65323afcbcf86 --- /dev/null +++ b/test/ModuleInterface/empty-extension.swift @@ -0,0 +1,49 @@ +// Test that we don't print extensions to implementation-only imported types. + +// RUN: %empty-directory(%t) + +// RUN: %target-swift-frontend -emit-module %s -DIOI_LIB -module-name IOILib -emit-module-path %t/IOILib.swiftmodule +// RUN: %target-swift-frontend -emit-module %s -DEXPORTED_LIB -module-name IndirectLib -emit-module-path %t/IndirectLib.swiftmodule -I %t +// RUN: %target-swift-frontend -emit-module %s -DLIB -module-name Lib -emit-module-path %t/Lib.swiftmodule -I %t + +// RUN: %target-swift-frontend-typecheck -emit-module-interface-path %t/out.swiftinterface %s -I %t -swift-version 5 -enable-library-evolution +// RUN: %FileCheck %s < %t/out.swiftinterface + +#if IOI_LIB + +public struct IOIImportedType { + public func foo() {} +} + +#elseif EXPORTED_LIB + +public struct ExportedType { + public func foo() {} +} + +#elseif LIB + +@_exported import IndirectLib + +public struct NormalImportedType { + public func foo() {} +} + +#else // Client + +import Lib +@_implementationOnly import IOILib + +public protocol PublicProto { + func foo() +} +extension IOIImportedType : PublicProto {} +// CHECK-NOT: IOIImportedType + +extension NormalImportedType : PublicProto {} +// CHECK: extension NormalImportedType + +extension ExportedType : PublicProto {} +// CHECK: extension ExportedType + +#endif diff --git a/test/ModuleInterface/inherited-generic-parameters.swift b/test/ModuleInterface/inherited-generic-parameters.swift index 1be75a69d7311..ecaebf59237e8 100644 --- a/test/ModuleInterface/inherited-generic-parameters.swift +++ b/test/ModuleInterface/inherited-generic-parameters.swift @@ -19,6 +19,8 @@ public class Base { // CHECK-NEXT: public init(_: A, _: A) public init(_: A, _: A) {} +// CHECK-NEXT: public init(_: C) where C : main.Base + public init(_: C) where C : Base {} // CHECK: } } @@ -27,6 +29,7 @@ public class Derived : Base { // CHECK-NEXT: {{(@objc )?}}deinit // CHECK-NEXT: override public init(x: @escaping (T) -> T) // CHECK-NEXT: override public init(_ argument: A, _ argument: A) +// CHECK-NEXT: override public init(_ argument: C) where C : main.Base // CHECK-NEXT: } } diff --git a/test/ModuleInterface/unbuildable.swift b/test/ModuleInterface/unbuildable.swift index 42506ad70770f..3c1606164cfc7 100644 --- a/test/ModuleInterface/unbuildable.swift +++ b/test/ModuleInterface/unbuildable.swift @@ -14,8 +14,15 @@ // // And finally, test: // -// RUN: not %target-swift-frontend -typecheck %s -I %t -DCURRENT 2>&1 | %FileCheck -check-prefix=CURRENT %s -// RUN: not %target-swift-frontend -typecheck %s -I %t -DFUTURE 2>&1 | %FileCheck -check-prefix=FUTURE %s +// RUN: not %target-swift-frontend -typecheck %s -I %t -DCURRENT 2>&1 | %FileCheck -check-prefixes=ALL,CURRENT %s +// RUN: not %target-swift-frontend -typecheck %s -I %t -DFUTURE 2>&1 | %FileCheck -check-prefixes=ALL,FUTURE %s +// +// Test that we get the same results when typechecking the interface: +// +// RUN: not %target-swift-frontend -typecheck-module-from-interface %t/UnbuildableCurrent.swiftinterface 2>&1 | %FileCheck -check-prefixes=ALL,CURRENT-VERIFY %s +// RUN: not %target-swift-frontend -typecheck-module-from-interface %t/UnbuildableFuture.swiftinterface 2>&1 | %FileCheck -check-prefixes=ALL,FUTURE-VERIFY %s + +// ALL: Unbuildable{{[^.]+}}.swiftinterface:{{[0-9]+}}:{{[0-9]+}}: error: use of unknown directive '#somethingYouveNeverHeardOf' #if CURRENT import UnbuildableCurrent @@ -25,3 +32,5 @@ import UnbuildableFuture // FUTURE: unbuildable.swift:[[@LINE-1]]:8: error: failed to build module 'UnbuildableFuture' from its module interface; the compiler that produced it, 'NeoTokyoSwift 2000.42', may have used features that aren't supported by this compiler, '{{.*Swift version.*}}' #endif +// CURRENT-VERIFY: UnbuildableCurrent.swiftinterface:1:1: error: failed to verify module interface of 'UnbuildableCurrent'; it may have been damaged or it may have triggered a bug in the Swift compiler when it was produced +// FUTURE-VERIFY: UnbuildableFuture.swiftinterface:1:1: error: failed to verify module interface of 'UnbuildableFuture'; the compiler that produced it, 'NeoTokyoSwift 2000.42', may have used features that aren't supported by this compiler, '{{.*Swift version.*}}' diff --git a/test/ModuleInterface/verify-module-interfaces.swift b/test/ModuleInterface/verify-module-interfaces.swift new file mode 100644 index 0000000000000..191360f2bfb90 --- /dev/null +++ b/test/ModuleInterface/verify-module-interfaces.swift @@ -0,0 +1,15 @@ +// RUN: %empty-directory(%t) + +// Check that verification won't reject a valid interface: +// RUN: %target-build-swift -emit-library -enable-library-evolution -emit-module-interface -emit-module -swift-version 5 -o %t/MyModule.o -verify-emitted-module-interface -module-name MyModule %s + +// Check that verification will reject an invalid interface: +// RUN: not %target-build-swift -emit-library -enable-library-evolution -emit-module-interface -emit-module -swift-version 5 -o %t/MyModule.o -verify-emitted-module-interface -module-name MyModule -Xfrontend -debug-emit-invalid-swiftinterface-syntax %s 2>&1 | %FileCheck %s + +// ...but not if verification is off. +// RUN: %target-build-swift -emit-library -enable-library-evolution -emit-module-interface -emit-module -swift-version 5 -o %t/MyModule.o -no-verify-emitted-module-interface -module-name MyModule -Xfrontend -debug-emit-invalid-swiftinterface-syntax %s + +public struct MyStruct {} + +// CHECK: MyModule.swiftinterface:{{[0-9]+}}:{{[0-9]+}}: error: use of unknown directive '#__debug_emit_invalid_swiftinterface_syntax__' +// CHECK: MyModule.swiftinterface:{{[0-9]+}}:{{[0-9]+}}: error: failed to verify module interface of 'MyModule'; it may have been damaged or it may have triggered a bug in the Swift compiler when it was produced diff --git a/test/NameLookup/Inputs/custom_attrs_A.swift b/test/NameLookup/Inputs/custom_attrs_A.swift new file mode 100644 index 0000000000000..c8035b4fa167e --- /dev/null +++ b/test/NameLookup/Inputs/custom_attrs_A.swift @@ -0,0 +1,13 @@ +@propertyWrapper +public struct Wrapper { + public var wrappedValue: Value + + public init(wrappedValue: Value) { + self.wrappedValue = wrappedValue + } +} + +@_functionBuilder +public struct Builder { + static func buildBlock(_ component: T) -> T { component } +} diff --git a/test/NameLookup/Inputs/custom_attrs_B.swift b/test/NameLookup/Inputs/custom_attrs_B.swift new file mode 100644 index 0000000000000..c8035b4fa167e --- /dev/null +++ b/test/NameLookup/Inputs/custom_attrs_B.swift @@ -0,0 +1,13 @@ +@propertyWrapper +public struct Wrapper { + public var wrappedValue: Value + + public init(wrappedValue: Value) { + self.wrappedValue = wrappedValue + } +} + +@_functionBuilder +public struct Builder { + static func buildBlock(_ component: T) -> T { component } +} diff --git a/test/NameLookup/custom_attrs_ambiguous.swift b/test/NameLookup/custom_attrs_ambiguous.swift new file mode 100644 index 0000000000000..b549e34e273ba --- /dev/null +++ b/test/NameLookup/custom_attrs_ambiguous.swift @@ -0,0 +1,21 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-module -I %t -o %t %S/Inputs/custom_attrs_A.swift +// RUN: %target-swift-frontend -emit-module -I %t -o %t %S/Inputs/custom_attrs_B.swift +// RUN: %target-swift-frontend -typecheck -verify -verify-ignore-unknown -I %t %s +import custom_attrs_A +import custom_attrs_B + +// SR-13470 + +struct Test { + @Wrapper var x: Int = 17 + // expected-error@-1 {{ambiguous use of attribute 'Wrapper'}} + // expected-note@-2 {{use 'custom_attrs_A.' to reference the attribute 'Wrapper' in module 'custom_attrs_A'}} {{4-4=custom_attrs_A.}} + // expected-note@-3 {{use 'custom_attrs_B.' to reference the attribute 'Wrapper' in module 'custom_attrs_B'}} {{4-4=custom_attrs_B.}} + + init(@Builder closure: () -> Int) {} + // expected-error@-1 {{ambiguous use of attribute 'Builder'}} + // expected-note@-2 {{use 'custom_attrs_A.' to reference the attribute 'Builder' in module 'custom_attrs_A'}} {{9-9=custom_attrs_A.}} + // expected-note@-3 {{use 'custom_attrs_B.' to reference the attribute 'Builder' in module 'custom_attrs_B'}} {{9-9=custom_attrs_B.}} +} + diff --git a/test/NameLookup/member_type_shadowing.swift b/test/NameLookup/member_type_shadowing.swift index 3ce67db444956..0e3b4f7a81b9d 100644 --- a/test/NameLookup/member_type_shadowing.swift +++ b/test/NameLookup/member_type_shadowing.swift @@ -29,3 +29,17 @@ class B: A { _ = B.Reusable.option2 // expected-error {{type 'B.Reusable' has no member 'option2'; did you mean 'option1'?}} } } + +protocol Q { + typealias A = Int +} + +struct S : Q { + typealias A = String +} + +func usesA(_: S.A) {} // should resolve to the typealias inside S + +func callsA() { + usesA("hello") +} diff --git a/test/Parse/async-syntax.swift b/test/Parse/async-syntax.swift index 54c1bac839969..c305fc44dd67b 100644 --- a/test/Parse/async-syntax.swift +++ b/test/Parse/async-syntax.swift @@ -12,5 +12,15 @@ func testTypeExprs() { } func testAwaitOperator() async { - let _ = __await asyncGlobal1() + let _ = await asyncGlobal1() +} + +func testAsyncClosure() { + let _ = { () async in 5 } + let _ = { () throws in 5 } + let _ = { () async throws in 5 } +} + +func testAwait() async { + let _ = await asyncGlobal1() } diff --git a/test/Parse/async.swift b/test/Parse/async.swift index 6fee5c0bfdee6..657048a27aec6 100644 --- a/test/Parse/async.swift +++ b/test/Parse/async.swift @@ -41,3 +41,14 @@ func testTypeExprs() { let _ = [() -> async ()]() // expected-error{{'async' may only occur before '->'}}{{18-24=}}{{15-15=async }} } + +// Parsing await syntax. +struct MyFuture { + func await() -> Int { 0 } +} + +func testAwaitExpr() async { + let _ = await asyncGlobal1() + let myFuture = MyFuture() + let _ = myFuture.await() +} diff --git a/test/PrintAsObjC/Inputs/custom-modules/CompatibilityAlias.h b/test/PrintAsObjC/Inputs/custom-modules/CompatibilityAlias.h index 0d8ec65a05288..45e6515b4bf73 100644 --- a/test/PrintAsObjC/Inputs/custom-modules/CompatibilityAlias.h +++ b/test/PrintAsObjC/Inputs/custom-modules/CompatibilityAlias.h @@ -1,5 +1,7 @@ // This file is meant to be included with modules turned off, compiled against // the fake clang-importer-sdk. #import +#import @compatibility_alias StringCheese NSString; +@compatibility_alias GymClass GenericClass; diff --git a/test/PrintAsObjC/classes.swift b/test/PrintAsObjC/classes.swift index 025bef7fb4d5d..69c2beae96e5a 100644 --- a/test/PrintAsObjC/classes.swift +++ b/test/PrintAsObjC/classes.swift @@ -49,8 +49,26 @@ import SingleGenericClass // CHECK-NEXT: @end @objc class B1 : A1 {} +// Used in BridgedTypes test case +struct Notification: _ObjectiveCBridgeable { + func _bridgeToObjectiveC() -> NSNotification { fatalError() } + static func _forceBridgeFromObjectiveC( + _ source: NSNotification, + result: inout Self? + ) { fatalError() } + @discardableResult + static func _conditionallyBridgeFromObjectiveC( + _ source: NSNotification, + result: inout Self? + ) -> Bool { fatalError() } + @_effects(readonly) + static func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectiveCType?) + -> Self { fatalError() } +} + // CHECK-LABEL: @interface BridgedTypes // CHECK-NEXT: - (NSDictionary * _Nonnull)dictBridge:(NSDictionary * _Nonnull)x SWIFT_WARN_UNUSED_RESULT; +// CHECK-NEXT: - (NSNotification * _Nonnull)noteBridge:(NSNotification * _Nonnull)x SWIFT_WARN_UNUSED_RESULT; // CHECK-NEXT: - (NSSet * _Nonnull)setBridge:(NSSet * _Nonnull)x SWIFT_WARN_UNUSED_RESULT; // CHECK-NEXT: init // CHECK-NEXT: @end @@ -59,6 +77,10 @@ import SingleGenericClass return x } + @objc func noteBridge(_ x: Notification) -> Notification { + return x + } + @objc func setBridge(_ x: Set) -> Set { return x } @@ -798,6 +820,9 @@ public class NonObjCClass { } // CHECK-NEXT: - (StringCheese * _Nullable)foo SWIFT_WARN_UNUSED_RESULT; @objc func foo() -> StringCheese? { return nil } + // CHECK-NEXT: - (GymClass * _Nullable)foosball SWIFT_WARN_UNUSED_RESULT; + @objc func foosball() -> GymClass? { return nil } + // CHECK-NEXT: - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; } // CHECK-NEXT: @end diff --git a/test/SIL/Parser/async.sil b/test/SIL/Parser/async.sil index 694f66de78175..f65cee1ca6e16 100644 --- a/test/SIL/Parser/async.sil +++ b/test/SIL/Parser/async.sil @@ -1,8 +1,31 @@ // RUN: %target-sil-opt -enable-sil-verify-all=true %s | %target-sil-opt -enable-sil-verify-all=true | %FileCheck %s -// CHECK: sil [async] @async_test -sil [async] @async_test : $() -> () { +import Builtin + +// CHECK: sil @not_async_test : $@convention(thin) () -> () { +sil @not_async_test : $() -> () { +bb0: + %0 = tuple () + return %0 : $() +} + +// CHECK: sil @not_async_test2 : $@convention(thin) (Builtin.Int32) -> () { +sil @not_async_test2 : $(Builtin.Int32) -> () { +bb0(%int : $Builtin.Int32): + %0 = tuple () + return %0 : $() +} + +// CHECK: sil @async_test : $@convention(thin) @async +sil @async_test : $@async () -> () { bb0: %0 = tuple () return %0 : $() } + +// CHECK: sil @take_async : $@convention(thin) (@async () -> ()) -> () +sil @take_async : $(@async () -> ()) -> () { +bb0(%fn : $@async () -> ()): + %0 = tuple () + return %0 : $() +} diff --git a/test/SIL/Serialization/basic.sil b/test/SIL/Serialization/basic.sil index dd7f9ba3a54d4..f6950e30ab2a5 100644 --- a/test/SIL/Serialization/basic.sil +++ b/test/SIL/Serialization/basic.sil @@ -15,8 +15,8 @@ bb0(%0 : @guaranteed $Builtin.NativeObject): return undef : $() } -// CHECK-LABEL: sil [async] @async_test -sil [async] @async_test : $() -> () { +// CHECK-LABEL: sil @async_test : $@convention(thin) @async +sil @async_test : $@async () -> () { bb0: %0 = tuple () return %0 : $() diff --git a/test/SILGen/async.swift b/test/SILGen/async.swift deleted file mode 100644 index 901978a7ac493..0000000000000 --- a/test/SILGen/async.swift +++ /dev/null @@ -1,20 +0,0 @@ -// RUN: %target-swift-frontend -emit-silgen -enable-experimental-concurrency -module-name Async -Xllvm -sil-full-demangle -parse-as-library %s | %FileCheck %s - -import Swift - -// CHECK-LABEL: sil hidden [async] [ossa] @$s5Async04testA0yyYF : $@convention(thin) () -> () { -func testAsync() async {} -// CHECK-LABEL: sil hidden [async] [ossa] @$s5Async11testAsyncp1SiyYF : $@convention(thin) () -> Int { -func testAsyncp1() async -> Int { return 0 } - -// CHECK-LABEL: sil hidden [async] [ossa] @$s5Async5test2yyYKF : $@convention(thin) () -> @error Error { -func test2() async throws {} -// CHECK-LABEL: sil hidden [async] [ossa] @$s5Async7test2p1SiyYKF : $@convention(thin) () -> (Int, @error Error) { -func test2p1() async throws -> Int { return 0 } - -// CHECK-LABEL: sil hidden [async] [ossa] @$s5Async5test3yyyyKXEYKF : $@convention(thin) (@noescape @callee_guaranteed () -> @error Error) -> @error Error { -func test3(_ cl: () throws -> ()) async rethrows {} -// CHECK-LABEL: sil hidden [async] [ossa] @$s5Async7test3p1yS2iyKXEYKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error) { -func test3p1(_ cl: () throws -> Int) async rethrows -> Int { return try cl() } - - diff --git a/test/SILGen/default_arguments.swift b/test/SILGen/default_arguments.swift index 8fc06fb8ed67a..0895a9a0f018a 100644 --- a/test/SILGen/default_arguments.swift +++ b/test/SILGen/default_arguments.swift @@ -156,7 +156,7 @@ class Foo { return x } - // CHECK-LABEL: sil private [ossa] @globalinit_33_E52D764B1F2009F2390B2B8DF62DAEB8_func0 + // CHECK-LABEL: sil private [global_init_once_fn] [ossa] @{{.*}}WZ // CHECK: string_literal utf8 "Foo" static let x = Foo(int:0) diff --git a/test/SILGen/fragile_globals.swift b/test/SILGen/fragile_globals.swift index 0a4ace7ffa3a1..c6c6e412eece0 100644 --- a/test/SILGen/fragile_globals.swift +++ b/test/SILGen/fragile_globals.swift @@ -11,7 +11,7 @@ var mygg = 29 // Check if we have one token: from mygg. // Initializers from other modules are never fragile. -// CHECK: sil_global private{{.*}} @globalinit_[[T3:.*]]_token0 +// CHECK: sil_global private{{.*}} @[[T3:.*]]Wz //@inlinable public func sum() -> Int { @@ -21,8 +21,8 @@ public func sum() -> Int { // Check if all the addressors are inlined. // CHECK-LABEL: sil {{.*}}@$s15fragile_globals3sumSiyF -// CHECK-DAG: global_addr @globalinit_[[T1:.*]]_token0 -// CHECK-DAG: function_ref @globalinit_[[T1]]_func0 +// CHECK-DAG: global_addr @[[T1:.*]]Wz +// CHECK-DAG: function_ref @[[T1]]WZ // CHECK-DAG: global_addr @$s15fragile_globals4myggSivp // CHECK-DAG: function_ref @$s7ModuleA2ggSivau // CHECK-DAG: function_ref @$s7ModuleB2ggSivau diff --git a/test/SILGen/global_resilience.swift b/test/SILGen/global_resilience.swift index 78b425a9ed684..2f5ea45c549e8 100644 --- a/test/SILGen/global_resilience.swift +++ b/test/SILGen/global_resilience.swift @@ -43,21 +43,21 @@ public var myEmptyGlobal = MyEmptyStruct() // Mutable addressor for fixed-layout global -// CHECK-LABEL: sil private [ossa] @globalinit_{{.*}}_func1 +// CHECK-LABEL: sil private [global_init_once_fn] [ossa] @{{.*}}WZ // CHECK: alloc_global @$s17global_resilience19myFixedLayoutGlobalAA13MyEmptyStructVv // CHECK: return // CHECK-LABEL: sil [global_init] [ossa] @$s17global_resilience19myFixedLayoutGlobalAA13MyEmptyStructVvau -// CHECK: function_ref @globalinit_{{.*}}_func1 +// CHECK: function_ref @{{.*}}WZ // CHECK: global_addr @$s17global_resilience19myFixedLayoutGlobalAA13MyEmptyStructVv // CHECK: return -// CHECK-OPT-LABEL: sil private @globalinit_{{.*}}_func1 +// CHECK-OPT-LABEL: sil private [global_init_once_fn] @{{.*}}WZ // CHECK-OPT: alloc_global @$s17global_resilience19myFixedLayoutGlobalAA13MyEmptyStructVv // CHECK-OPT: return // CHECK-OPT-LABEL: sil [global_init] @$s17global_resilience19myFixedLayoutGlobalAA13MyEmptyStructVvau -// CHECK-OPT: function_ref @globalinit_{{.*}}_func1 +// CHECK-OPT: function_ref @{{.*}}WZ // CHECK-OPT: global_addr @$s17global_resilience19myFixedLayoutGlobalAA13MyEmptyStructVvp // CHECK-OPT: return diff --git a/test/SILGen/keypaths_objc.swift b/test/SILGen/keypaths_objc.swift index 215847db3e443..b5603386f5876 100644 --- a/test/SILGen/keypaths_objc.swift +++ b/test/SILGen/keypaths_objc.swift @@ -113,3 +113,47 @@ class OverrideFrameworkObjCProperty: A { func overrideFrameworkObjCProperty() { let _ = \OverrideFrameworkObjCProperty.counter } + +@dynamicMemberLookup +class DynamicClass { + init() {} + subscript(dynamicMember member: KeyPath) -> DynamicClass { + fatalError() + } +} + +// CHECK-LABEL: sil hidden [ossa] @{{.*}}dynamicMemberLookupSimple +func dynamicMemberLookupSimple(foo: DynamicClass, nonobjc: DynamicClass) { + // CHECK: keypath $KeyPath, (objc "bar" + _ = foo.bar + // CHECK: keypath $KeyPath, (objc "int" + _ = foo.int + // CHECK: keypath $KeyPath, (objc "bar" + // CHECK: keypath $KeyPath, (objc "foo" + _ = foo.bar.foo + // CHECK: keypath $KeyPath, (root + _ = foo.nonobjc + // CHECK: keypath $KeyPath, (objc "thisIsADifferentName" + _ = foo.differentName + // CHECK: keypath $KeyPath, (root + _ = nonobjc.x + // CHECK: keypath $KeyPath, (root + _ = nonobjc.y +} + +// CHECK-LABEL: sil hidden [ossa] @{{.*}}dynamicMemberLookupNestedKeypaths +func dynamicMemberLookupNestedKeypaths(foo: DynamicClass) { + // CHECK: keypath $KeyPath, (objc "bar" + // CHECK: keypath $KeyPath, (objc "foo" + // CHECK: keypath $KeyPath, (objc "bar" + _ = foo.bar.foo.bar +} + +// CHECK-LABEL: sil hidden [ossa] @{{.*}}dynamicMemberLookupMixedKeypaths +func dynamicMemberLookupMixedKeypaths(foo: DynamicClass) { + // CHECK: keypath $KeyPath, (objc "bar" + // CHECK: keypath $KeyPath, (objc "foo" + // CHECK: keypath $KeyPath, (root + // CHECK: keypath $KeyPath, (root + _ = foo.bar.foo.nonobjc.y +} \ No newline at end of file diff --git a/test/SILGen/lazy_globals.swift b/test/SILGen/lazy_globals.swift index 4e1cc299c3468..c5604dc5a159a 100644 --- a/test/SILGen/lazy_globals.swift +++ b/test/SILGen/lazy_globals.swift @@ -1,14 +1,14 @@ // RUN: %target-swift-emit-silgen -parse-as-library %s | %FileCheck %s -// CHECK: sil private [ossa] @globalinit_[[T:.*]]_func0 : $@convention(c) () -> () { +// CHECK: sil private [global_init_once_fn] [ossa] @[[T:.*]]WZ : $@convention(c) () -> () { // CHECK: alloc_global @$s12lazy_globals1xSiv // CHECK: [[XADDR:%.*]] = global_addr @$s12lazy_globals1xSivp : $*Int // CHECK: store {{%.*}} to [trivial] [[XADDR]] : $*Int // CHECK: sil hidden [global_init] [ossa] @$s12lazy_globals1xSivau : $@convention(thin) () -> Builtin.RawPointer { -// CHECK: [[TOKEN_ADDR:%.*]] = global_addr @globalinit_[[T]]_token0 : $*Builtin.Word +// CHECK: [[TOKEN_ADDR:%.*]] = global_addr @[[T]]Wz : $*Builtin.Word // CHECK: [[TOKEN_PTR:%.*]] = address_to_pointer [[TOKEN_ADDR]] : $*Builtin.Word to $Builtin.RawPointer -// CHECK: [[INIT_FUNC:%.*]] = function_ref @globalinit_[[T]]_func0 : $@convention(c) () -> () +// CHECK: [[INIT_FUNC:%.*]] = function_ref @[[T]]WZ : $@convention(c) () -> () // CHECK: builtin "once"([[TOKEN_PTR]] : $Builtin.RawPointer, [[INIT_FUNC]] : $@convention(c) () -> ()) : $() // CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$s12lazy_globals1xSivp : $*Int // CHECK: [[GLOBAL_PTR:%.*]] = address_to_pointer [[GLOBAL_ADDR]] : $*Int to $Builtin.RawPointer @@ -16,7 +16,7 @@ // CHECK: } var x: Int = 0 -// CHECK: sil private [ossa] @globalinit_[[T:.*]]_func1 : $@convention(c) () -> () { +// CHECK: sil private [global_init_once_fn] [ossa] @[[T:.*]]WZ : $@convention(c) () -> () { // CHECK: alloc_global @$s12lazy_globals3FooV3fooSivpZ // CHECK: [[XADDR:%.*]] = global_addr @$s12lazy_globals3FooV3fooSivpZ : $*Int // CHECK: store {{.*}} to [trivial] [[XADDR]] : $*Int @@ -24,9 +24,9 @@ var x: Int = 0 struct Foo { // CHECK: sil hidden [global_init] [ossa] @$s12lazy_globals3FooV3fooSivau : $@convention(thin) () -> Builtin.RawPointer { -// CHECK: [[TOKEN_ADDR:%.*]] = global_addr @globalinit_[[T]]_token1 : $*Builtin.Word +// CHECK: [[TOKEN_ADDR:%.*]] = global_addr @[[T]]Wz : $*Builtin.Word // CHECK: [[TOKEN_PTR:%.*]] = address_to_pointer [[TOKEN_ADDR]] : $*Builtin.Word to $Builtin.RawPointer -// CHECK: [[INIT_FUNC:%.*]] = function_ref @globalinit_[[T]]_func1 : $@convention(c) () -> () +// CHECK: [[INIT_FUNC:%.*]] = function_ref @[[T]]WZ : $@convention(c) () -> () // CHECK: builtin "once"([[TOKEN_PTR]] : $Builtin.RawPointer, [[INIT_FUNC]] : $@convention(c) () -> ()) : $() // CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$s12lazy_globals3FooV3fooSivpZ : $*Int // CHECK: [[GLOBAL_PTR:%.*]] = address_to_pointer [[GLOBAL_ADDR]] : $*Int to $Builtin.RawPointer @@ -40,7 +40,7 @@ struct Foo { static var initialized: Int = 57 } -// CHECK: sil private [ossa] @globalinit_[[T:.*]]_func3 : $@convention(c) () -> () { +// CHECK: sil private [global_init_once_fn] [ossa] @[[T:.*3bar.*]]WZ : $@convention(c) () -> () { // CHECK: alloc_global @$s12lazy_globals3BarO3barSivpZ // CHECK: [[XADDR:%.*]] = global_addr @$s12lazy_globals3BarO3barSivpZ : $*Int // CHECK: store {{.*}} to [trivial] [[XADDR]] : $*Int @@ -48,9 +48,9 @@ struct Foo { enum Bar { // CHECK: sil hidden [global_init] [ossa] @$s12lazy_globals3BarO3barSivau : $@convention(thin) () -> Builtin.RawPointer { -// CHECK: [[TOKEN_ADDR:%.*]] = global_addr @globalinit_[[T]]_token3 : $*Builtin.Word +// CHECK: [[TOKEN_ADDR:%.*]] = global_addr @[[T]]Wz : $*Builtin.Word // CHECK: [[TOKEN_PTR:%.*]] = address_to_pointer [[TOKEN_ADDR]] : $*Builtin.Word to $Builtin.RawPointer -// CHECK: [[INIT_FUNC:%.*]] = function_ref @globalinit_[[T]]_func3 : $@convention(c) () -> () +// CHECK: [[INIT_FUNC:%.*]] = function_ref @[[T]]WZ : $@convention(c) () -> () // CHECK: builtin "once"([[TOKEN_PTR]] : $Builtin.RawPointer, [[INIT_FUNC]] : $@convention(c) () -> ()) : $() // CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$s12lazy_globals3BarO3barSivpZ : $*Int // CHECK: [[GLOBAL_PTR:%.*]] = address_to_pointer [[GLOBAL_ADDR]] : $*Int to $Builtin.RawPointer @@ -63,13 +63,13 @@ enum Bar { func f() -> (Int, Int) { return (1, 2) } -// CHECK: sil private [ossa] @globalinit_[[T]]_func4 : $@convention(c) () -> () { +// CHECK: sil private [global_init_once_fn] [ossa] @[[T:.*2a1.*2b1.*]]WZ : $@convention(c) () -> () { // CHECK: function_ref @$s12lazy_globals1fSi_SityF : $@convention(thin) () -> (Int, Int) // CHECK: sil hidden [global_init] [ossa] @$s12lazy_globals2a1Sivau : $@convention(thin) () -> Builtin.RawPointer -// CHECK: function_ref @globalinit_[[T]]_func4 : $@convention(c) () -> () +// CHECK: function_ref @[[T]]WZ : $@convention(c) () -> () // CHECK: global_addr @$s12lazy_globals2a1Sivp : $*Int // CHECK: sil hidden [global_init] [ossa] @$s12lazy_globals2b1Sivau : $@convention(thin) () -> Builtin.RawPointer { -// CHECK: function_ref @globalinit_[[T]]_func4 : $@convention(c) () -> () +// CHECK: function_ref @[[T]]WZ : $@convention(c) () -> () // CHECK: global_addr @$s12lazy_globals2b1Sivp : $*Int var (a1, b1) = f() diff --git a/test/SILGen/lazy_globals_multiple_vars.swift b/test/SILGen/lazy_globals_multiple_vars.swift index 0c415d5c20231..059cfa8267cbf 100644 --- a/test/SILGen/lazy_globals_multiple_vars.swift +++ b/test/SILGen/lazy_globals_multiple_vars.swift @@ -1,34 +1,34 @@ // RUN: %target-swift-emit-silgen -parse-as-library %s | %FileCheck %s -// CHECK: sil private [ossa] [[INIT_A_B:@globalinit_.*]] : +// CHECK: sil private [global_init_once_fn] [ossa] [[INIT_A_B:@.*1a.*1b.*WZ]] : // CHECK: alloc_global @$s26lazy_globals_multiple_vars1aSiv // CHECK: global_addr @$s26lazy_globals_multiple_vars1aSiv // CHECK: alloc_global @$s26lazy_globals_multiple_vars1bSiv // CHECK: global_addr @$s26lazy_globals_multiple_vars1bSiv // CHECK: sil hidden [global_init] [ossa] @$s26lazy_globals_multiple_vars1aSivau -// CHECK: global_addr [[TOKEN_A_B:@globalinit_.*]] : +// CHECK: global_addr [[TOKEN_A_B:@.*1a.*1b.*Wz]] : // CHECK: function_ref [[INIT_A_B]] // CHECK: sil hidden [global_init] [ossa] @$s26lazy_globals_multiple_vars1bSivau // CHECK: global_addr [[TOKEN_A_B]] // CHECK: function_ref [[INIT_A_B]] var (a, b) = (1, 2) -// CHECK: sil private [ossa] [[INIT_C:@globalinit_.*]] : +// CHECK: sil private [global_init_once_fn] [ossa] [[INIT_C:@.*1c.*WZ]] : // CHECK-NOT: global_addr @$s26lazy_globals_multiple_vars1dSiv // CHECK: alloc_global @$s26lazy_globals_multiple_vars1cSiv // CHECK: global_addr @$s26lazy_globals_multiple_vars1cSiv // CHECK-NOT: global_addr @$s26lazy_globals_multiple_vars1dSiv // CHECK: sil hidden [global_init] [ossa] @$s26lazy_globals_multiple_vars1cSivau -// CHECK: global_addr [[TOKEN_C:@globalinit_.*]] : +// CHECK: global_addr [[TOKEN_C:@.*1c.*Wz]] : // CHECK: function_ref [[INIT_C]] -// CHECK: sil private [ossa] [[INIT_D:@globalinit_.*]] : +// CHECK: sil private [global_init_once_fn] [ossa] [[INIT_D:@.*1d.*WZ]] : // CHECK-NOT: global_addr @$s26lazy_globals_multiple_vars1cSiv // CHECK: alloc_global @$s26lazy_globals_multiple_vars1dSiv // CHECK: global_addr @$s26lazy_globals_multiple_vars1dSiv // CHECK-NOT: global_addr @$s26lazy_globals_multiple_vars1cSiv // CHECK: sil hidden [global_init] [ossa] @$s26lazy_globals_multiple_vars1dSivau // CHECK-NOT: global_addr [[TOKEN_C]] -// CHECK: global_addr [[TOKEN_D:@globalinit_.*]] : +// CHECK: global_addr [[TOKEN_D:@.*1d.*Wz]] : // CHECK-NOT: global_addr [[TOKEN_C]] // CHECK: function_ref [[INIT_D]] var c = 1, d = 2 diff --git a/test/SILGen/observers.swift b/test/SILGen/observers.swift index 3051c0a1126c7..6b6c6d4503fa1 100644 --- a/test/SILGen/observers.swift +++ b/test/SILGen/observers.swift @@ -171,7 +171,7 @@ public struct DidSetWillSetTests { var global_observing_property : Int = zero { // The variable is initialized with "zero". - // CHECK-LABEL: sil private [ossa] @globalinit_{{.*}}_func1 : $@convention(c) () -> () { + // CHECK-LABEL: sil private [global_init_once_fn] [ossa] @{{.*}}WZ : $@convention(c) () -> () { // CHECK: bb0: // CHECK-NEXT: alloc_global @$s9observers25global_observing_propertySiv // CHECK-NEXT: %1 = global_addr @$s9observers25global_observing_propertySivp : $*Int diff --git a/test/SILGen/opaque_result_type_private.swift b/test/SILGen/opaque_result_type_private.swift new file mode 100644 index 0000000000000..25cff253f4d59 --- /dev/null +++ b/test/SILGen/opaque_result_type_private.swift @@ -0,0 +1,34 @@ +// RUN: %target-swift-emit-silgen -primary-file %s -disable-availability-checking | %FileCheck %s +// RUN: %target-swift-emit-sil -primary-file %s -O -disable-availability-checking + +// CHECK-LABEL: sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer>>) -> Int32 { + +// CHECK: [[BOX:%.*]] = alloc_stack $PrivateClass +// CHECK: [[FN:%.*]] = function_ref @$s26opaque_result_type_private19returnPrivateOpaqueQryF : $@convention(thin) () -> @out PrivateClass +// CHECK: apply [[FN]]([[BOX]]) : $@convention(thin) () -> @out PrivateClass +// CHECK: [[RESULT:%.*]] = load [take] [[BOX]] : $*PrivateClass +// CHECK: destroy_value [[RESULT]] : $PrivateClass +// CHECK: dealloc_stack [[BOX]] : $*PrivateClass +_ = returnPrivateOpaque() + +// CHECK: [[BOX:%.*]] = alloc_stack $LocalClass +// CHECK: [[FN:%.*]] = function_ref @$s26opaque_result_type_private17returnLocalOpaqueQryF : $@convention(thin) () -> @out LocalClass +// CHECK: apply [[FN]]([[BOX]]) : $@convention(thin) () -> @out LocalClass +// CHECK: [[RESULT:%.*]] = load [take] [[BOX]] : $*LocalClass +// CHECK: destroy_value [[RESULT]] : $LocalClass +// CHECK: dealloc_stack [[BOX]] : $*LocalClass +_ = returnLocalOpaque() + +fileprivate class PrivateClass {} + +// CHECK-LABEL: sil hidden [ossa] @$s26opaque_result_type_private19returnPrivateOpaqueQryF : $@convention(thin) () -> @out @_opaqueReturnTypeOf("$s26opaque_result_type_private19returnPrivateOpaqueQryF", 0) 🦸 +func returnPrivateOpaque() -> some Any { + return PrivateClass() +} + +// CHECK-LABEL: sil hidden [ossa] @$s26opaque_result_type_private17returnLocalOpaqueQryF : $@convention(thin) () -> @out @_opaqueReturnTypeOf("$s26opaque_result_type_private17returnLocalOpaqueQryF", 0) 🦸 +func returnLocalOpaque() -> some Any { + class LocalClass {} + + return LocalClass() +} diff --git a/test/SILGen/unreachable_code.swift b/test/SILGen/unreachable_code.swift index 79c3fb0837f44..799a27a49eefc 100644 --- a/test/SILGen/unreachable_code.swift +++ b/test/SILGen/unreachable_code.swift @@ -67,8 +67,7 @@ func testUnreachableCase1(a : Tree) { case let Leaf: _ = Leaf return - case .Branch(_): // expected-warning {{case will never be executed}} - // expected-warning@-1 {{case is already handled by previous patterns; consider removing it}} + case .Branch(_): // expected-warning {{case is already handled by previous patterns; consider removing it}} return } } @@ -87,8 +86,7 @@ func testUnreachableCase3(a : Tree) { switch a { case _: break - case .Branch(_): // expected-warning {{case will never be executed}} - // expected-warning@-1 {{case is already handled by previous patterns; consider removing it}} + case .Branch(_): // expected-warning {{case is already handled by previous patterns; consider removing it}} return } } @@ -137,3 +135,14 @@ func sr6141() { return; bar?.append("x") // expected-warning{{code after 'return' will never be executed}} } + +func testUnreachableCatchClause() { + enum ErrorEnum: Error { case someError } + do { + throw ErrorEnum.someError + } catch let error { + print(error) + } catch ErrorEnum.someError { // expected-warning {{case will never be executed}} + print("some error") + } +} diff --git a/test/SILOptimizer/Inputs/definite_init_cross_module/OtherModule.swift b/test/SILOptimizer/Inputs/definite_init_cross_module/OtherModule.swift index 3e449b357336c..e3568a71bdc25 100644 --- a/test/SILOptimizer/Inputs/definite_init_cross_module/OtherModule.swift +++ b/test/SILOptimizer/Inputs/definite_init_cross_module/OtherModule.swift @@ -41,3 +41,14 @@ public struct Empty { public struct GenericEmpty { public init() {} } + +open class VisibleNoArgsDesignatedInit { + var x: Float + public init() { x = 0.0 } + + // Add some designated inits the subclass cannot see. + private init(x: Float) { self.x = x } + fileprivate init(y: Float) { self.x = y } + internal init(z: Float) { self.x = z } +} + diff --git a/test/SILOptimizer/access_marker_verify.swift b/test/SILOptimizer/access_marker_verify.swift index 1ed6f62f84fdd..6062f4116579f 100644 --- a/test/SILOptimizer/access_marker_verify.swift +++ b/test/SILOptimizer/access_marker_verify.swift @@ -627,17 +627,17 @@ func testShims() -> UInt32 { // --- global variable initialization. var globalString1 = "⓪" // start non-empty -// CHECK-LABEL: sil private [ossa] @globalinit_33_{{.*}}_func0 : $@convention(c) () -> () { +// CHECK-LABEL: sil private [global_init_once_fn] [ossa] @{{.*}}WZ : $@convention(c) () -> () { // CHECK: alloc_global @$s20access_marker_verify13globalString1SSvp // CHECK: [[GA:%.*]] = global_addr @$s20access_marker_verify13globalString1SSvp : $*String // CHECK: apply // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[GA]] : $*String // CHECK: store %{{.*}} to [init] [[ACCESS]] : $*String // CHECK: end_access -// CHECK-LABEL: } // end sil function 'globalinit_33_180BF7B9126DB0C8C6C26F15ACD01908_func0' +// CHECK-LABEL: } // end sil function '{{.*}}WZ' var globalString2 = globalString1 -// CHECK-LABEL: sil private [ossa] @globalinit_33_180BF7B9126DB0C8C6C26F15ACD01908_func1 : $@convention(c) () -> () { +// CHECK-LABEL: sil private [global_init_once_fn] [ossa] @{{.*}}WZ : $@convention(c) () -> () { // CHECK: alloc_global @$s20access_marker_verify13globalString2SSvp // CHECK: [[GA:%.*]] = global_addr @$s20access_marker_verify13globalString2SSvp : $*String // CHECK: apply @@ -648,7 +648,7 @@ var globalString2 = globalString1 // CHECK: end_access [[INIT]] : $*String // CHECK: end_access [[ACCESS]] : $*String // CHECK-NOT: end_access -// CHECK-LABEL: } // end sil function 'globalinit_33_180BF7B9126DB0C8C6C26F15ACD01908_func1' +// CHECK-LABEL: } // end sil function '{{.*}}WZ' // --- getter. @@ -1037,13 +1037,13 @@ func testPointerInit(x: Int, y: UnsafeMutablePointer) { class testInitExistentialGlobal { static var testProperty: P = StructP() } -// CHECK-LABEL: sil private [ossa] @globalinit{{.*}} : $@convention(c) () -> () { +// CHECK-LABEL: sil private [global_init_once_fn] [ossa] @{{.*}}WZ : $@convention(c) () -> () { // CHECK: alloc_global @$s20access_marker_verify25testInitExistentialGlobalC0D8PropertyAA1P_pvpZ // CHECK: [[GADR:%.*]] = global_addr @$s20access_marker_verify25testInitExistentialGlobalC0D8PropertyAA1P_pvpZ : $*P // CHECK: %{{.*}} = apply %{{.*}}({{.*}}) : $@convention(method) (@thin StructP.Type) -> StructP // CHECK: [[EADR:%.*]] = init_existential_addr [[GADR]] : $*P, $StructP // CHECK: store %{{.*}} to [trivial] [[EADR]] : $*StructP -// CHECK-LABEL: } // end sil function 'globalinit +// CHECK-LABEL: } // end sil function '{{.*}}WZ public enum SomeError: Swift.Error { case error diff --git a/test/SILOptimizer/access_marker_verify_objc.swift b/test/SILOptimizer/access_marker_verify_objc.swift index b9fc5fbaa7c0e..c3e1ed48efe35 100644 --- a/test/SILOptimizer/access_marker_verify_objc.swift +++ b/test/SILOptimizer/access_marker_verify_objc.swift @@ -12,14 +12,14 @@ import Foundation // --- initializer `let` of CFString. // The verifier should ignore this. -// CHECK_LABEL: sil private @globalinit{{.*}} : $@convention(c) () -> () { +// CHECK_LABEL: sil private @{{.*}}WZ : $@convention(c) () -> () { // CHECK: bb0: // CHECK: alloc_global @$s25access_marker_verify_objc12testCFStringC8cfStringSo0F3RefavpZ // CHECK: [[GA:%.*]] = global_addr @$s25access_marker_verify_objc12testCFStringC8cfStringSo0F3RefavpZ : $*CFString // CHECK-NOT: begin_access // CHECK: store %{{.*}} to [init] [[GA]] : $*CFString // CHECK: return %{{.*}} : $() -// CHECK-LABEL: } // end sil function 'globalinit{{.*}}' +// CHECK-LABEL: } // end sil function '{{.*}}WZ' class testCFString { public static let cfString: CFString = "" as CFString } diff --git a/test/SILOptimizer/arcsequenceopts.sil b/test/SILOptimizer/arcsequenceopts.sil index 8825d9cbae7f0..b12c341ed0de9 100644 --- a/test/SILOptimizer/arcsequenceopts.sil +++ b/test/SILOptimizer/arcsequenceopts.sil @@ -405,6 +405,12 @@ bb0(%0 : $<τ_0_0> { var τ_0_0 } ): return %1 : $() } +sil @guaranteed_box_throwing_use : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } ) -> @error Error { +bb0(%0 : $<τ_0_0> { var τ_0_0 } ): + %1 = tuple () + return %1 : $() +} + // CHECK_LABEL: sil hidden [noinline] @$test_guaranteed_call : // CHECK: bb1{{.*}}: // CHECK-NOT: strong_retain @@ -2157,6 +2163,30 @@ bb2(%4 : $Error): throw %4 : $Error } +// CHECK_LABEL: sil hidden [noinline] @$try_apply_test_3 : +// CHECK-NOT: strong_retain +// CHECK-NOT: strong_release +// CHECK_LABEL: } // end sil function '$try_apply_test_3' +sil hidden [noinline] @$try_apply_test_3 : $@convention(thin) () -> @error Error { +bb0: + %box = alloc_box $<τ_0_0> { var τ_0_0 } + %proj = project_box %box : $<τ_0_0> { var τ_0_0 } , 0 + %funcref = function_ref @guaranteed_box_throwing_use : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } ) -> @error Error + br bb1 + +bb1: + strong_retain %box : $<τ_0_0> { var τ_0_0 } + try_apply %funcref (%box) : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } ) -> @error Error, normal bbs, error bbe + +bbs(%s : $()): + strong_release %box : $<τ_0_0> { var τ_0_0 } + return undef : $() + +bbe(%e : $Error): + strong_release %box : $<τ_0_0> { var τ_0_0 } + throw %e : $Error +} + // In this control flow, ARC runs multiple iterations to get rid of and move the retain and releases. // In the first iteration, we will try to move id1/id3 towards each other. // we create new instructions and remove the old ones. However we had a bug to insert these newly created diff --git a/test/SILOptimizer/definite_init_cross_module.swift b/test/SILOptimizer/definite_init_cross_module.swift index 2201cbf12c436..6a7f9debbbd1b 100644 --- a/test/SILOptimizer/definite_init_cross_module.swift +++ b/test/SILOptimizer/definite_init_cross_module.swift @@ -254,3 +254,27 @@ extension GenericEmpty { init(xx: Double) { } // expected-error {{'self.init' isn't called on all paths before returning from initializer}} } + +class AcceptsVisibleNoArgsDesignatedInit: VisibleNoArgsDesignatedInit { + var y: Float + init(y: Float) { + self.y = y + // no error + } +} + +open class InModuleVisibleNoArgsDesignatedInit { + var x: Float + public init() { x = 0.0 } + + // Add a designated init the subclass cannot see. + private init(x: Float) { self.x = x } +} + +class AcceptsInModuleVisibleNoArgsDesignatedInit: InModuleVisibleNoArgsDesignatedInit { + var y: Float + init(y: Float) { + self.y = y + // no error + } +} diff --git a/test/SILOptimizer/escape_analysis.sil b/test/SILOptimizer/escape_analysis.sil index bc8b42ba2426d..21944bbe21603 100644 --- a/test/SILOptimizer/escape_analysis.sil +++ b/test/SILOptimizer/escape_analysis.sil @@ -1983,3 +1983,27 @@ bb4: %z = tuple () return %z : $() } + +// Test CGNode mapping for result of an apply to no return function +// CHECK-LABEL:CG of $testcaller +// CHECK: Arg [ref] %0 Esc: A, Succ: (%0.1) +// CHECK: Con [int] %0.1 Esc: A, Succ: (%0.2) +// CHECK: Con [ref] %0.2 Esc: A, Succ: +// CHECK-LABEL:End +sil hidden [noinline] @$testcaller : $@convention(thin) (@owned Z) -> () { +bb0(%0 : $Z): + %2 = function_ref @$noreturncallee : $@convention(thin) (@guaranteed Z) -> @owned Z + %3 = apply %2(%0) : $@convention(thin) (@guaranteed Z) -> @owned Z + dealloc_ref %3 : $Z + %5 = tuple () + return %5 : $() +} + +// CHECK-LABEL:CG of $noreturncallee +// CHECK: Arg [ref] %0 Esc: A, Succ: +// CHECK-LABEL:End +sil hidden [noinline] @$noreturncallee : $@convention(thin) (@guaranteed Z) -> @owned Z { +bb0(%0 : $Z): + unreachable +} + diff --git a/test/SILOptimizer/globalopt_trivial_nontrivial.sil b/test/SILOptimizer/globalopt_trivial_nontrivial.sil index 3625c10946211..8f094f633febb 100644 --- a/test/SILOptimizer/globalopt_trivial_nontrivial.sil +++ b/test/SILOptimizer/globalopt_trivial_nontrivial.sil @@ -38,7 +38,7 @@ sil_global private @globalinit_nontrivialglobal_token : $Builtin.Word sil_global hidden [let] @$nontrivialglobal : $TClass -sil private @globalinit_trivialglobal_func : $@convention(c) () -> () { +sil private [global_init_once_fn] @globalinit_trivialglobal_func : $@convention(c) () -> () { bb0: alloc_global @$trivialglobal %1 = global_addr @$trivialglobal : $*TStruct @@ -83,13 +83,13 @@ bb0: return %4 : $Int32 } -// CHECK-LABEL: sil private @globalinit_nontrivialglobal_func : +// CHECK-LABEL: sil private [global_init_once_fn] @globalinit_nontrivialglobal_func : // CHECK: alloc_global @$nontrivialglobal // CHECK: [[GLOBL_ADDR:%.*]] = global_addr @$nontrivialglobal : $*TClass // CHECK: [[REF:%.*]] = alloc_ref $TClass // CHECK: store [[REF]] to [[GLOBL_ADDR]] : $*TClass // CHECK: } // end sil function 'globalinit_nontrivialglobal_func' -sil private @globalinit_nontrivialglobal_func : $@convention(c) () -> () { +sil private [global_init_once_fn] @globalinit_nontrivialglobal_func : $@convention(c) () -> () { bb0: alloc_global @$nontrivialglobal %1 = global_addr @$nontrivialglobal : $*TClass diff --git a/test/SILOptimizer/globalopt_trivial_nontrivial_ossa.sil b/test/SILOptimizer/globalopt_trivial_nontrivial_ossa.sil index 182210cb2671e..433aff21f011f 100644 --- a/test/SILOptimizer/globalopt_trivial_nontrivial_ossa.sil +++ b/test/SILOptimizer/globalopt_trivial_nontrivial_ossa.sil @@ -32,7 +32,7 @@ sil_global private @globalinit_nontrivialglobal_token : $Builtin.Word sil_global hidden [let] @$nontrivialglobal : $TClass -sil private [ossa] @globalinit_trivialglobal_func : $@convention(c) () -> () { +sil private [global_init_once_fn] [ossa] @globalinit_trivialglobal_func : $@convention(c) () -> () { bb0: alloc_global @$trivialglobal %1 = global_addr @$trivialglobal : $*TStruct @@ -75,13 +75,13 @@ bb0: return %4 : $Int32 } -// CHECK-LABEL: sil private [ossa] @globalinit_nontrivialglobal_func : +// CHECK-LABEL: sil private [global_init_once_fn] [ossa] @globalinit_nontrivialglobal_func : // CHECK: alloc_global @$nontrivialglobal // CHECK: [[GLOBL_ADDR:%.*]] = global_addr @$nontrivialglobal : $*TClass // CHECK: [[REF:%.*]] = alloc_ref $TClass // CHECK: store [[REF]] to [init] [[GLOBL_ADDR]] : $*TClass // CHECK: } // end sil function 'globalinit_nontrivialglobal_func' -sil private [ossa] @globalinit_nontrivialglobal_func : $@convention(c) () -> () { +sil private [global_init_once_fn] [ossa] @globalinit_nontrivialglobal_func : $@convention(c) () -> () { bb0: alloc_global @$nontrivialglobal %1 = global_addr @$nontrivialglobal : $*TClass diff --git a/test/SILOptimizer/inline_addressor.swift b/test/SILOptimizer/inline_addressor.swift index c78e0a25c5f41..369799a725370 100644 --- a/test/SILOptimizer/inline_addressor.swift +++ b/test/SILOptimizer/inline_addressor.swift @@ -11,10 +11,10 @@ var totalsum = nonTrivialInit(true) //CHECK-LABEL: sil {{.*}}testit //CHECK: {{^bb0}} -//CHECK: globalinit_ +//CHECK: WZ //CHECK-NOT: {{^bb0}} //CHECK: {{^bb1}} -//CHECK-NOT: globalinit +//CHECK-NOT: WZ //CHECK-NOT: totalsum //CHECK-NOT: inputval //CHECK: {{^}$}} diff --git a/test/SILOptimizer/inline_generics.sil b/test/SILOptimizer/inline_generics.sil index 5ba0af36fdfbb..2ca1b70b7b188 100644 --- a/test/SILOptimizer/inline_generics.sil +++ b/test/SILOptimizer/inline_generics.sil @@ -47,55 +47,6 @@ bb0(%0 : $*T, %1 : $*T): return %9 : $() } // end sil function 'testInliningOfGenerics' -sil hidden @P_combine : $@convention(method) (@in T, @guaranteed Self) -> @owned @callee_owned (@in T) -> Bool { -bb0(%0 : $*T, %1 : $Self): - // function_ref P.(combine (first : A1) -> (A1) -> Bool).(closure #1) - %4 = function_ref @_TFFE50generic_inlining_partial_apply_opened_existentialsPS_1P7combineurFT5firstqd___Fqd__SbU_Fqd__Sb : $@convention(thin) <τ_0_0 where τ_0_0 : P><τ_1_0> (@in τ_1_0) -> Bool - %5 = partial_apply %4() : $@convention(thin) <τ_0_0 where τ_0_0 : P><τ_1_0> (@in τ_1_0) -> Bool - destroy_addr %0 : $*T - return %5 : $@callee_owned (@in T) -> Bool -} // end sil function 'P_combine' - -// P.(combine (first : A1) -> (A1) -> Bool).(closure #1) -sil shared @_TFFE50generic_inlining_partial_apply_opened_existentialsPS_1P7combineurFT5firstqd___Fqd__SbU_Fqd__Sb : $@convention(thin) (@in T) -> Bool { -bb0(%0 : $*T): - %2 = integer_literal $Builtin.Int1, -1 - %3 = struct $Bool (%2 : $Builtin.Int1) - destroy_addr %0 : $*T - return %3 : $Bool -} // end sil function '_TFFE50generic_inlining_partial_apply_opened_existentialsPS_1P7combineurFT5firstqd___Fqd__SbU_Fqd__Sb' - - -// Check that P_combine is not inlined into the generic function, because -// doing so would result in a partial_apply instruction, with an opened existential -// in the substitution list. And this cannot be handled by the IRGen yet. -// CHECK-LABEL: sil @dont_inline_callee_with_opened_existential_in_partial_apply_substitution_list -// CHECK: [[FUN_REF:%[0-9]+]] = function_ref @P_combine -// CHECK: apply [[FUN_REF]] -// CHECK: end sil function 'dont_inline_callee_with_opened_existential_in_partial_apply_substitution_list' -sil @dont_inline_callee_with_opened_existential_in_partial_apply_substitution_list : $@convention(thin) (@owned P) -> @owned @callee_owned (@owned T) -> Bool { -bb0(%0 : $P): - %2 = open_existential_ref %0 : $P to $@opened("41B148C8-F49C-11E6-BE69-A45E60E99281") P - // function_ref P.combine (first : A1) -> (A1) -> Bool - %3 = function_ref @P_combine : $@convention(method) <τ_0_0 where τ_0_0 : P><τ_1_0> (@in τ_1_0, @guaranteed τ_0_0) -> @owned @callee_owned (@in τ_1_0) -> Bool - %4 = open_existential_ref %0 : $P to $@opened("41B14A4E-F49C-11E6-BE69-A45E60E99281") P - %5 = witness_method $@opened("41B14A4E-F49C-11E6-BE69-A45E60E99281") P, #P.getSelf : (Self) -> () -> Self, %4 : $@opened("41B14A4E-F49C-11E6-BE69-A45E60E99281") P : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0 - %6 = apply %5<@opened("41B14A4E-F49C-11E6-BE69-A45E60E99281") P>(%4) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> @owned τ_0_0 - %7 = init_existential_ref %6 : $@opened("41B14A4E-F49C-11E6-BE69-A45E60E99281") P : $@opened("41B14A4E-F49C-11E6-BE69-A45E60E99281") P, $P - %8 = alloc_stack $P - store %7 to %8 : $*P - %10 = apply %3<@opened("41B148C8-F49C-11E6-BE69-A45E60E99281") P, P>(%8, %2) : $@convention(method) <τ_0_0 where τ_0_0 : P><τ_1_0> (@in τ_1_0, @guaranteed τ_0_0) -> @owned @callee_owned (@in τ_1_0) -> Bool - // function_ref thunk - %11 = function_ref @thunk1 : $@convention(thin) (@owned P, @owned @callee_owned (@in P) -> Bool) -> Bool - %12 = partial_apply %11(%10) : $@convention(thin) (@owned P, @owned @callee_owned (@in P) -> Bool) -> Bool - // function_ref thunk - %13 = function_ref @thunk2 : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned τ_0_0, @owned @callee_owned (@owned P) -> Bool) -> Bool - %14 = partial_apply %13(%12) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@owned τ_0_0, @owned @callee_owned (@owned P) -> Bool) -> Bool - dealloc_stack %8 : $*P - strong_release %0 : $P - return %14 : $@callee_owned (@owned T) -> Bool -} // end sil function 'dont_inline_callee_with_opened_existential_in_partial_apply_substitution_list' - // thunk sil shared [transparent] [reabstraction_thunk] @thunk1 : $@convention(thin) (@owned P, @owned @callee_owned (@in P) -> Bool) -> Bool { bb0(%0 : $P, %1 : $@callee_owned (@in P) -> Bool): diff --git a/test/SILOptimizer/licm.sil b/test/SILOptimizer/licm.sil index 6823dda54a085..9ac8ae2492cba 100644 --- a/test/SILOptimizer/licm.sil +++ b/test/SILOptimizer/licm.sil @@ -854,3 +854,82 @@ bb9(%39 : $Builtin.Int64): // Preds: bb7 dealloc_stack %3 : $*Index // id: %41 return %40 : $Int64 // id: %42 } + +// testConditionalTrapInInfiniteSyncLoop and +// testConditionalTrapDominatingSyncLoopExit +// +// It's legal for the optimizer to consider code after the loop as +// always reachable, but when a loop has no exits, or when the loops +// exits are dominated by a conditional statement we should not +// consider conditional statements within the loop as dominating all +// possible execution paths through the loop. At least not when there +// is at least one path through the loop that contains a +// "synchronization point", such as a function that may contain a +// memory barrier, perform I/O, or exit the program. +sil @mayExit : $@convention(thin) () -> () + +// CHECK-LABEL: sil @testConditionalTrapInInfiniteSyncLoop : $@convention(thin) (Builtin.Int1, Builtin.Int1) -> () { +// CHECK: bb0 +// CHECK-NOT: cond_fail +// CHECK: br bb1 +// CHECK: bb1: +// CHECK: cond_br %0, bb2, bb3 +// CHECK: bb2: +// CHECK: cond_fail %1 : $Builtin.Int1, "arithmetic overflow" +// CHECK-LABEL: } // end sil function 'testConditionalTrapInInfiniteSyncLoop' +sil @testConditionalTrapInInfiniteSyncLoop : $@convention(thin) (Builtin.Int1, Builtin.Int1) -> () { +bb0(%0 : $Builtin.Int1, %1 : $Builtin.Int1): + br bb1 + +bb1: // loop head + cond_br %0, bb2, bb3 + +bb2: // maybe never executed + cond_fail %1 : $Builtin.Int1, "arithmetic overflow" + br bb4 + +bb3: + // synchronization point: has "real" side-effects that we can't + // reorder with traps + %f = function_ref @mayExit : $@convention(thin) () -> () + apply %f() : $@convention(thin) () -> () + br bb4 + +bb4: // latch + br bb1 +} + +// CHECK-LABEL: sil @testConditionalTrapDominatingSyncLoopExit : $@convention(thin) (Builtin.Int1, Builtin.Int1, Builtin.Int1) -> () { +// CHECK: bb0 +// CHECK-NOT: cond_fail +// CHECK: br bb1 +// CHECK: bb1: +// CHECK: cond_br %0, bb2, bb4 +// CHECK: bb2: +// CHECK: cond_fail %1 : $Builtin.Int1, "arithmetic overflow" +// CHECK-LABEL: } // end sil function 'testConditionalTrapDominatingSyncLoopExit' +sil @testConditionalTrapDominatingSyncLoopExit : $@convention(thin) (Builtin.Int1, Builtin.Int1, Builtin.Int1) -> () { +bb0(%0 : $Builtin.Int1, %1 : $Builtin.Int1, %2 : $Builtin.Int1): + br bb1 + +bb1: // loop head + cond_br %0, bb2, bb4 + +bb2: // maybe never executed + cond_fail %1 : $Builtin.Int1, "arithmetic overflow" + cond_br %2, bb3, bb5 + +bb3: // tail + br bb1 + +bb4: + // synchronization point: has "real" side-effects that we can't + // reorder with traps + %f = function_ref @mayExit : $@convention(thin) () -> () + apply %f() : $@convention(thin) () -> () + br bb1 + +bb5: + %99 = tuple () + return %99 : $() +} diff --git a/test/SILOptimizer/opt-remark-generator-force-emit-implicit-autogen.swift b/test/SILOptimizer/opt-remark-generator-force-emit-implicit-autogen.swift new file mode 100644 index 0000000000000..9c49cd002cf51 --- /dev/null +++ b/test/SILOptimizer/opt-remark-generator-force-emit-implicit-autogen.swift @@ -0,0 +1,16 @@ +// RUN: %target-swiftc_driver -O -Rpass-missed=sil-opt-remark-gen -Xllvm -sil-disable-pass=FunctionSignatureOpts -emit-sil %s -o /dev/null -Xfrontend -verify -Xllvm -optremarkgen-visit-implicit-autogen-funcs=1 + +// From the constructor. +class Klass {} // expected-remark {{heap allocated ref of type 'Klass'}} + +struct KlassPair { + var lhs: Klass // expected-remark {{retain of type 'Klass'}} + // expected-note @-1 {{of 'self.lhs'}} + // expected-remark @-2 {{release of type 'Klass'}} + // expected-note @-3 {{of 'self.lhs'}} + var rhs: Klass // expected-remark {{retain of type 'Klass'}} + // expected-note @-1 {{of 'self.rhs'}} + // expected-remark @-2 {{release of type 'Klass'}} + // expected-note @-3 {{of 'self.rhs'}} +} + diff --git a/test/SILOptimizer/opt-remark-generator-semantics.swift b/test/SILOptimizer/opt-remark-generator-semantics.swift index 513d7d3ef7cb3..ab39837098cb2 100644 --- a/test/SILOptimizer/opt-remark-generator-semantics.swift +++ b/test/SILOptimizer/opt-remark-generator-semantics.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -emit-sil %s -verify -Osize +// RUN: %target-swift-frontend -emit-sil %s -verify -Osize -o /dev/null -module-name main // // NOTE: We only emit opt-remarks with -Osize,-O today! -O does drop way more // stuff though, so we test with -Osize. @@ -7,29 +7,41 @@ public class Klass {} public var mySingleton = Klass() +@inline(never) +func getGlobal() -> Klass { + return mySingleton +} + +@inline(never) +func useKlass(_ k: Klass) {} + @_semantics("optremark") @inline(never) -public func forceOptRemark() -> Klass { - return mySingleton // expected-remark {{retain}} - // expected-note @-6 {{of 'mySingleton'}} +public func forceOptRemark() { + let x = getGlobal() + useKlass(x) // expected-remark {{release of type 'Klass'}} + // expected-note @-2 {{of 'x'}} } @_semantics("optremark.sil-opt-remark-gen") @inline(never) -public func forceOptRemark2() -> Klass { - return mySingleton // expected-remark {{retain}} - // expected-note @-13 {{of 'mySingleton'}} +public func forceOptRemark2() { + let x = getGlobal() + useKlass(x) // expected-remark {{release of type 'Klass'}} + // expected-note @-2 {{of 'x'}} } @_semantics("optremark.fail") @inline(never) -public func failMatch() -> Klass { - return mySingleton +public func failMatch() { + let x = getGlobal() + useKlass(x) } @_semantics("optremark") public func allocateInlineCallee() -> Klass { return Klass() // expected-remark {{Pure call. Always profitable to inline "main.Klass.__allocating_init()"}} + // expected-remark @-1 {{heap allocated ref of type 'Klass'}} } @_semantics("optremark.sil-inliner") @@ -45,29 +57,31 @@ public func allocateInlineCallee3() -> Klass { @_semantics("optremark.sil-inliner") @_semantics("optremark.sil-opt-remark-gen") public func mix1() -> (Klass, Klass) { - return (mySingleton, Klass()) // expected-remark {{Pure call. Always profitable to inline "main.Klass.__allocating_init()"}} - // expected-remark @-1:5 {{retain}} - // expected-note @-42:12 {{of 'mySingleton'}} + let x = getGlobal() + return (x, Klass()) // expected-remark {{Pure call. Always profitable to inline "main.Klass.__allocating_init()"}} + // expected-remark @-1:16 {{heap allocated ref of type 'Klass'}} } @_semantics("optremark.sil-inliner") public func mix2() -> (Klass, Klass) { - return (mySingleton, Klass()) // expected-remark {{Pure call. Always profitable to inline "main.Klass.__allocating_init()"}} + let x = getGlobal() + return (x, Klass()) // expected-remark {{Pure call. Always profitable to inline "main.Klass.__allocating_init()"}} } @_semantics("optremark.sil-opt-remark-gen") public func mix3() -> (Klass, Klass) { - return (mySingleton, Klass()) // expected-remark @:5 {{retain}} - // expected-note @-53:12 {{of 'mySingleton'}} + let x = getGlobal() + return (x, Klass()) // expected-remark {{heap allocated ref of type 'Klass'}} } @_semantics("optremark") public func mix4() -> (Klass, Klass) { - return (mySingleton, Klass()) // expected-remark {{Pure call. Always profitable to inline "main.Klass.__allocating_init()"}} - // expected-remark @-1:5 {{retain}} - // expected-note @-60:12 {{of 'mySingleton'}} + let x = getGlobal() + return (x, Klass()) // expected-remark {{Pure call. Always profitable to inline "main.Klass.__allocating_init()"}} + // expected-remark @-1 {{heap allocated ref of type 'Klass'}} } public func mix5() -> (Klass, Klass) { - return (mySingleton, Klass()) + let x = getGlobal() + return (x, Klass()) } diff --git a/test/SILOptimizer/opt-remark-generator-yaml.swift b/test/SILOptimizer/opt-remark-generator-yaml.swift index 11e3dbb7f9d25..13a9301f1546d 100644 --- a/test/SILOptimizer/opt-remark-generator-yaml.swift +++ b/test/SILOptimizer/opt-remark-generator-yaml.swift @@ -1,4 +1,3 @@ -// REQUIRES: rdar66330768 // RUN: %target-swiftc_driver -O -Rpass-missed=sil-opt-remark-gen -Xllvm -sil-disable-pass=FunctionSignatureOpts -emit-sil %s -o /dev/null -Xfrontend -verify // RUN: %empty-directory(%t) @@ -10,7 +9,18 @@ public class Klass {} -public var global = Klass() +// CHECK: --- !Missed +// CHECK-NEXT: Pass: sil-opt-remark-gen +// CHECK-NEXT: Name: sil.memory +// CHECK-NEXT: DebugLoc: { File: '{{.*}}opt-remark-generator-yaml.swift', +// CHECK-NEXT: Line: [[# @LINE + 7 ]], Column: 21 } +// CHECK-NEXT: Function: main +// CHECK-NEXT: Args: +// CHECK-NEXT: - String: 'heap allocated ref of type ''' +// CHECK-NEXT: - ValueType: Klass +// CHECK-NEXT: - String: '''' +// CHECK-NEXT: ... +public var global = Klass() // expected-remark {{heap allocated ref of type 'Klass'}} // CHECK: --- !Missed // CHECK-NEXT: Pass: sil-opt-remark-gen @@ -32,6 +42,17 @@ public func getGlobal() -> Klass { // expected-note @-19:12 {{of 'global'}} } +// CHECK: --- !Missed +// CHECK-NEXT: Pass: sil-opt-remark-gen +// CHECK-NEXT: Name: sil.memory +// CHECK-NEXT: DebugLoc: { File: '{{.*}}opt-remark-generator-yaml.swift', +// CHECK-NEXT: Line: [[# @LINE + 51]], Column: 11 } +// CHECK-NEXT: Function: 'useGlobal()' +// CHECK-NEXT: Args: +// CHECK-NEXT: - String: 'heap allocated ref of type ''' +// CHECK-NEXT: - ValueType: +// CHECK-NEXT: - String: '''' +// CHECK-NEXT: ... // CHECK-NEXT: --- !Missed // CHECK-NEXT: Pass: sil-opt-remark-gen // CHECK-NEXT: Name: sil.memory @@ -54,7 +75,7 @@ public func getGlobal() -> Klass { // CHECK-NEXT: Function: 'useGlobal()' // CHECK-NEXT: Args: // CHECK-NEXT: - String: 'release of type ''' -// CHECK-NEXT: - ValueType: {{'Array'|__ContiguousArrayStorageBase}} +// CHECK-NEXT: - ValueType: // CHECK-NEXT: - String: '''' // CHECK-NEXT: ... // CHECK-NEXT: --- !Missed @@ -76,10 +97,11 @@ public func useGlobal() { let x = getGlobal() // Make sure that the retain msg is at the beginning of the print and the // releases are the end of the print. - print(x) // expected-remark @:5 {{retain of type 'Klass'}} - // expected-note @-4:9 {{of 'x'}} + print(x) // expected-remark @:11 {{heap allocated ref of type}} + // expected-remark @-1:5 {{retain of type 'Klass'}} + // expected-note @-5:9 {{of 'x'}} // We test the type emission above since FileCheck can handle regex. - // expected-remark @-3:12 {{release of type}} - // expected-remark @-4:12 {{release of type 'Klass'}} - // expected-note @-8:9 {{of 'x'}} + // expected-remark @-4:12 {{release of type}} + // expected-remark @-5:12 {{release of type 'Klass'}} + // expected-note @-9:9 {{of 'x'}} } diff --git a/test/SILOptimizer/opt-remark-generator.swift b/test/SILOptimizer/opt-remark-generator.swift index ed32d18dae885..8c780ea9f571b 100644 --- a/test/SILOptimizer/opt-remark-generator.swift +++ b/test/SILOptimizer/opt-remark-generator.swift @@ -1,9 +1,13 @@ // RUN: %target-swiftc_driver -O -Rpass-missed=sil-opt-remark-gen -Xllvm -sil-disable-pass=FunctionSignatureOpts -emit-sil %s -o /dev/null -Xfrontend -verify // REQUIRES: optimized_stdlib +// XFAIL: OS=linux-androideabi && CPU=armv7 + public class Klass {} -public var global = Klass() +// TODO: Change global related code to be implicit/autogenerated (as +// appropriate) so we don't emit this remark. +public var global = Klass() // expected-remark {{heap allocated ref of type 'Klass'}} @inline(never) public func getGlobal() -> Klass { @@ -11,15 +15,20 @@ public func getGlobal() -> Klass { // expected-note @-5:12 {{of 'global'}} } +// Make sure that the retain msg is at the beginning of the print and the +// releases are the end of the print. +// +// The heap allocated ref is for the temporary array and the release that is +// unannotated is for that array as well. We make sure that the heap allocated +// ref is on the argument that necessitated its creation. public func useGlobal() { let x = getGlobal() - // Make sure that the retain msg is at the beginning of the print and the - // releases are the end of the print. - print(x) // expected-remark @:5 {{retain of type 'Klass'}} - // expected-note @-4:9 {{of 'x'}} - // expected-remark @-2:12 {{release of type}} - // expected-remark @-3:12 {{release of type 'Klass'}} - // expected-note @-7:9 {{of 'x'}} + print(x) // expected-remark @:11 {{heap allocated ref of type}} + // expected-remark @-1:5 {{retain of type 'Klass'}} + // expected-note @-3:9 {{of 'x'}} + // expected-remark @-3:12 {{release of type}} + // expected-remark @-4:12 {{release of type 'Klass'}} + // expected-note @-6:9 {{of 'x'}} } public enum TrivialState { @@ -29,27 +38,21 @@ case third } struct StructWithOwner { - // This retain is from the initializers of owner. - // - // TODO: Should we emit this? - var owner = Klass() // expected-remark {{retain of type 'Klass'}} - // expected-note @-1 {{of 'self.owner'}} - // expected-remark @-2 {{release of type 'Klass'}} - // expected-note @-3 {{of 'self.owner'}} + var owner = Klass() var state = TrivialState.first } func printStructWithOwner(x : StructWithOwner) { - print(x) // expected-remark {{retain of type 'Klass'}} - // expected-note @-2:27 {{of 'x.owner'}} - // We should be able to infer the arg here. + print(x) // expected-remark @:11 {{heap allocated ref of type}} + // expected-remark @-1 {{retain of type 'Klass'}} + // expected-note @-3:27 {{of 'x.owner'}} // expected-remark @-3:12 {{release of type}} } func printStructWithOwnerOwner(x : StructWithOwner) { - print(x.owner) // expected-remark {{retain of type 'Klass'}} - // expected-note @-2:32 {{of 'x.owner'}} - // We should be able to infer the arg here. + print(x.owner) // expected-remark @:11 {{heap allocated ref of type}} + // expected-remark @-1 {{retain of type 'Klass'}} + // expected-note @-3:32 {{of 'x.owner'}} // expected-remark @-3:18 {{release of type}} } @@ -64,32 +67,26 @@ func callingAnInitializerStructWithOwner(x: Klass) -> StructWithOwner { } struct KlassPair { - var lhs: Klass // expected-remark {{retain of type 'Klass'}} - // expected-note @-1 {{of 'self.lhs'}} - // expected-remark @-2 {{release of type 'Klass'}} - // expected-note @-3 {{of 'self.lhs'}} - var rhs: Klass // expected-remark {{retain of type 'Klass'}} - // expected-note @-1 {{of 'self.rhs'}} - // expected-remark @-2 {{release of type 'Klass'}} - // expected-note @-3 {{of 'self.rhs'}} + var lhs: Klass + var rhs: Klass } func printKlassPair(x : KlassPair) { // We pattern match columns to ensure we get retain on the p and release on // the end ')' - print(x) // expected-remark @:5 {{retain of type 'Klass'}} - // expected-note @-4:21 {{of 'x.lhs'}} - // expected-remark @-2:5 {{retain of type 'Klass'}} - // expected-note @-6:21 {{of 'x.rhs'}} - // This is a release for Array for print. + print(x) // expected-remark @:11 {{heap allocated ref of type}} + // expected-remark @-1:5 {{retain of type 'Klass'}} + // expected-note @-5:21 {{of 'x.lhs'}} + // expected-remark @-3:5 {{retain of type 'Klass'}} + // expected-note @-7:21 {{of 'x.rhs'}} // expected-remark @-5:12 {{release of type}} } func printKlassPairLHS(x : KlassPair) { // We print the remarks at the 'p' and at the ending ')'. - print(x.lhs) // expected-remark @:5 {{retain of type 'Klass'}} - // expected-note @-3:24 {{of 'x.lhs'}} - // Release for Array needed for print. + print(x.lhs) // expected-remark @:11 {{heap allocated ref of type}} + // expected-remark @-1:5 {{retain of type 'Klass'}} + // expected-note @-4:24 {{of 'x.lhs'}} // expected-remark @-3:16 {{release of type}} } @@ -108,20 +105,21 @@ func callingAnInitializerKlassPair(x: Klass, y: Klass) -> KlassPair { func printKlassTuplePair(x : (Klass, Klass)) { // We pattern match columns to ensure we get retain on the p and release on // the end ')' - print(x) // expected-remark @:5 {{retain of type 'Klass'}} - // expected-note @-4:26 {{of 'x'}} - // expected-remark @-2:5 {{retain of type 'Klass'}} - // expected-note @-6:26 {{of 'x'}} - // Release on temp array for print(...). + print(x) // expected-remark @:11 {{heap allocated ref of type}} + // expected-remark @-1:5 {{retain of type 'Klass'}} + // expected-note @-5:26 {{of 'x'}} + // expected-remark @-3:5 {{retain of type 'Klass'}} + // expected-note @-7:26 {{of 'x'}} // expected-remark @-5:12 {{release of type}} } func printKlassTupleLHS(x : (Klass, Klass)) { // We print the remarks at the 'p' and at the ending ')'. - print(x.0) // expected-remark @:5 {{retain of type 'Klass'}} - // expected-note @-3:25 {{of 'x'}} + print(x.0) // expected-remark @:11 {{heap allocated ref of type}} + // expected-remark @-1:5 {{retain of type 'Klass'}} + // expected-note @-4:25 {{of 'x'}} // Release on Array for print. - // expected-remark @-3:14 {{release of type}} + // expected-remark @-4:14 {{release of type}} } func returnKlassTupleLHS(x: (Klass, Klass)) -> Klass { @@ -189,19 +187,22 @@ func castAsQuestionDiamondGEP2(x: KlassPair) { // expected-remark @-2:39 {{retain of type 'Klass'}} // expected-note @-4 {{of 'x.rhs'}} case let (.some(x1), .some(x2)): - print(x1, x2) // expected-remark {{retain of type 'Optional'}} + print(x1, x2) // expected-remark @:15 {{heap allocated ref of type}} // expected-remark @-1 {{retain of type 'Optional'}} - // expected-remark @-2 {{release of type}} - // expected-remark @-3 {{release of type 'Optional'}} + // expected-remark @-2 {{retain of type 'Optional'}} + // expected-remark @-3 {{release of type}} // expected-remark @-4 {{release of type 'Optional'}} + // expected-remark @-5 {{release of type 'Optional'}} case let (.some(x1), nil): - print(x1) // expected-remark {{retain of type 'SubKlass'}} - // expected-remark @-1 {{release of type}} - // expected-remark @-2 {{release of type 'Optional'}} + print(x1) // expected-remark @:15 {{heap allocated ref of type}} + // expected-remark @-1 {{retain of type 'SubKlass'}} + // expected-remark @-2 {{release of type}} + // expected-remark @-3 {{release of type 'Optional'}} case let (nil, .some(x2)): - print(x2) // expected-remark {{retain of type 'SubKlass'}} - // expected-remark @-1 {{release of type}} - // expected-remark @-2 {{release of type 'Optional'}} + print(x2) // expected-remark @:15 {{heap allocated ref of type}} + // expected-remark @-1 {{retain of type 'SubKlass'}} + // expected-remark @-2 {{release of type}} + // expected-remark @-3 {{release of type 'Optional'}} case (nil, nil): break } @@ -241,3 +242,45 @@ func inoutKlassQuestionCastArgument2(x: inout Klass?) -> SubKlass? { return x as? SubKlass // expected-remark {{retain of type 'Klass'}} // expected-note @-2 {{of 'x.some'}} } + +// We should have 1x rr remark here on calleeX for storing it into the array to +// print. Release is from the array. We don't pattern match it due to the actual +// underlying Array type name changing under the hood in between platforms. +@inline(__always) +func alwaysInlineCallee(_ calleeX: Klass) { + print(calleeX) // expected-remark @:11 {{heap allocated ref of type}} + // expected-remark @-1:5 {{retain of type 'Klass'}} + // expected-note @-3:27 {{of 'calleeX'}} + // expected-remark @-3:18 {{release of type}} +} + +// We should have 3x rr remarks here on callerX and none on calleeX. All of the +// releases are for the temporary array that we pass into print. +// +// TODO: Should we print out as notes the whole inlined call stack? +func alwaysInlineCaller(_ callerX: Klass) { + alwaysInlineCallee(callerX) // expected-remark @:5 {{heap allocated ref of type}} + // expected-remark @-1:5 {{retain of type 'Klass'}} + // expected-note @-3:27 {{of 'callerX'}} + // expected-remark @-3:31 {{release of type}} + print(callerX) // expected-remark @:11 {{heap allocated ref of type}} + // expected-remark @-1:5 {{retain of type 'Klass'}} + // expected-note @-7:27 {{of 'callerX'}} + // expected-remark @-3:18 {{release of type}} + alwaysInlineCallee(callerX) // expected-remark @:5 {{heap allocated ref of type}} + // expected-remark @-1:5 {{retain of type 'Klass'}} + // expected-note @-11:27 {{of 'callerX'}} + // expected-remark @-3:31 {{release of type}} +} + +func allocateValue() { + // Remark should be on Klass and note should be on k. + let k = Klass() // expected-remark @:13 {{heap allocated ref of type 'Klass'}} + // expected-note @-1:9 {{of 'k'}} + print(k) // expected-remark @:11 {{heap allocated ref of type}} + // expected-remark @-1:5 {{retain of type 'Klass'}} + // expected-note @-4:9 {{of 'k'}} + // expected-remark @-3:12 {{release of type}} + // expected-remark @-4:12 {{release of type 'Klass'}} + // expected-note @-7:9 {{of 'k'}} +} diff --git a/test/SILOptimizer/semantic-arc-opts.sil b/test/SILOptimizer/semantic-arc-opts.sil index aac4e3eb35ddf..ac0de9fae5479 100644 --- a/test/SILOptimizer/semantic-arc-opts.sil +++ b/test/SILOptimizer/semantic-arc-opts.sil @@ -32,7 +32,10 @@ protocol MyFakeAnyObject : Klass { func myFakeMethod() } -final class Klass {} +final class Klass { + var base: Klass +} + extension Klass : MyFakeAnyObject { func myFakeMethod() } @@ -1512,6 +1515,31 @@ bb3: return %9999 : $() } +// CHECK-LABEL: sil [ossa] @switch_enum_test_loadcopy_with_leaked_enum_case : $@convention(thin) (@owned FakeOptional) -> () { +// CHECK-NOT: load [copy] +// CHECK: load_borrow +// CHECK-NOT: load [copy] +// CHECK: } // end sil function 'switch_enum_test_loadcopy_with_leaked_enum_case' +sil [ossa] @switch_enum_test_loadcopy_with_leaked_enum_case : $@convention(thin) (@owned FakeOptional) -> () { +bb0(%0 : @owned $FakeOptional): + %0a = alloc_stack $FakeOptional + store %0 to [init] %0a : $*FakeOptional + %1 = load [copy] %0a : $*FakeOptional + switch_enum %1 : $FakeOptional, case #FakeOptional.some!enumelt: bb1, case #FakeOptional.none!enumelt: bb2 + +bb1(%2 : @owned $Builtin.NativeObject): + unreachable + +bb2: + br bb3 + +bb3: + destroy_addr %0a : $*FakeOptional + dealloc_stack %0a : $*FakeOptional + %9999 = tuple() + return %9999 : $() +} + // CHECK-LABEL: sil [ossa] @switch_enum_test_copyvalue_no_default : $@convention(thin) (@guaranteed FakeOptional) -> () { // CHECK-NOT: copy_value // CHECK: } // end sil function 'switch_enum_test_copyvalue_no_default' @@ -2568,3 +2596,46 @@ bb0(%0 : @guaranteed $Builtin.NativeObject, %1 : @guaranteed $Builtin.NativeObje %9999 = tuple() return %9999 : $() } + +// Make sure that we properly handle this case with out parameters and don't +// crash due to the SILArgument in bb3. +// +// CHECK-LABEL: sil [ossa] @iterated_transforming_terminator : $@convention(method) (@guaranteed Builtin.NativeObject) -> @out FakeOptional { +// CHECK-NOT: copy_value +// CHECK-NOT: @owned +// CHECK: } // end sil function 'iterated_transforming_terminator' +sil [ossa] @iterated_transforming_terminator : $@convention(method) (@guaranteed Builtin.NativeObject) -> @out FakeOptional { +bb0(%0 : $*FakeOptional, %1 : @guaranteed $Builtin.NativeObject): + %3 = init_enum_data_addr %0 : $*FakeOptional, #FakeOptional.some!enumelt + %4 = copy_value %1 : $Builtin.NativeObject + checked_cast_br %4 : $Builtin.NativeObject to Klass, bb1, bb2 + +bb1(%7 : @owned $Klass): + %8 = enum $FakeOptional, #FakeOptional.some!enumelt, %7 : $Klass + br bb3(%8 : $FakeOptional) + +bb2(%10 : @owned $Builtin.NativeObject): + destroy_value %10 : $Builtin.NativeObject + %12 = enum $FakeOptional, #FakeOptional.none!enumelt + br bb3(%12 : $FakeOptional) + +bb3(%14 : @owned $FakeOptional): + switch_enum %14 : $FakeOptional, case #FakeOptional.some!enumelt: bb4, case #FakeOptional.none!enumelt: bb6 + +bb4(%16 : @owned $Klass): + %17 = begin_borrow %16 : $Klass + %18 = ref_element_addr %17 : $Klass, #Klass.base + copy_addr %18 to [initialization] %3 : $*Klass + end_borrow %17 : $Klass + destroy_value %16 : $Klass + inject_enum_addr %0 : $*FakeOptional, #FakeOptional.some!enumelt + br bb5 + +bb5: + %24 = tuple () + return %24 : $() + +bb6: + inject_enum_addr %0 : $*FakeOptional, #FakeOptional.none!enumelt + br bb5 +} diff --git a/test/SILOptimizer/static_initializer.sil b/test/SILOptimizer/static_initializer.sil index bcdb29794c702..dbc5e28526a4f 100644 --- a/test/SILOptimizer/static_initializer.sil +++ b/test/SILOptimizer/static_initializer.sil @@ -25,8 +25,8 @@ sil_global private @globalinit_token0 : $Builtin.Word // CHECK-NEXT: } sil_global @_Tv2ch1xSi : $Outer -// CHECK-LABEL: sil private @globalinit_func0 : $@convention(c) () -> () { -sil private @globalinit_func0 : $@convention(c) () -> () { +// CHECK-LABEL: sil private [global_init_once_fn] @globalinit_func0 : $@convention(c) () -> () { +sil private [global_init_once_fn] @globalinit_func0 : $@convention(c) () -> () { bb0: %0 = global_addr @_Tv2ch1xSi : $*Outer %1 = integer_literal $Builtin.Int32, 2 diff --git a/test/SPI/Inputs/ioi_helper.swift b/test/SPI/Inputs/ioi_helper.swift new file mode 100644 index 0000000000000..f885a21d07f60 --- /dev/null +++ b/test/SPI/Inputs/ioi_helper.swift @@ -0,0 +1 @@ +public struct IOIPublicStruct {} diff --git a/test/SPI/experimental_spi_imports_swiftinterface.swift b/test/SPI/experimental_spi_imports_swiftinterface.swift index 76a50f21796da..35d715424d387 100644 --- a/test/SPI/experimental_spi_imports_swiftinterface.swift +++ b/test/SPI/experimental_spi_imports_swiftinterface.swift @@ -4,7 +4,7 @@ /// Generate 3 empty modules. // RUN: touch %t/empty.swift -// RUN: %target-swift-frontend -emit-module %t/empty.swift -module-name ExperimentalImported -emit-module-path %t/ExperimentalImported.swiftmodule -swift-version 5 -enable-library-evolution +// RUN: %target-swift-frontend -emit-module %S/Inputs/ioi_helper.swift -module-name ExperimentalImported -emit-module-path %t/ExperimentalImported.swiftmodule -swift-version 5 -enable-library-evolution // RUN: %target-swift-frontend -emit-module %t/empty.swift -module-name IOIImported -emit-module-path %t/IOIImported.swiftmodule -swift-version 5 -enable-library-evolution // RUN: %target-swift-frontend -emit-module %t/empty.swift -module-name SPIImported -emit-module-path %t/SPIImported.swiftmodule -swift-version 5 -enable-library-evolution @@ -24,3 +24,10 @@ @_spi(dummy) import SPIImported // CHECK-PUBLIC: {{^}}import SPIImported // CHECK-PRIVATE: @_spi{{.*}} import SPIImported + +@_spi(X) +extension IOIPublicStruct { + public func foo() {} +} +// CHECK-PUBLIC-NOT: IOIPublicStruct +// CHECK-PRIVATE: @_spi{{.*}} extension IOIPublicStruct diff --git a/test/SPI/private_swiftinterface.swift b/test/SPI/private_swiftinterface.swift index 6af2d40bc51f2..9473a265af173 100644 --- a/test/SPI/private_swiftinterface.swift +++ b/test/SPI/private_swiftinterface.swift @@ -3,6 +3,7 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend -emit-module %S/Inputs/spi_helper.swift -module-name SPIHelper -emit-module-path %t/SPIHelper.swiftmodule -swift-version 5 -enable-library-evolution -emit-module-interface-path %t/SPIHelper.swiftinterface -emit-private-module-interface-path %t/SPIHelper.private.swiftinterface +// RUN: %target-swift-frontend -emit-module %S/Inputs/ioi_helper.swift -module-name IOIHelper -emit-module-path %t/IOIHelper.swiftmodule -swift-version 5 -enable-library-evolution -emit-module-interface-path %t/IOIHelper.swiftinterface -emit-private-module-interface-path %t/IOIHelper.private.swiftinterface /// Make sure that the public swiftinterface of spi_helper doesn't leak SPI. // RUN: %FileCheck -check-prefix=CHECK-HELPER %s < %t/SPIHelper.swiftinterface @@ -25,6 +26,7 @@ // CHECK-PUBLIC: import SPIHelper // CHECK-PRIVATE: @_spi(OtherSPI) @_spi(HelperSPI) import SPIHelper +@_implementationOnly import IOIHelper public func foo() {} // CHECK-PUBLIC: foo() // CHECK-PRIVATE: foo() @@ -155,6 +157,11 @@ extension PublicType: SPIProto2 where T: SPIProto2 {} // CHECK-PRIVATE: extension PublicType : {{.*}}.SPIProto2 where T : {{.*}}.SPIProto2 // CHECK-PUBLIC-NOT: _ConstraintThatIsNotPartOfTheAPIOfThisLibrary +public protocol LocalPublicProto {} +extension IOIPublicStruct : LocalPublicProto {} +// CHECK-PRIVATE-NOT: IOIPublicStruct +// CHECK-PUBLIC-NOT: IOIPublicStruct + // The dummy conformance should be only in the private swiftinterface for // SPI extensions. @_spi(LocalSPI) diff --git a/test/ScanDependencies/Inputs/CHeaders/G.h b/test/ScanDependencies/Inputs/CHeaders/G.h index ef09c49a98e0f..4da23ffcbb4f6 100644 --- a/test/ScanDependencies/Inputs/CHeaders/G.h +++ b/test/ScanDependencies/Inputs/CHeaders/G.h @@ -1 +1,6 @@ +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 110000 +#include "X.h" +#endif + void funcG(void); + diff --git a/test/ScanDependencies/Inputs/CHeaders/H.h b/test/ScanDependencies/Inputs/CHeaders/H.h new file mode 100644 index 0000000000000..9c4b66d8f0e84 --- /dev/null +++ b/test/ScanDependencies/Inputs/CHeaders/H.h @@ -0,0 +1,5 @@ +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 110000 +#include "I.h" +#endif + +void funcH(void); diff --git a/test/ScanDependencies/Inputs/CHeaders/I.h b/test/ScanDependencies/Inputs/CHeaders/I.h new file mode 100644 index 0000000000000..d9ddc05cc65b4 --- /dev/null +++ b/test/ScanDependencies/Inputs/CHeaders/I.h @@ -0,0 +1 @@ +void funcI(void); diff --git a/test/ScanDependencies/Inputs/CHeaders/X.h b/test/ScanDependencies/Inputs/CHeaders/X.h new file mode 100644 index 0000000000000..11c123884ef12 --- /dev/null +++ b/test/ScanDependencies/Inputs/CHeaders/X.h @@ -0,0 +1 @@ +void funcX(void); diff --git a/test/ScanDependencies/Inputs/CHeaders/module.modulemap b/test/ScanDependencies/Inputs/CHeaders/module.modulemap index dbd29ce9d9739..95fc7fef133c2 100644 --- a/test/ScanDependencies/Inputs/CHeaders/module.modulemap +++ b/test/ScanDependencies/Inputs/CHeaders/module.modulemap @@ -27,3 +27,18 @@ module G { header "G.h" export * } + +module H { + header "H.h" + export * +} + +module I { + header "I.h" + export * +} + +module X { + header "X.h" + export * +} diff --git a/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift b/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift index 464afba79f014..4c84230cd4efb 100644 --- a/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift +++ b/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift @@ -90,6 +90,9 @@ struct SwiftModuleDetails: Codable { /// arguments to the generic PCM build arguments reported from the dependency /// graph. var extraPcmArgs: [String]? + + /// A flag to indicate whether or not this module is a framework. + var isFramework: Bool } /// Details specific to Swift external modules. diff --git a/test/ScanDependencies/batch_module_scan.swift b/test/ScanDependencies/batch_module_scan.swift new file mode 100644 index 0000000000000..59189771b340f --- /dev/null +++ b/test/ScanDependencies/batch_module_scan.swift @@ -0,0 +1,40 @@ +// RUN: %empty-directory(%t) +// RUN: %empty-directory(%t/inputs) +// RUN: %empty-directory(%t/outputs) +// RUN: mkdir -p %t/clang-module-cache + +// RUN: echo "[{" > %/t/inputs/input.json +// RUN: echo "\"swiftModuleName\": \"F\"," >> %/t/inputs/input.json +// RUN: echo "\"arguments\": \"-target x86_64-apple-macosx10.9\"," >> %/t/inputs/input.json +// RUN: echo "\"output\": \"%/t/outputs/F.swiftmodule.json\"" >> %/t/inputs/input.json +// RUN: echo "}," >> %/t/inputs/input.json +// RUN: echo "{" >> %/t/inputs/input.json +// RUN: echo "\"clangModuleName\": \"F\"," >> %/t/inputs/input.json +// RUN: echo "\"arguments\": \"-target x86_64-apple-macosx10.9\"," >> %/t/inputs/input.json +// RUN: echo "\"output\": \"%/t/outputs/F.pcm.json\"" >> %/t/inputs/input.json +// RUN: echo "}]" >> %/t/inputs/input.json + +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -batch-scan-input-file %/t/inputs/input.json + +// Check the contents of the JSON output +// RUN: %FileCheck %s -check-prefix=CHECK-PCM < %t/outputs/F.pcm.json +// RUN: %FileCheck %s -check-prefix=CHECK-SWIFT < %t/outputs/F.swiftmodule.json + +// CHECK-PCM: { +// CHECK-PCM-NEXT: "mainModuleName": "F", +// CHECK-PCM-NEXT: "modules": [ +// CHECK-PCM-NEXT: { +// CHECK-PCM-NEXT: "clang": "F" +// CHECK-PCM-NEXT: }, +// CHECK-PCM-NEXT: { +// CHECK-PCM-NEXT: "modulePath": "F.pcm", +// CHECK-PCM: "-I + +// CHECK-SWIFT: { +// CHECK-SWIFT-NEXT: "mainModuleName": "F", +// CHECK-SWIFT-NEXT: "modules": [ +// CHECK-SWIFT-NEXT: { +// CHECK-SWIFT-NEXT: "swift": "F" +// CHECK-SWIFT-NEXT: }, +// CHECK-SWIFT-NEXT: { +// CHECK-SWIFT-NEXT: "modulePath": "F.swiftmodule", diff --git a/test/ScanDependencies/batch_module_scan_arguments.swift b/test/ScanDependencies/batch_module_scan_arguments.swift new file mode 100644 index 0000000000000..65f2320766ec7 --- /dev/null +++ b/test/ScanDependencies/batch_module_scan_arguments.swift @@ -0,0 +1,24 @@ +// RUN: %empty-directory(%t) +// RUN: %empty-directory(%t/inputs) +// RUN: %empty-directory(%t/outputs) +// RUN: mkdir -p %t/clang-module-cache + +// RUN: echo "[{" > %/t/inputs/input.json +// RUN: echo "\"clangModuleName\": \"H\"," >> %/t/inputs/input.json +// RUN: echo "\"arguments\": \"-target x86_64-apple-macosx10.9\"," >> %/t/inputs/input.json +// RUN: echo "\"output\": \"%/t/outputs/H.10.9.pcm.json\"" >> %/t/inputs/input.json +// RUN: echo "}," >> %/t/inputs/input.json +// RUN: echo "{" >> %/t/inputs/input.json +// RUN: echo "\"clangModuleName\": \"H\"," >> %/t/inputs/input.json +// RUN: echo "\"arguments\": \"-target x86_64-apple-macosx11.0\"," >> %/t/inputs/input.json +// RUN: echo "\"output\": \"%/t/outputs/H.11.0.pcm.json\"" >> %/t/inputs/input.json +// RUN: echo "}]" >> %/t/inputs/input.json + +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -batch-scan-input-file %/t/inputs/input.json + +// Check the contents of the JSON output +// RUN: %FileCheck %s -check-prefix=CHECK-TEN < %t/outputs/H.10.9.pcm.json +// RUN: %FileCheck %s -check-prefix=CHECK-ELEVEN < %t/outputs/H.11.0.pcm.json + +// CHECK-TEN: "clang": "I" +// CHECK-ELEVEN-NOT: "clang": "I" diff --git a/test/ScanDependencies/batch_module_scan_versioned.swift b/test/ScanDependencies/batch_module_scan_versioned.swift new file mode 100644 index 0000000000000..02725a2ff0160 --- /dev/null +++ b/test/ScanDependencies/batch_module_scan_versioned.swift @@ -0,0 +1,49 @@ +// RUN: %empty-directory(%t) +// RUN: %empty-directory(%t/inputs) +// RUN: %empty-directory(%t/outputs) +// RUN: mkdir -p %t/clang-module-cache + +// RUN: echo "[{" > %/t/inputs/input.json +// RUN: echo "\"clangModuleName\": \"G\"," >> %/t/inputs/input.json +// RUN: echo "\"arguments\": \"-Xcc -target -Xcc x86_64-apple-macosx10.9\"," >> %/t/inputs/input.json +// RUN: echo "\"output\": \"%/t/outputs/G_109.pcm.json\"" >> %/t/inputs/input.json +// RUN: echo "}," >> %/t/inputs/input.json +// RUN: echo "{" >> %/t/inputs/input.json +// RUN: echo "\"clangModuleName\": \"G\"," >> %/t/inputs/input.json +// RUN: echo "\"arguments\": \"-Xcc -target -Xcc x86_64-apple-macosx11.0\"," >> %/t/inputs/input.json +// RUN: echo "\"output\": \"%/t/outputs/G_110.pcm.json\"" >> %/t/inputs/input.json +// RUN: echo "}]" >> %/t/inputs/input.json + +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -batch-scan-input-file %/t/inputs/input.json + +// Check the contents of the JSON output +// RUN: %FileCheck %s -check-prefix=CHECK-PCM109 < %t/outputs/G_109.pcm.json +// RUN: %FileCheck %s -check-prefix=CHECK-PCM110 < %t/outputs/G_110.pcm.json + +// CHECK-PCM109: { +// CHECK-PCM109-NEXT: "mainModuleName": "G", +// CHECK-PCM109-NEXT: "modules": [ +// CHECK-PCM109-NEXT: { +// CHECK-PCM109-NEXT: "clang": "G" +// CHECK-PCM109-NEXT: }, +// CHECK-PCM109-NEXT: { +// CHECK-PCM109-NEXT: "modulePath": "G.pcm", +// CHECK-PCM109: "directDependencies": [ +// CHECK-PCM109-NEXT: { +// CHECK-PCM109-NEXT: "clang": "X" +// CHECK-PCM109-NEXT: } +// CHECK-PCM109-NEXT: ], +// CHECK-PCM109: "-I + +// CHECK-PCM110: { +// CHECK-PCM110-NEXT: "mainModuleName": "G", +// CHECK-PCM110-NEXT: "modules": [ +// CHECK-PCM110-NEXT: { +// CHECK-PCM110-NEXT: "clang": "G" +// CHECK-PCM110-NEXT: }, +// CHECK-PCM110-NEXT: { +// CHECK-PCM110-NEXT: "modulePath": "G.pcm", +// CHECK-PCM110: "directDependencies": [ +// CHECK-PCM110-NEXT: ], +// CHECK-PCM110-NOT: "clang": "X" +// CHECK-PCM110: "-I diff --git a/test/ScanDependencies/can_import_placeholder.swift b/test/ScanDependencies/can_import_placeholder.swift new file mode 100644 index 0000000000000..8c14c6b2a125e --- /dev/null +++ b/test/ScanDependencies/can_import_placeholder.swift @@ -0,0 +1,55 @@ +// RUN: %empty-directory(%t) +// RUN: mkdir -p %t/clang-module-cache +// RUN: mkdir -p %t/inputs + +// RUN: echo "[{" > %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"SomeExternalModule\"," >> %/t/inputs/map.json +// RUN: echo "\"modulePath\": \"%/t/inputs/SomeExternalModule.swiftmodule\"," >> %/t/inputs/map.json +// RUN: echo "\"docPath\": \"%/t/inputs/SomeExternalModule.swiftdoc\"," >> %/t/inputs/map.json +// RUN: echo "\"sourceInfoPath\": \"%/t/inputs/SomeExternalModule.swiftsourceinfo\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json +// RUN: echo "}," >> %/t/inputs/map.json +// RUN: echo "{" >> %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"Swift\"," >> %/t/inputs/map.json +// RUN: echo "\"modulePath\": \"%/stdlib_module\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json +// RUN: echo "}," >> %/t/inputs/map.json +// RUN: echo "{" >> %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"SwiftOnoneSupport\"," >> %/t/inputs/map.json +// RUN: echo "\"modulePath\": \"%/ononesupport_module\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json +// RUN: echo "}]" >> %/t/inputs/map.json + +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -placeholder-dependency-module-map-file %t/inputs/map.json -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 + +// Check the contents of the JSON output +// RUN: %FileCheck %s < %t/deps.json + +// REQUIRES: executable_test +// REQUIRES: objc_interop +#if canImport(SomeExternalModule) +import SomeExternalModule +#endif + +// CHECK: "mainModuleName": "deps" + +/// --------Main module +// CHECK-LABEL: "modulePath": "deps.swiftmodule", +// CHECK-NEXT: sourceFiles +// CHECK-NEXT: can_import_placeholder.swift + +// CHECK: directDependencies +// CHECK-NEXT: { +// CHECK-NEXT: "swiftPlaceholder": "SomeExternalModule" +// CHECK-NEXT: } +// CHECK-NEXT: { +// CHECK-NEXT: "swift": "Swift" +// CHECK-NEXT: } +// CHECK-NEXT: { +// CHECK-NEXT: "swift": "SwiftOnoneSupport" +// CHECK-NEXT: } +// CHECK-NEXT: { +// CHECK-NEXT: "swift": "F" +// CHECK-NEXT: } +// CHECK-NEXT: ], + diff --git a/test/ScanDependencies/can_import_with_map.swift b/test/ScanDependencies/can_import_with_map.swift index e21bf826fe038..3becb8115eb1f 100644 --- a/test/ScanDependencies/can_import_with_map.swift +++ b/test/ScanDependencies/can_import_with_map.swift @@ -8,15 +8,18 @@ // RUN: echo "\"moduleName\": \"Foo\"," >> %/t/inputs/map.json // RUN: echo "\"modulePath\": \"%/t/inputs/Foo.swiftmodule\"," >> %/t/inputs/map.json // RUN: echo "\"docPath\": \"%/t/inputs/Foo.swiftdoc\"," >> %/t/inputs/map.json -// RUN: echo "\"sourceInfoPath\": \"%/t/inputs/Foo.swiftsourceinfo\"" >> %/t/inputs/map.json +// RUN: echo "\"sourceInfoPath\": \"%/t/inputs/Foo.swiftsourceinfo\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}," >> %/t/inputs/map.json // RUN: echo "{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"Swift\"," >> %/t/inputs/map.json -// RUN: echo "\"modulePath\": \"%/stdlib_module\"" >> %/t/inputs/map.json +// RUN: echo "\"modulePath\": \"%/stdlib_module\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}," >> %/t/inputs/map.json // RUN: echo "{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"SwiftOnoneSupport\"," >> %/t/inputs/map.json -// RUN: echo "\"modulePath\": \"%/ononesupport_module\"" >> %/t/inputs/map.json +// RUN: echo "\"modulePath\": \"%/ononesupport_module\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}]" >> %/t/inputs/map.json // RUN: %target-swift-frontend -typecheck %s -explicit-swift-module-map-file %t/inputs/map.json -disable-implicit-swift-modules diff --git a/test/ScanDependencies/diagnose_dependency_cycle.swift b/test/ScanDependencies/diagnose_dependency_cycle.swift index 1157d364a7954..609fd331646eb 100644 --- a/test/ScanDependencies/diagnose_dependency_cycle.swift +++ b/test/ScanDependencies/diagnose_dependency_cycle.swift @@ -1,7 +1,7 @@ // RUN: %empty-directory(%t) // RUN: mkdir -p %t/clang-module-cache -// RUN: not %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -disable-implicit-swift-modules -Xcc -Xclang -Xcc -fno-implicit-modules &> %t/out.txt +// RUN: not %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 &> %t/out.txt // RUN: %FileCheck %s < %t/out.txt diff --git a/test/ScanDependencies/explicit-framework-irgen.swift b/test/ScanDependencies/explicit-framework-irgen.swift new file mode 100644 index 0000000000000..0ad514de35a2b --- /dev/null +++ b/test/ScanDependencies/explicit-framework-irgen.swift @@ -0,0 +1,37 @@ +// RUN: %empty-directory(%t) +// RUN: mkdir -p %t/clang-module-cache +// RUN: mkdir -p %t/inputs +// RUN: echo "/// Some cool comments" > %t/foo.swift +// RUN: echo "public func foo() {}" >> %t/foo.swift +// RUN: %target-swift-frontend -emit-module -emit-module-path %t/inputs/Foo.swiftmodule -emit-module-doc-path %t/inputs/Foo.swiftdoc -emit-module-source-info -emit-module-source-info-path %t/inputs/Foo.swiftsourceinfo -module-cache-path %t.module-cache %t/foo.swift -module-name Foo + +// RUN: echo "[{" > %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"Foo\"," >> %/t/inputs/map.json +// RUN: echo "\"modulePath\": \"%/t/inputs/Foo.swiftmodule\"," >> %/t/inputs/map.json +// RUN: echo "\"docPath\": \"%/t/inputs/Foo.swiftdoc\"," >> %/t/inputs/map.json +// RUN: echo "\"sourceInfoPath\": \"%/t/inputs/Foo.swiftsourceinfo\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": true" >> %/t/inputs/map.json +// RUN: echo "}," >> %/t/inputs/map.json +// RUN: echo "{" >> %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"Swift\"," >> %/t/inputs/map.json +// RUN: echo "\"modulePath\": \"%/stdlib_module\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json +// RUN: echo "}," >> %/t/inputs/map.json +// RUN: echo "{" >> %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"SwiftOnoneSupport\"," >> %/t/inputs/map.json +// RUN: echo "\"modulePath\": \"%/ononesupport_module\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json +// RUN: echo "}]" >> %/t/inputs/map.json + +// RUN: %target-swift-frontend -emit-object -emit-module -disable-implicit-swift-modules -explicit-swift-module-map-file %t/inputs/map.json -o %t/explicit-framework-irgen.o %s +import Foo + +// This test is to verify autolinking behavior so it is macOS-specific. +// REQUIRES: OS=macosx + +// RUN: otool -l %t/explicit-framework-irgen.o | %FileCheck %s +// CHECK: cmd LC_LINKER_OPTION +// CHECK-NEXT: cmdsize +// CHECK-NEXT: count +// CHECK-NEXT: string #1 -framework +// CHECK-NEXT: string #2 Foo diff --git a/test/ScanDependencies/explicit-module-map-forwarding-module.swift b/test/ScanDependencies/explicit-module-map-forwarding-module.swift index 5d3c3cfa82c60..c8b694cea201c 100644 --- a/test/ScanDependencies/explicit-module-map-forwarding-module.swift +++ b/test/ScanDependencies/explicit-module-map-forwarding-module.swift @@ -18,15 +18,18 @@ // RUN: echo "\"moduleName\": \"Foo\"," >> %/t/inputs/map.json // RUN: echo "\"modulePath\": \"%/t/inputs/Foo-from-interface.swiftmodule\"," >> %/t/inputs/map.json // RUN: echo "\"docPath\": \"%/t/inputs/Foo.swiftdoc\"," >> %/t/inputs/map.json -// RUN: echo "\"sourceInfoPath\": \"%/t/inputs/Foo.swiftsourceinfo\"" >> %/t/inputs/map.json +// RUN: echo "\"sourceInfoPath\": \"%/t/inputs/Foo.swiftsourceinfo\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}," >> %/t/inputs/map.json // RUN: echo "{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"Swift\"," >> %/t/inputs/map.json -// RUN: echo "\"modulePath\": \"%/stdlib_module\"" >> %/t/inputs/map.json +// RUN: echo "\"modulePath\": \"%/stdlib_module\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}," >> %/t/inputs/map.json // RUN: echo "{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"SwiftOnoneSupport\"," >> %/t/inputs/map.json -// RUN: echo "\"modulePath\": \"%/ononesupport_module\"" >> %/t/inputs/map.json +// RUN: echo "\"modulePath\": \"%/ononesupport_module\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}]" >> %/t/inputs/map.json // RUN: %target-swift-ide-test -print-module-comments -module-to-print=Foo -enable-swiftsourceinfo -source-filename %s -explicit-swift-module-map-file %t/inputs/map.json | %FileCheck %s diff --git a/test/ScanDependencies/explicit-module-map.swift b/test/ScanDependencies/explicit-module-map.swift index 821a6cfdc847f..77bfe5dd248f6 100644 --- a/test/ScanDependencies/explicit-module-map.swift +++ b/test/ScanDependencies/explicit-module-map.swift @@ -9,15 +9,18 @@ // RUN: echo "\"moduleName\": \"Foo\"," >> %/t/inputs/map.json // RUN: echo "\"modulePath\": \"%/t/inputs/Foo.swiftmodule\"," >> %/t/inputs/map.json // RUN: echo "\"docPath\": \"%/t/inputs/Foo.swiftdoc\"," >> %/t/inputs/map.json -// RUN: echo "\"sourceInfoPath\": \"%/t/inputs/Foo.swiftsourceinfo\"" >> %/t/inputs/map.json +// RUN: echo "\"sourceInfoPath\": \"%/t/inputs/Foo.swiftsourceinfo\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}," >> %/t/inputs/map.json // RUN: echo "{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"Swift\"," >> %/t/inputs/map.json -// RUN: echo "\"modulePath\": \"%/stdlib_module\"" >> %/t/inputs/map.json +// RUN: echo "\"modulePath\": \"%/stdlib_module\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}," >> %/t/inputs/map.json // RUN: echo "{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"SwiftOnoneSupport\"," >> %/t/inputs/map.json -// RUN: echo "\"modulePath\": \"%/ononesupport_module\"" >> %/t/inputs/map.json +// RUN: echo "\"modulePath\": \"%/ononesupport_module\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}]" >> %/t/inputs/map.json // RUN: %target-swift-ide-test -print-module-comments -module-to-print=Foo -enable-swiftsourceinfo -source-filename %s -explicit-swift-module-map-file %t/inputs/map.json | %FileCheck %s diff --git a/test/ScanDependencies/module_deps.swift b/test/ScanDependencies/module_deps.swift index 7e3a62507ed99..dc48ba5e0998d 100644 --- a/test/ScanDependencies/module_deps.swift +++ b/test/ScanDependencies/module_deps.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) // RUN: mkdir -p %t/clang-module-cache -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -disable-implicit-swift-modules -Xcc -Xclang -Xcc -fno-implicit-modules +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 // Check the contents of the JSON output // RUN: %FileCheck %s < %t/deps.json @@ -105,7 +105,6 @@ import SubE // CHECK-NEXT: "-only-use-extra-clang-opts" // CHECK-NEXT: "-Xcc" // CHECK-NEXT: "clang" -// CHECK: "-fno-implicit-modules" /// --------Swift module E // CHECK: "swift": "E" @@ -195,9 +194,7 @@ import SubE /// --------Clang module SwiftShims // CHECK-LABEL: "modulePath": "SwiftShims.pcm", -// CHECK-NO-SEARCH-PATHS-NOT: "-I" // CHECK-NO-SEARCH-PATHS-NOT: "-sdk" -// CHECK-NO-SEARCH-PATHS-NOT: "-F" // CHECK-NO-SEARCH-PATHS-NOT: "-prebuilt-module-cache-path" // Check make-style dependencies diff --git a/test/ScanDependencies/module_deps_clang_only.swift b/test/ScanDependencies/module_deps_clang_only.swift new file mode 100644 index 0000000000000..34ac0c6eeefd1 --- /dev/null +++ b/test/ScanDependencies/module_deps_clang_only.swift @@ -0,0 +1,21 @@ +// RUN: %empty-directory(%t) +// RUN: mkdir -p %t/clang-module-cache +// RUN: %target-swift-frontend -scan-clang-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -disable-implicit-swift-modules -module-name C + +// Check the contents of the JSON output +// RUN: %FileCheck %s < %t/deps.json + +// CHECK: "mainModuleName": "C", +// CHECK-NEXT: "modules": [ +// CHECK-NEXT: { +// CHECK-NEXT: "clang": "C" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "modulePath": "C.pcm", +// CHECK-NEXT: "sourceFiles": [ + + +// CHECK: "directDependencies": [ +// CHECK-NEXT: { +// CHECK-NEXT: "clang": "B" +// CHECK-NEXT: } diff --git a/test/ScanDependencies/module_deps_cross_import_overlay.swift b/test/ScanDependencies/module_deps_cross_import_overlay.swift index 7b1bfd9b63363..94031c4ce38bc 100644 --- a/test/ScanDependencies/module_deps_cross_import_overlay.swift +++ b/test/ScanDependencies/module_deps_cross_import_overlay.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) // RUN: mkdir -p %t/clang-module-cache -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -disable-implicit-swift-modules -Xcc -Xclang -Xcc -fno-implicit-modules +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 // Check the contents of the JSON output // RUN: %FileCheck %s < %t/deps.json diff --git a/test/ScanDependencies/module_deps_external.swift b/test/ScanDependencies/module_deps_external.swift index 601b60d62b4e7..f3b2147a487da 100644 --- a/test/ScanDependencies/module_deps_external.swift +++ b/test/ScanDependencies/module_deps_external.swift @@ -6,26 +6,21 @@ // RUN: echo "\"moduleName\": \"SomeExternalModule\"," >> %/t/inputs/map.json // RUN: echo "\"modulePath\": \"%/t/inputs/SomeExternalModule.swiftmodule\"," >> %/t/inputs/map.json // RUN: echo "\"docPath\": \"%/t/inputs/SomeExternalModule.swiftdoc\"," >> %/t/inputs/map.json -// RUN: echo "\"sourceInfoPath\": \"%/t/inputs/SomeExternalModule.swiftsourceinfo\"" >> %/t/inputs/map.json +// RUN: echo "\"sourceInfoPath\": \"%/t/inputs/SomeExternalModule.swiftsourceinfo\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}," >> %/t/inputs/map.json // RUN: echo "{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"Swift\"," >> %/t/inputs/map.json -// RUN: echo "\"modulePath\": \"%/stdlib_module\"" >> %/t/inputs/map.json +// RUN: echo "\"modulePath\": \"%/stdlib_module\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}," >> %/t/inputs/map.json // RUN: echo "{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"SwiftOnoneSupport\"," >> %/t/inputs/map.json -// RUN: echo "\"modulePath\": \"%/ononesupport_module\"" >> %/t/inputs/map.json +// RUN: echo "\"modulePath\": \"%/ononesupport_module\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}]" >> %/t/inputs/map.json - -// RUN: echo "[{" > %/t/inputs/map.json -// RUN: echo "\"moduleName\": \"SomeExternalModule\"," >> %/t/inputs/map.json -// RUN: echo "\"modulePath\": \"%/t/inputs/SomeExternalModule.swiftmodule\"," >> %/t/inputs/map.json -// RUN: echo "\"docPath\": \"%/t/inputs/SomeExternalModule.swiftdoc\"," >> %/t/inputs/map.json -// RUN: echo "\"sourceInfoPath\": \"%/t/inputs/SomeExternalModule.swiftsourceinfo\"" >> %/t/inputs/map.json -// RUN: echo "}]" >> %/t/inputs/map.json - -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -placeholder-dependency-module-map-file %t/inputs/map.json -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -disable-implicit-swift-modules -Xcc -Xclang -Xcc -fno-implicit-modules +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -placeholder-dependency-module-map-file %t/inputs/map.json -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 // Check the contents of the JSON output // RUN: %FileCheck %s < %t/deps.json diff --git a/test/ScanDependencies/module_deps_private_interface.swift b/test/ScanDependencies/module_deps_private_interface.swift new file mode 100644 index 0000000000000..2098775216ea8 --- /dev/null +++ b/test/ScanDependencies/module_deps_private_interface.swift @@ -0,0 +1,16 @@ +// RUN: %empty-directory(%t) +// RUN: mkdir -p %t/clang-module-cache +// RUN: echo "// swift-interface-format-version: 1.0" > %t/Foo.swiftinterface +// RUN: echo "// swift-module-flags: -module-name Foo" >> %t/Foo.swiftinterface +// RUN: echo "public func foo() {}" >> %t/Foo.swiftinterface + +// RUN: cp %t/Foo.swiftinterface %t/Foo.private.swiftinterface + +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %t + +// Check the contents of the JSON output +// RUN: %FileCheck %s < %t/deps.json + +import Foo + +// CHECK: "moduleInterfacePath": "{{.*}}Foo.private.swiftinterface", diff --git a/test/ScanDependencies/module_framework.swift b/test/ScanDependencies/module_framework.swift new file mode 100644 index 0000000000000..9756277074277 --- /dev/null +++ b/test/ScanDependencies/module_framework.swift @@ -0,0 +1,23 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -emit-dependencies -emit-dependencies-path %t/deps.d -swift-version 4 -Xcc -Xclang + +// Check the contents of the JSON output +// RUN: %FileCheck %s < %t/deps.json +// REQUIRES: OS=macosx + +import CryptoKit + +// CHECK: "mainModuleName": "deps" +// CHECK: directDependencies +// CHECK-NEXT: { +// CHECK-NEXT: "swift": "CryptoKit" +// CHECK-NEXT: } +// CHECK-NEXT: { +// CHECK-NEXT: "swift": "Swift" +// CHECK-NEXT: } +// CHECK-NEXT: { +// CHECK-NEXT: "swift": "SwiftOnoneSupport" +// CHECK-NEXT: } +// CHECK-NEXT: ], + +// CHECK: "isFramework": true diff --git a/test/ScanDependencies/module_not_found.swift b/test/ScanDependencies/module_not_found.swift index 1674f380b3732..8fd238eba6736 100644 --- a/test/ScanDependencies/module_not_found.swift +++ b/test/ScanDependencies/module_not_found.swift @@ -7,10 +7,12 @@ // RUN: echo "[{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"Swift\"," >> %/t/inputs/map.json // RUN: echo "\"modulePath\": \"%stdlib_dir/Swift.swiftmodule/%module-target-triple.swiftmodule\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}," >> %/t/inputs/map.json // RUN: echo "{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"SwiftOnoneSupport\"," >> %/t/inputs/map.json // RUN: echo "\"modulePath\": \"%stdlib_dir/SwiftOnoneSupport.swiftmodule/%module-target-triple.swiftmodule\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}]" >> %/t/inputs/map.json // Add the -I search path to ensure we do not accidentally implicitly load Foo.swiftmodule diff --git a/test/Sema/Inputs/fixits-derived-conformances-multifile.swift b/test/Sema/Inputs/fixits-derived-conformances-multifile.swift new file mode 100644 index 0000000000000..7512251332dbd --- /dev/null +++ b/test/Sema/Inputs/fixits-derived-conformances-multifile.swift @@ -0,0 +1,6 @@ +public enum Enum { case one } // expected-note {{type declared here}} +public enum GenericEnum { case one(Int) } // expected-note {{type declared here}} + +public struct Struct {} // expected-note {{type declared here}} +public struct GenericStruct {} // expected-note {{type declared here}} + diff --git a/test/Sema/enum_conformance_synthesis.swift b/test/Sema/enum_conformance_synthesis.swift index 494d1b3480b32..c486385669cda 100644 --- a/test/Sema/enum_conformance_synthesis.swift +++ b/test/Sema/enum_conformance_synthesis.swift @@ -224,7 +224,7 @@ enum Complex2 { } extension Complex2 : Hashable {} extension Complex2 : CaseIterable {} // expected-error {{type 'Complex2' does not conform to protocol 'CaseIterable'}} -extension FromOtherFile: CaseIterable {} // expected-error {{cannot be automatically synthesized in an extension in a different file to the type}} +extension FromOtherFile: CaseIterable {} // expected-error {{extension outside of file declaring enum 'FromOtherFile' prevents automatic synthesis of 'allCases' for protocol 'CaseIterable'}} extension CaseIterableAcrossFiles: CaseIterable { public static var allCases: [CaseIterableAcrossFiles] { return [ .A ] @@ -248,7 +248,7 @@ extension OtherFileNonconforming: Hashable { func hash(into hasher: inout Hasher) {} } // ...but synthesis in a type defined in another file doesn't work yet. -extension YetOtherFileNonconforming: Equatable {} // expected-error {{cannot be automatically synthesized in an extension in a different file to the type}} +extension YetOtherFileNonconforming: Equatable {} // expected-error {{extension outside of file declaring enum 'YetOtherFileNonconforming' prevents automatic synthesis of '==' for protocol 'Equatable'}} extension YetOtherFileNonconforming: CaseIterable {} // expected-error {{does not conform}} // Verify that an indirect enum doesn't emit any errors as long as its "leaves" @@ -319,7 +319,7 @@ extension UnusedGenericDeriveExtension: Hashable {} // Cross-file synthesis is disallowed for conditional cases just as it is for // non-conditional ones. extension GenericOtherFileNonconforming: Equatable where T: Equatable {} -// expected-error@-1{{implementation of 'Equatable' cannot be automatically synthesized in an extension in a different file to the type}} +// expected-error@-1{{extension outside of file declaring generic enum 'GenericOtherFileNonconforming' prevents automatic synthesis of '==' for protocol 'Equatable'}} // rdar://problem/41852654 diff --git a/test/Sema/fixits-derived-conformances.swift b/test/Sema/fixits-derived-conformances.swift new file mode 100644 index 0000000000000..7d63103ed135c --- /dev/null +++ b/test/Sema/fixits-derived-conformances.swift @@ -0,0 +1,21 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift -emit-module -emit-library -module-name Types %S/Inputs/fixits-derived-conformances-multifile.swift -o %t/%target-library-name(Types) +// RUN: %swift -typecheck -target %target-triple -I %t -diagnostics-editor-mode -verify %s + +import Types + +extension GenericEnum: Equatable { } +// expected-error@-1 {{extension outside of file declaring generic enum 'GenericEnum' prevents automatic synthesis of '==' for protocol 'Equatable'}} +// expected-note@-2 {{do you want to add protocol stubs?}}{{35-35=\n public static func == (lhs: GenericEnum, rhs: GenericEnum) -> Bool {\n <#code#>\n \}\n}} + +extension Struct: Equatable { } +// expected-error@-1 {{extension outside of file declaring struct 'Struct' prevents automatic synthesis of '==' for protocol 'Equatable'}} +// expected-note@-2 {{do you want to add protocol stubs?}}{{30-30=\n public static func == (lhs: Struct, rhs: Struct) -> Bool {\n <#code#>\n \}\n}} +extension GenericStruct: Equatable { } +// expected-error@-1 {{extension outside of file declaring generic struct 'GenericStruct' prevents automatic synthesis of '==' for protocol 'Equatable'}} +// expected-note@-2 {{do you want to add protocol stubs?}}{{37-37=\n public static func == (lhs: GenericStruct, rhs: GenericStruct) -> Bool {\n <#code#>\n \}\n}} + +extension Enum: CaseIterable { } +// expected-error@-1 {{extension outside of file declaring enum 'Enum' prevents automatic synthesis of 'allCases' for protocol 'CaseIterable'}} +// expected-note@-2 {{do you want to add protocol stubs?}}{{31-31=\n public static var allCases: [Enum]\n}} + diff --git a/test/Sema/immutability.swift b/test/Sema/immutability.swift index beae8a87fa53e..d43c5c299b806 100644 --- a/test/Sema/immutability.swift +++ b/test/Sema/immutability.swift @@ -61,13 +61,13 @@ class FooClass { mutating init(a : Bool) {} // expected-error {{'mutating' may only be used on 'func' declarations}} {{3-12=}} - mutating // expected-error {{'mutating' isn't valid on methods in classes or class-bound protocols}} {{3-12=}} + mutating // expected-error {{'mutating' is not valid on instance methods in classes}} {{3-12=}} func baz() {} - nonmutating // expected-error {{'nonmutating' isn't valid on methods in classes or class-bound protocols}} {{3-15=}} + nonmutating // expected-error {{'nonmutating' is not valid on instance methods in classes}} {{3-15=}} func bay() {} - mutating nonmutating // expected-error {{'mutating' isn't valid on methods in classes or class-bound protocols}} expected-error {{'nonmutating' isn't valid on methods in classes or class-bound protocols}} + mutating nonmutating // expected-error {{'mutating' is not valid on instance methods in classes}} expected-error {{'nonmutating' is not valid on instance methods in classes}} func bax() {} var x : Int { @@ -86,6 +86,15 @@ class FooClass { } } + var computed: Int { + mutating get { 0 } // expected-error {{'mutating' is not valid on getters in classes}} {{5-14=}} + nonmutating set {} // expected-error {{'nonmutating' is not valid on setters in classes}} {{5-17=}} + } + + var storedWithObservers: Int = 0 { + mutating willSet {} // expected-error {{'mutating' is not valid on willSet observers in classes}} {{5-14=}} + nonmutating didSet {} // expected-error {{'nonmutating' is not valid on didSet observers in classes}} {{5-17=}} + } } @@ -241,7 +250,7 @@ func test_arguments(_ a : Int, protocol ClassBoundProtocolMutating : class { - mutating // expected-error {{'mutating' isn't valid on methods in classes or class-bound protocols}} {{3-12=}} + mutating // expected-error {{'mutating' is not valid on instance methods in class-bound protocols}} {{3-12=}} func f() } diff --git a/test/Sema/struct_equatable_hashable.swift b/test/Sema/struct_equatable_hashable.swift index be162f1abd1a2..1f9e2a2d3d42a 100644 --- a/test/Sema/struct_equatable_hashable.swift +++ b/test/Sema/struct_equatable_hashable.swift @@ -114,8 +114,10 @@ struct StructWithoutExplicitConformance { } func structWithoutExplicitConformance() { + // FIXME(rdar://problem/64844584) - on iOS simulator this diagnostic is flaky // This diagnostic is about `Equatable` because it's considered the best possible solution among other ones for operator `==`. - if StructWithoutExplicitConformance(a: 1, b: "b") == StructWithoutExplicitConformance(a: 2, b: "a") { } // expected-error{{referencing operator function '==' on 'Equatable' requires that 'StructWithoutExplicitConformance' conform to 'Equatable'}} + if StructWithoutExplicitConformance(a: 1, b: "b") == StructWithoutExplicitConformance(a: 2, b: "a") { } + // expected-error@-1 {{requires that 'StructWithoutExplicitConformance' conform to 'Equatable'}} } // Structs with non-hashable/equatable stored properties don't derive conformance. @@ -196,7 +198,7 @@ extension OtherFileNonconforming: Hashable { func hash(into hasher: inout Hasher) {} } // ...but synthesis in a type defined in another file doesn't work yet. -extension YetOtherFileNonconforming: Equatable {} // expected-error {{cannot be automatically synthesized in an extension in a different file to the type}} +extension YetOtherFileNonconforming: Equatable {} // expected-error {{extension outside of file declaring struct 'YetOtherFileNonconforming' prevents automatic synthesis of '==' for protocol 'Equatable'}} // Verify that we can add Hashable conformance in an extension by only // implementing hash(into:) @@ -253,7 +255,7 @@ extension UnusedGenericDeriveExtension: Hashable {} // Cross-file synthesis is still disallowed for conditional cases extension GenericOtherFileNonconforming: Equatable where T: Equatable {} -// expected-error@-1{{implementation of 'Equatable' cannot be automatically synthesized in an extension in a different file to the type}} +// expected-error@-1{{extension outside of file declaring generic struct 'GenericOtherFileNonconforming' prevents automatic synthesis of '==' for protocol 'Equatable'}} // rdar://problem/41852654 diff --git a/test/Serialization/Inputs/objc-xref/module.modulemap b/test/Serialization/Inputs/objc-xref/module.modulemap new file mode 100644 index 0000000000000..7c036997bed3b --- /dev/null +++ b/test/Serialization/Inputs/objc-xref/module.modulemap @@ -0,0 +1,4 @@ +module ObjCXRef { + header "objc_xref.h" + export * +} diff --git a/test/Serialization/Inputs/objc-xref/objc_xref.h b/test/Serialization/Inputs/objc-xref/objc_xref.h new file mode 100644 index 0000000000000..d3b7a87ef6439 --- /dev/null +++ b/test/Serialization/Inputs/objc-xref/objc_xref.h @@ -0,0 +1,2 @@ +@interface MyObject +@end diff --git a/test/Serialization/access-level.swift b/test/Serialization/access-level.swift new file mode 100644 index 0000000000000..5b098fb83f00e --- /dev/null +++ b/test/Serialization/access-level.swift @@ -0,0 +1,19 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s --check-prefix DIRECT-CHECK +// RUN: %target-swift-frontend -emit-sib %s -o %t/access-level.sib +// RUN: %target-swift-frontend -emit-ir %t/access-level.sib | %FileCheck %s --check-prefix FROM-SIB-CHECK + +// Ensure that the method linkage is default external when lowered from .swift directly +// DIRECT-CHECK-NOT: define{{.*}}internal{{.*}}swiftcc{{.*}}void @"$s4main7VisitorC13visitExprImpl33_205B03B83823935B4865F4617387553BLLyyF" + +// Ensure that the method linkage is default external when lowered from .swift -> .sib -> .ll +// FROM-SIB-CHECK-NOT: define{{.*}}internal{{.*}}swiftcc{{.*}}void @"$s4main7VisitorC13visitExprImpl33_205B03B83823935B4865F4617387553BLLyyF" + +open class Visitor { + public func visit() { + visitExprImpl() + } + @_optimize(none) + private func visitExprImpl() { + } +} diff --git a/test/Serialization/index-table-order.sil b/test/Serialization/index-table-order.sil new file mode 100644 index 0000000000000..b31e59bba578a --- /dev/null +++ b/test/Serialization/index-table-order.sil @@ -0,0 +1,51 @@ +// RUN: %empty-directory(%t) + +// Ensure that serialized sib can be deserialized correctly assuming +// contents of SIL_INDEX_BLOCK are sorted by their ids +// RUN: %target-swift-frontend -emit-sib %s -module-name test -o %t/test.sib +// RUN: %target-swift-frontend -emit-sil %t/test.sib -module-name test +// CHECK-DAG: sil_vtable +// CHECK-DAG: sil_global +// CHECK-DAG: sil_witness_table +// CHECK-DAG: sil_default_witness_table +// CHECK-DAG: sil_property + +sil_stage canonical + +import Builtin +import Swift + +// For SIL_FUNC_NAMES +sil @id : $@convention(thin) (Float) -> Float { +bb0(%0 : $Float): + return %0 : $Float +} + + +// For SIL_VTABLE_NAMES +class C {} +sil_vtable C {} + +// For SIL_GLOBALVAR_NAMES +sil_global @x : $Int + +// For SIL_WITNESS_TABLE_NAMES +protocol P1 {} +struct S : P1 {} + +sil_witness_table S: P1 module test {} + +// For SIL_DEFAULT_WITNESS_TABLE_NAMES +protocol P2 {} +sil_default_witness_table P2 {} + +// For SIL_PROPERTY_OFFSETS +struct A { + var a: Int +} + +sil_property #A.a () + +// For SIL_DIFFERENTIABILITY_WITNESS_NAMES +sil_differentiability_witness [parameters 0] [results 0] @id : $@convention(thin) (Float) -> Float {} + diff --git a/test/Serialization/xref-deinit.swift b/test/Serialization/xref-deinit.swift new file mode 100644 index 0000000000000..98c43b6670a87 --- /dev/null +++ b/test/Serialization/xref-deinit.swift @@ -0,0 +1,9 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-sib %s -o %t/xref-deinit.sib -I%t -I %S/Inputs/objc-xref +// RUN: %target-swift-frontend -emit-sil %t/xref-deinit.sib -I%t -I %S/Inputs/objc-xref + +// REQUIRES: objc_interop + +import ObjCXRef + +public class Object: MyObject {} diff --git a/test/SourceKit/CodeComplete/complete_checkdeps_vfs.swift b/test/SourceKit/CodeComplete/complete_checkdeps_vfs.swift index 388c09e57af33..84753c3a8c3f2 100644 --- a/test/SourceKit/CodeComplete/complete_checkdeps_vfs.swift +++ b/test/SourceKit/CodeComplete/complete_checkdeps_vfs.swift @@ -4,8 +4,8 @@ func foo(value: MyStruct) { // REQUIRES: shell -// RUN: DEPCHECK_INTERVAL=1 -// RUN: SLEEP_TIME=2 +// RUN: DEPCHECK_INTERVAL=2 +// RUN: SLEEP_TIME=3 // RUN: %empty-directory(%t) // RUN: %empty-directory(%t/VFS) @@ -23,7 +23,14 @@ func foo(value: MyStruct) { // RUN: -shell -- echo "### Keep" == \ // RUN: -shell -- sleep ${SLEEP_TIME} == \ -// RUN: -req=complete -pos=2:9 -pass-as-sourcetext -vfs-files=%t/VFS/Main.swift=@%s,%t/VFS/Library.swift=@%S/Inputs/checkdeps/MyProject_mod/Library.swift %t/VFS/Main.swift -- -target %target-triple %t/VFS/Main.swift %t/VFS/LibraryExt.swift %t/VFS/Library.swift \ +// RUN: -req=complete -pos=2:9 -pass-as-sourcetext -vfs-files=%t/VFS/Main.swift=@%s,%t/VFS/Library.swift=@%S/Inputs/checkdeps/MyProject_mod/Library.swift %t/VFS/Main.swift -- -target %target-triple %t/VFS/Main.swift %t/VFS/LibraryExt.swift %t/VFS/Library.swift == \ + +// RUN: -shell -- echo "### Rollback without sleep" == \ +// RUN: -req=complete -pos=2:9 -pass-as-sourcetext -vfs-files=%t/VFS/Main.swift=@%s,%t/VFS/Library.swift=@%S/Inputs/checkdeps/MyProject/Library.swift %t/VFS/Main.swift -- -target %target-triple %t/VFS/Main.swift %t/VFS/LibraryExt.swift %t/VFS/Library.swift == \ + +// RUN: -shell -- echo "### After sleep" == \ +// RUN: -shell -- sleep ${SLEEP_TIME} == \ +// RUN: -req=complete -pos=2:9 -pass-as-sourcetext -vfs-files=%t/VFS/Main.swift=@%s,%t/VFS/Library.swift=@%S/Inputs/checkdeps/MyProject/Library.swift %t/VFS/Main.swift -- -target %target-triple %t/VFS/Main.swift %t/VFS/LibraryExt.swift %t/VFS/Library.swift \ // RUN: | %FileCheck %s @@ -50,3 +57,19 @@ func foo(value: MyStruct) { // CHECK-DAG: key.description: "self" // CHECK: ] // CHECK: key.reusingastcontext: 1 + +// CHECK-LABEL: ### Rollback without sleep +// CHECK: key.results: [ +// CHECK-DAG: key.description: "myStructMethod_mod()" +// CHECK-DAG: key.description: "extensionMethod()" +// CHECK-DAG: key.description: "self" +// CHECK: ] +// CHECK: key.reusingastcontext: 1 + +// CHECK-LABEL: ### After sleep +// CHECK: key.results: [ +// CHECK-DAG: key.description: "myStructMethod()" +// CHECK-DAG: key.description: "extensionMethod()" +// CHECK-DAG: key.description: "self" +// CHECK: ] +// CHECK-NOT: key.reusingastcontext: 1 diff --git a/test/SourceKit/CodeComplete/complete_sequence_in_ifconfig.swift b/test/SourceKit/CodeComplete/complete_sequence_in_ifconfig.swift new file mode 100644 index 0000000000000..50c4acd8163ec --- /dev/null +++ b/test/SourceKit/CodeComplete/complete_sequence_in_ifconfig.swift @@ -0,0 +1,54 @@ +struct MyStruct { + init() {} + var value: Int = 1 +} + +func foo(arg: MyStruct) { + #if true + _ = arg./*8:11*/ + #else + _ = arg./*10:11*/ + #endif +} + +struct TestStruct { + #if true + func testActive(arg: MyStruct) { + _ = arg./*17:13*/ + } + #else + func testInactive(arg: MyStruct) { + _ = arg./*21:13*/ + } + #endif +} + +// Test that (1) fast completion happens even in inactive #if blocks, and +// (2) #if in toplevel decls invalidate cached ASTContext + +// RUN: %sourcekitd-test \ +// RUN: -req=complete -pos=8:11 %s -- %s -parse-as-library == \ +// RUN: -req=complete -pos=10:11 %s -- %s -parse-as-library == \ +// RUN: -req=complete -pos=17:13 %s -- %s -parse-as-library == \ +// RUN: -req=complete -pos=21:13 %s -- %s -parse-as-library \ +// RUN: | %FileCheck %s --check-prefix=RESULT + +// RESULT-LABEL: key.results: [ +// RESULT-DAG: key.description: "value" +// RESULT: ] +// RESULT-NOT: key.reusingastcontext: 1 + +// RESULT-LABEL: key.results: [ +// RESULT-DAG: key.description: "value" +// RESULT: ] +// RESULT: key.reusingastcontext: 1 + +// RESULT-LABEL: key.results: [ +// RESULT-DAG: key.description: "value" +// RESULT: ] +// RESULT: key.reusingastcontext: 1 + +// RESULT-LABEL: key.results: [ +// RESULT-DAG: key.description: "value" +// RESULT: ] +// RESULT-NOT: key.reusingastcontext: 1 diff --git a/test/SourceKit/CodeFormat/indent-multiline-string-interp.swift b/test/SourceKit/CodeFormat/indent-multiline-string-interp.swift new file mode 100644 index 0000000000000..e88853322c7cb --- /dev/null +++ b/test/SourceKit/CodeFormat/indent-multiline-string-interp.swift @@ -0,0 +1,57 @@ +let s1 = """ + \( + 45 +) + """ + +let s2 = """ + \( + 45 + ) +""" + +let s3 = """ +\( + 45 +) + """ + +let s4 = """ + foo \( 45 /* +comment content +*/) bar + """ + +// RUN: %sourcekitd-test -req=format -line=2 %s >%t.response +// RUN: %sourcekitd-test -req=format -line=3 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=4 %s >>%t.response + +// RUN: %sourcekitd-test -req=format -line=8 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=9 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=10 %s >>%t.response + +// RUN: %sourcekitd-test -req=format -line=14 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=15 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=16 %s >>%t.response + +// RUN: %sourcekitd-test -req=format -line=20 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=21 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=22 %s >>%t.response + +// RUN: %FileCheck --strict-whitespace %s <%t.response + +// CHECK: key.sourcetext: " \\(" +// CHECK: key.sourcetext: " 45" +// CHECK: key.sourcetext: " )" + +// CHECK: key.sourcetext: " \\(" +// CHECK: key.sourcetext: " 45" +// CHECK: key.sourcetext: " )" + +// CHECK: key.sourcetext: " \\(" +// CHECK: key.sourcetext: " 45" +// CHECK: key.sourcetext: ")" + +// CHECK: key.sourcetext: " foo \\( 45 /*" +// CHECK: key.sourcetext: " comment content" +// CHECK: key.sourcetext: " */) bar" diff --git a/test/SourceKit/CodeFormat/indent-multiline-string-nested.swift b/test/SourceKit/CodeFormat/indent-multiline-string-nested.swift new file mode 100644 index 0000000000000..feeff5ef5c468 --- /dev/null +++ b/test/SourceKit/CodeFormat/indent-multiline-string-nested.swift @@ -0,0 +1,25 @@ +func foo() { + let s1 = """ + this is line1 in outer string \(""" + nested string in interpolation + """) + + this is line2 in outer string + """ +} + +// RUN: %sourcekitd-test -req=format -line=3 %s >%t.response +// RUN: %sourcekitd-test -req=format -line=4 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=5 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=6 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=7 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=8 %s >>%t.response + +// RUN: %FileCheck --strict-whitespace %s <%t.response + +// CHECK: key.sourcetext: " this is line1 in outer string \\(\"\"\"" +// CHECK: key.sourcetext: " nested string in interpolation" +// CHECK: key.sourcetext: " \"\"\")" +// CHECK: key.sourcetext: " " +// CHECK: key.sourcetext: " this is line2 in outer string" +// CHECK: key.sourcetext: " \"\"\"" diff --git a/test/SourceKit/CodeFormat/indent-multiline-string-trailing-interp.swift b/test/SourceKit/CodeFormat/indent-multiline-string-trailing-interp.swift new file mode 100644 index 0000000000000..254f91c087f40 --- /dev/null +++ b/test/SourceKit/CodeFormat/indent-multiline-string-trailing-interp.swift @@ -0,0 +1,31 @@ +// RUN: %sourcekitd-test -req=format -line=24 %s >%t.response +// RUN: %sourcekitd-test -req=format -line=25 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=26 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=27 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=28 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=29 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=30 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=31 %s >>%t.response + +// RUN: %FileCheck --strict-whitespace %s <%t.response + +// The end quotes are ignored as it would be impossible to know whether +// they are part of the interpolation or another string, etc. +// CHECK: key.sourcetext: " " +// CHECK: key.sourcetext: " this is line1" +// CHECK: key.sourcetext: "" +// CHECK: key.sourcetext: "this is line2" +// CHECK: key.sourcetext: " " +// CHECK: key.sourcetext: " and this is a line with trailing interpolation \\(1 +" +// CHECK: key.sourcetext: " " +// CHECK: key.sourcetext: " \"\"\"" + +let s1 = """ + +this is line1 + + this is line2 + + and this is a line with trailing interpolation \(1 + + + """ diff --git a/test/SourceKit/CodeFormat/indent-multiline-string-trailing-ownline.swift b/test/SourceKit/CodeFormat/indent-multiline-string-trailing-ownline.swift new file mode 100644 index 0000000000000..a709366985b4d --- /dev/null +++ b/test/SourceKit/CodeFormat/indent-multiline-string-trailing-ownline.swift @@ -0,0 +1,24 @@ +// RUN: %sourcekitd-test -req=format -line=19 %s >%t.response +// RUN: %sourcekitd-test -req=format -line=20 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=21 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=22 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=23 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=24 %s >>%t.response + +// RUN: %FileCheck --strict-whitespace %s <%t.response + +// CHECK: key.sourcetext: " " +// CHECK: key.sourcetext: " this is line1" +// CHECK: key.sourcetext: "" +// CHECK: key.sourcetext: "this is line2" +// CHECK: key.sourcetext: " " +// CHECK: key.sourcetext: " " + +let s1 = + """ + +this is line1 + + this is line2 + + diff --git a/test/SourceKit/CodeFormat/indent-multiline-string-trailing.swift b/test/SourceKit/CodeFormat/indent-multiline-string-trailing.swift new file mode 100644 index 0000000000000..aad9b33e03312 --- /dev/null +++ b/test/SourceKit/CodeFormat/indent-multiline-string-trailing.swift @@ -0,0 +1,23 @@ +// RUN: %sourcekitd-test -req=format -line=18 %s >%t.response +// RUN: %sourcekitd-test -req=format -line=19 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=20 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=21 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=22 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=23 %s >>%t.response + +// RUN: %FileCheck --strict-whitespace %s <%t.response + +// CHECK: key.sourcetext: " " +// CHECK: key.sourcetext: " this is line1" +// CHECK: key.sourcetext: "" +// CHECK: key.sourcetext: "this is line2" +// CHECK: key.sourcetext: " " +// CHECK: key.sourcetext: " " + +let s1 = """ + +this is line1 + + this is line2 + + diff --git a/test/SourceKit/CodeFormat/indent-multiline-string.swift b/test/SourceKit/CodeFormat/indent-multiline-string.swift index bab0eb7c80f32..3348f32c5eeab 100644 --- a/test/SourceKit/CodeFormat/indent-multiline-string.swift +++ b/test/SourceKit/CodeFormat/indent-multiline-string.swift @@ -1,20 +1,44 @@ func foo() { let s1 = """ -this is line1, - this is line2, + +this is line1 + + this is line2 + + + this is line3 + this is a line with interpolation \(1 + + 2) + """ + + let s2 = """ """ - let s1 = - "content" } -// RUN: %sourcekitd-test -req=format -line=3 -length=1 %s >%t.response -// RUN: %sourcekitd-test -req=format -line=4 -length=1 %s >>%t.response -// RUN: %sourcekitd-test -req=format -line=5 -length=1 %s >>%t.response -// RUN: %sourcekitd-test -req=format -line=7 -length=1 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=2 %s >%t.response +// RUN: %sourcekitd-test -req=format -line=3 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=4 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=5 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=6 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=7 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=8 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=9 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=10 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=11 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=12 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=15 %s >>%t.response // RUN: %FileCheck --strict-whitespace %s <%t.response -// CHECK: key.sourcetext: "this is line1," -// CHECK: key.sourcetext: " this is line2," +// CHECK: key.sourcetext: " let s1 = \"\"\"" +// CHECK: key.sourcetext: " " +// CHECK: key.sourcetext: " this is line1" +// CHECK: key.sourcetext: " " +// CHECK: key.sourcetext: " this is line2" +// CHECK: key.sourcetext: " " +// CHECK: key.sourcetext: " " +// CHECK: key.sourcetext: " this is line3" +// CHECK: key.sourcetext: " this is a line with interpolation \\(1 +" +// CHECK: key.sourcetext: " 2)" +// CHECK: key.sourcetext: " \"\"\"" // CHECK: key.sourcetext: "\"\"\"" -// CHECK: key.sourcetext: " \"content\"" diff --git a/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/UnderscoreNotLinked.swift b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/UnderscoreNotLinked.swift new file mode 100644 index 0000000000000..9fe3d6e819519 --- /dev/null +++ b/test/SymbolGraph/Symbols/Mixins/DeclarationFragments/UnderscoreNotLinked.swift @@ -0,0 +1,11 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -module-name UnderscoreNotLinked -emit-module -emit-module-path %t/ +// RUN: %target-swift-symbolgraph-extract -module-name UnderscoreNotLinked -I %t -pretty-print -output-dir %t +// RUN: %FileCheck %s --input-file %t/UnderscoreNotLinked.symbols.json + +public protocol _ShouldntBeLinked {} +public protocol ShouldBeLinked : _ShouldntBeLinked {} +public struct MyStruct : ShouldBeLinked {} + +// CHECK: "spelling": "_ShouldntBeLinked" +// CHECK-NOT: "preciseIdentifier": "s:19UnderscoreNotLinked011_ShouldntBeC0P" diff --git a/test/Syntax/Parser/async.swift b/test/Syntax/Parser/async.swift new file mode 100644 index 0000000000000..686491170eb4d --- /dev/null +++ b/test/Syntax/Parser/async.swift @@ -0,0 +1,28 @@ +// Verify that async parses correctly via the parser lib even without the +// experimental flag being set in LangOpts. +// +// REQUIRES: syntax_parser_lib +// RUN: %swift-syntax-parser-test %s -dump-diags 2>&1 | %FileCheck %s + +func asyncGlobal1() async { } +func asyncGlobal2() async throws { } + +typealias AsyncFunc1 = () async -> () +typealias AsyncFunc2 = () async throws -> () + +func testTypeExprs() { + let _ = [() async -> ()]() + let _ = [() async throws -> ()]() +} + +func testAwaitOperator() async { + let _ = await asyncGlobal1() +} + +func testAsyncClosure() { + let _ = { () async in 5 } + let _ = { () throws in 5 } + let _ = { () async throws in 5 } +} + +// CHECK: 0 error(s) 0 warnings(s) 0 note(s) diff --git a/test/api-digester/Inputs/cake.swift b/test/api-digester/Inputs/cake.swift index 3de399487412f..b1728b6f61d48 100644 --- a/test/api-digester/Inputs/cake.swift +++ b/test/api-digester/Inputs/cake.swift @@ -139,3 +139,6 @@ public class UnavailableOnMac {} extension SwiftObjcClass { public func functionUnavailableOnMac() {} } + +@_alwaysEmitIntoClient +public func emitIntoClientFunc() {} diff --git a/test/api-digester/Outputs/cake.json b/test/api-digester/Outputs/cake.json index 8a487febb665b..08a230436a852 100644 --- a/test/api-digester/Outputs/cake.json +++ b/test/api-digester/Outputs/cake.json @@ -1340,6 +1340,25 @@ ], "hasMissingDesignatedInitializers": true }, + { + "kind": "Function", + "name": "emitIntoClientFunc", + "printedName": "emitIntoClientFunc()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "s:4cake18emitIntoClientFuncyyF", + "moduleName": "cake", + "declAttributes": [ + "AlwaysEmitIntoClient" + ], + "funcSelfKind": "NonMutating" + }, { "kind": "TypeDecl", "name": "Int", diff --git a/test/api-digester/Outputs/clang-module-dump.txt b/test/api-digester/Outputs/clang-module-dump.txt index 43ec745788e68..3f928e1abbc71 100644 --- a/test/api-digester/Outputs/clang-module-dump.txt +++ b/test/api-digester/Outputs/clang-module-dump.txt @@ -43,6 +43,7 @@ "declKind": "Protocol", "usr": "c:objc(pl)AnotherObjcProt", "moduleName": "Foo", + "genericSig": "", "objc_name": "AnotherObjcProt", "declAttributes": [ "ObjC", @@ -196,6 +197,7 @@ "declKind": "Protocol", "usr": "c:objc(pl)ObjcProt", "moduleName": "Foo", + "genericSig": "", "objc_name": "ObjcProt", "declAttributes": [ "ObjC", diff --git a/test/api-digester/compare-clang-dump.swift b/test/api-digester/compare-clang-dump.swift index cdb59d1bf93a4..3cafec46d6288 100644 --- a/test/api-digester/compare-clang-dump.swift +++ b/test/api-digester/compare-clang-dump.swift @@ -3,7 +3,7 @@ // RUN: %empty-directory(%t.module-cache) // RUN: %api-digester -dump-sdk -module Foo -o %t.dump1.json -module-cache-path %t.module-cache %clang-importer-sdk-nosource -I %S/Inputs/Foo -avoid-location // RUN: %api-digester -dump-sdk -module Foo -o %t.dump2.json -module-cache-path %t.module-cache %clang-importer-sdk-nosource -I %S/Inputs/Foo-new-version -avoid-location -// RUN: %api-digester -diagnose-sdk -protocol-requirement-white-list %S/Inputs/Foo-prot-allowlist.txt -print-module --input-paths %t.dump1.json -input-paths %t.dump2.json -o %t.result +// RUN: %api-digester -diagnose-sdk -protocol-requirement-allow-list %S/Inputs/Foo-prot-allowlist.txt -print-module --input-paths %t.dump1.json -input-paths %t.dump2.json -o %t.result // RUN: %clang -E -P -x c %S/Outputs/Foo-diff.txt -o - | sed '/^\s*$/d' > %t.expected // RUN: %clang -E -P -x c %t.result -o - | sed '/^\s*$/d' > %t.result.tmp diff --git a/test/api-digester/use-interface-for.swift b/test/api-digester/use-interface-for.swift new file mode 100644 index 0000000000000..6399084893092 --- /dev/null +++ b/test/api-digester/use-interface-for.swift @@ -0,0 +1,20 @@ +// REQUIRES: VENDOR=apple + +// RUN: %empty-directory(%t.mod) +// RUN: %empty-directory(%t.sdk) +// RUN: %empty-directory(%t.module-cache) + +// RUN: echo "public func foo() {}" > %t.swift + +// RUN: %target-swift-frontend -emit-module -emit-module-interface-path %t.mod/cake.swiftinterface %t.swift %clang-importer-sdk-nosource -parse-as-library -enable-library-evolution -disable-objc-attr-requires-foundation-module -module-cache-path %t.module-cache -emit-module-path %t.mod/cake.swiftmodule -module-name cake -swift-version 5 + +// Step 1: we should be able to load if we prefer cake.swiftinterface +// RUN: %api-digester -dump-sdk -print-module -module cake -I %t.mod -sdk %clang-importer-sdk-path -module-cache-path %t.module-cache -o %t.json -abi -abort-on-module-fail -use-interface-for-module cake + +// RUN: echo "Swift Syntax Error" >> %t.mod/cake.swiftinterface + +// Step 2: we shouldn't be able to load if we prefer cake.swiftinterface and cake.swiftinterface is broken +// RUN: not %api-digester -dump-sdk -print-module -module cake -I %t.mod -sdk %clang-importer-sdk-path -module-cache-path %t.module-cache -o %t.json -abi -abort-on-module-fail -use-interface-for-module cake + +// Step 3: we should be able to load if we don't prefer cake.swiftinterface +// RUN: %api-digester -dump-sdk -print-module -module cake -I %t.mod -sdk %clang-importer-sdk-path -module-cache-path %t.module-cache -o %t.json -abi -abort-on-module-fail diff --git a/test/attr/asynchandler.swift b/test/attr/asynchandler.swift new file mode 100644 index 0000000000000..e3147f62edbdd --- /dev/null +++ b/test/attr/asynchandler.swift @@ -0,0 +1,52 @@ +// RUN: %target-swift-frontend -typecheck -verify %s -enable-experimental-concurrency + +func globalAsyncFunction() async -> Int { 0 } + +@asyncHandler func asyncHandler1() { + // okay, it's an async context + let _ = await globalAsyncFunction() +} + +@asyncHandler func asyncHandler2(fn: @autoclosure () async -> Int ) { + // okay, it's an async context +} + +@asyncHandler +func asyncHandlerBad1() -> Int { 0 } +// expected-error@-1{{'@asyncHandler' function can only return 'Void'}} + +@asyncHandler +func asyncHandlerBad2() async { } +// expected-error@-1{{'@asyncHandler' function cannot be 'async' itself}}{{25-31=}} + +@asyncHandler +func asyncHandlerBad3() throws { } +// expected-error@-1{{'@asyncHandler' function cannot throw}}{{25-32=}} + +@asyncHandler +func asyncHandlerBad4(result: inout Int) { } +// expected-error@-1{{'inout' parameter is not allowed in '@asyncHandler' function}} + +struct X { + @asyncHandler func asyncHandlerMethod() { } + + @asyncHandler + mutating func asyncHandlerMethodBad1() { } + // expected-error@-1{{'@asyncHandler' function cannot be 'mutating'}}{{3-12=}} + + @asyncHandler init() { } + // expected-error@-1{{@asyncHandler may only be used on 'func' declarations}} +} + + +// Inference of @asyncHandler +protocol P { + @asyncHandler func callback() +} + +extension X: P { + func callback() { + // okay, it's an async context + let _ = await globalAsyncFunction() + } +} diff --git a/test/attr/asynchandler_noconcurrency.swift b/test/attr/asynchandler_noconcurrency.swift new file mode 100644 index 0000000000000..97545fd0bc555 --- /dev/null +++ b/test/attr/asynchandler_noconcurrency.swift @@ -0,0 +1,4 @@ +// RUN: %target-swift-frontend -typecheck -verify %s + +@asyncHandler func asyncHandler1() { } +// expected-error@-1{{'@asyncHandler' is only valid when experimental concurrency is enabled}} diff --git a/test/attr/attr_override.swift b/test/attr/attr_override.swift index b059d707a578f..e234a294b9e02 100644 --- a/test/attr/attr_override.swift +++ b/test/attr/attr_override.swift @@ -590,7 +590,7 @@ class SR_4206_Base_7 { } class SR_4206_Derived_7: SR_4206_Base_7 { - override func foo1() where T: SR_4206_Protocol_2 {} // expected-error {{overridden method 'foo1' has generic signature which is incompatible with base method's generic signature ; expected generic signature to be }} + override func foo1() where T: SR_4206_Protocol_2 {} // expected-error {{overridden method 'foo1' has generic signature which is incompatible with base method's generic signature ; expected generic signature to be }} override func foo2() {} // OK } @@ -627,7 +627,7 @@ class SR_4206_Base_10 { func foo() where T: SR_4206_Protocol_1 {} // expected-note {{overridden declaration is here}} } class SR_4206_Derived_10: SR_4206_Base_10 { - override func foo() where U: SR_4206_Protocol_1 {} // expected-error {{overridden method 'foo' has generic signature which is incompatible with base method's generic signature ; expected generic signature to be }} + override func foo() where U: SR_4206_Protocol_1 {} // expected-error {{overridden method 'foo' has generic signature which is incompatible with base method's generic signature ; expected generic signature to be }} } // Override with return type specialization diff --git a/test/decl/ext/extensions.swift b/test/decl/ext/extensions.swift index 485ff4da476d7..b6f5133acfd8d 100644 --- a/test/decl/ext/extensions.swift +++ b/test/decl/ext/extensions.swift @@ -267,14 +267,14 @@ extension ImposeClassReq1 where Self: AnyObject { var wrappingProperty2: Int { get { return someProperty } - mutating set { someProperty = newValue } // expected-error {{'mutating' isn't valid on methods in classes or class-bound protocols}} + mutating set { someProperty = newValue } // expected-error {{'mutating' is not valid on setters in class-bound protocols}} } - mutating func foo() { // expected-error {{mutating' isn't valid on methods in classes or class-bound protocols}} + mutating func foo() { // expected-error {{mutating' is not valid on instance methods in class-bound protocols}} someProperty = 1 } - nonmutating func bar() { // expected-error {{'nonmutating' isn't valid on methods in classes or class-bound protocols}} + nonmutating func bar() { // expected-error {{'nonmutating' is not valid on instance methods in class-bound protocols}} someProperty = 2 } @@ -309,14 +309,14 @@ extension ImposeClassReq2 { var wrappingProperty2: Int { get { return someProperty } - mutating set { someProperty = newValue } // expected-error {{'mutating' isn't valid on methods in classes or class-bound protocols}} + mutating set { someProperty = newValue } // expected-error {{'mutating' is not valid on setters in class-bound protocols}} } - mutating func foo() { // expected-error {{mutating' isn't valid on methods in classes or class-bound protocols}} + mutating func foo() { // expected-error {{mutating' is not valid on instance methods in class-bound protocols}} someProperty = 1 } - nonmutating func bar() { // expected-error {{'nonmutating' isn't valid on methods in classes or class-bound protocols}} + nonmutating func bar() { // expected-error {{'nonmutating' is not valid on instance methods in class-bound protocols}} someProperty = 2 } @@ -349,3 +349,10 @@ struct SR_10466 { extension SR_10466 where T == Never { // expected-note {{requirement specified as 'T' == 'Never' [with T = T]}} typealias A = Int } + +#if true +protocol Rdar66943328 { + associatedtype Assoc +} +extension Rdar66943328 where Assoc == Int // expected-error {{expected '{' in extension}} +#endif diff --git a/test/decl/protocol/conforms/associated_type.swift b/test/decl/protocol/conforms/associated_type.swift index f299611655ef8..805624c6f36a6 100644 --- a/test/decl/protocol/conforms/associated_type.swift +++ b/test/decl/protocol/conforms/associated_type.swift @@ -94,27 +94,8 @@ struct SR_12707_Conform_P2: SR_12707_P2 { typealias A = Never } -// Default type witness -protocol SR_12707_P3 { - associatedtype A - associatedtype B: SR_12707_C<(A, Self)> = SR_12707_C<(A, Self)> -} -struct SR_12707_Conform_P3: SR_12707_P3 { - typealias A = Never -} - -// FIXME: Type witness resolution success is order-dependent. -protocol SR_12707_FIXME_P1 { - associatedtype A -} -protocol SR_12707_FIXME_P2: SR_12707_FIXME_P1 { - associatedtype B: SR_12707_C<(A, Self)> = SR_12707_C<(A, Self)> // expected-note {{default type 'associated_type.SR_12707_C<(associated_type.SR_12707_FIXME_Conform_P2.A, associated_type.SR_12707_FIXME_Conform_P2)>' (aka 'SR_12707_C<(Never, SR_12707_FIXME_Conform_P2)>') for associated type 'B' (from protocol 'SR_12707_FIXME_P2') does not inherit from 'associated_type.SR_12707_C<(associated_type.SR_12707_FIXME_Conform_P2.A, associated_type.SR_12707_FIXME_Conform_P2)>'}} -} -struct SR_12707_FIXME_Conform_P2: SR_12707_FIXME_P2 { // expected-error {{type 'SR_12707_FIXME_Conform_P2' does not conform to protocol 'SR_12707_FIXME_P2'}} - typealias A = Never -} - -// FIXME: Type witness resolution success is order-dependent. +// FIXME: resolveTypeWitnessViaLookup must not happen independently in the +// general case. protocol SR_12707_FIXME_P3 { associatedtype A: SR_12707_C // expected-note {{protocol requires nested type 'A'; do you want to add it?}} associatedtype B @@ -123,3 +104,27 @@ struct SR_12707_FIXME_Conform_P3: SR_12707_FIXME_P3 { // expected-error {{type ' typealias A = SR_12707_C // expected-note {{possibly intended match 'SR_12707_FIXME_Conform_P3.A' (aka 'SR_12707_C') does not inherit from 'SR_12707_C'}} typealias B = Never } + +// FIXME: Associated type inference via value witnesses should consider +// tentative witnesses when checking a candidate. +protocol SR_12707_FIXME_P4 { + associatedtype X = Never + + associatedtype A: SR_12707_C // expected-note {{unable to infer associated type 'A' for protocol 'SR_12707_FIXME_P4'}} + func foo(arg: A) +} +struct SR_12707_FIXME_Conform_P4: SR_12707_FIXME_P4 { // expected-error {{type 'SR_12707_FIXME_Conform_P4' does not conform to protocol 'SR_12707_FIXME_P4'}} + func foo(arg: SR_12707_C) {} // expected-note {{candidate would match and infer 'A' = 'SR_12707_C' if 'SR_12707_C' inherited from 'SR_12707_C'}} +} + +// Abstract type witnesses. +protocol SR_12707_P5a { + associatedtype X = Never + + associatedtype A: SR_12707_C + associatedtype B: SR_12707_C +} +protocol SR_12707_P5b: SR_12707_P5a where B == SR_12707_C { + associatedtype C: SR_12707_C = SR_12707_C +} +struct SR_12707_Conform_P5>: SR_12707_P5b {} diff --git a/test/decl/protocol/fixits_missing_protocols_in_context.swift b/test/decl/protocol/fixits_missing_protocols_in_context.swift new file mode 100644 index 0000000000000..0511266896062 --- /dev/null +++ b/test/decl/protocol/fixits_missing_protocols_in_context.swift @@ -0,0 +1,45 @@ +// RUN: %target-swift-frontend -typecheck -diagnostics-editor-mode -verify %s + +// Test that we emit fix-its to insert requirement stubs for the missing protocol conformance, in addition to adding the conformance. + +protocol P { + func method() + var property: Int { get } +} + +class C { + var p: P? + + func assign() { + p = self + // expected-error@-1 {{cannot assign value of type 'C' to type 'P?'}} + // expected-note@-2 {{add missing conformance to 'P' to class 'C'}} {{8-8=: P}} {{10-10=\n func method() {\n <#code#>\n \}\n\n var property: Int\n}} + } +} + +// Test that we don't emit fix-it to insert a requirement stub if there is already a satisfying witness. + +class C1 { + var p: P? + + func assign() { + p = self + // expected-error@-1 {{cannot assign value of type 'C1' to type 'P?'}} + // expected-note@-2 {{add missing conformance to 'P' to class 'C1'}} {{9-9=: P}} {{11-11=\n var property: Int\n}} + } + + func method() {} +} + +class C2 { + var p: P? + + func assign() { + p = self + // expected-error@-1 {{cannot assign value of type 'C2' to type 'P?'}} + // expected-note@-2 {{add missing conformance to 'P' to class 'C2'}} {{9-9=: P}} + } + + func method() {} + var property: Int = 0 +} diff --git a/test/decl/protocol/req/missing_conformance.swift b/test/decl/protocol/req/missing_conformance.swift index c838d20cd8557..871c4344c30ef 100644 --- a/test/decl/protocol/req/missing_conformance.swift +++ b/test/decl/protocol/req/missing_conformance.swift @@ -132,6 +132,7 @@ extension CountSteps1 // expected-error {{type 'CountSteps1' does not conform where T : Equatable { typealias Index = Int + // expected-error@-1 {{invalid redeclaration of synthesized implementation for protocol requirement 'Index'}} func index(_ i: Index, offsetBy d: Int) -> Index { return i + d } diff --git a/test/decl/protocol/req/unsatisfiable.swift b/test/decl/protocol/req/unsatisfiable.swift index 682300ddd43e4..390c856bb0950 100644 --- a/test/decl/protocol/req/unsatisfiable.swift +++ b/test/decl/protocol/req/unsatisfiable.swift @@ -58,3 +58,25 @@ protocol P4 { protocol P5 { associatedtype Y where Y : S // expected-error {{type 'Self.Y' constrained to non-protocol, non-class type 'S'}} } + +protocol P6 { + associatedtype T + associatedtype U + + func foo() where T == U + // expected-error@-1 {{instance method requirement 'foo()' cannot add constraint 'Self.T == Self.U' on 'Self'}} + // expected-note@-2 {{protocol requires function 'foo()' with type '() -> ()'; do you want to add a stub?}} +} + +struct S2 : P6 { + // expected-error@-1 {{type 'S2' does not conform to protocol 'P6'}} + typealias T = Int + typealias U = String + + func foo() {} + // expected-note@-1 {{candidate has non-matching type '() -> ()'}} + + // FIXME: This error is bogus and should be omitted on account of the protocol requirement itself + // being invalid. +} + diff --git a/test/decl/protocol/special/coding/Inputs/struct_codable_simple_multi1.swift b/test/decl/protocol/special/coding/Inputs/struct_codable_simple_multi1.swift index 7d72e19fe049d..2bd193260a0f2 100644 --- a/test/decl/protocol/special/coding/Inputs/struct_codable_simple_multi1.swift +++ b/test/decl/protocol/special/coding/Inputs/struct_codable_simple_multi1.swift @@ -21,3 +21,11 @@ struct SimpleStruct : Codable { let _ = SimpleStruct.CodingKeys.z // expected-error {{type 'SimpleStruct.CodingKeys' has no member 'z'}} } } + +// SR-13137 Ensure unqualified lookup installs CodingKeys regardless of the +// order of primaries. +struct A: Codable { + var property: String + static let propertyName = CodingKeys.property.stringValue +} + diff --git a/test/decl/protocol/special/coding/Inputs/struct_codable_simple_multi2.swift b/test/decl/protocol/special/coding/Inputs/struct_codable_simple_multi2.swift index e1c762b8d296a..96310709d71a4 100644 --- a/test/decl/protocol/special/coding/Inputs/struct_codable_simple_multi2.swift +++ b/test/decl/protocol/special/coding/Inputs/struct_codable_simple_multi2.swift @@ -8,3 +8,11 @@ func foo() { // struct. let _ = SimpleStruct.CodingKeys.self // expected-error {{'CodingKeys' is inaccessible due to 'private' protection level}} } + +struct B { + static let propertyName = A.propertyName + + struct Nest { + static let propertyName = A.propertyName + } +} diff --git a/test/decl/var/property_wrappers.swift b/test/decl/var/property_wrappers.swift index 736a32a261fa3..b816762cd2cc5 100644 --- a/test/decl/var/property_wrappers.swift +++ b/test/decl/var/property_wrappers.swift @@ -1732,7 +1732,7 @@ extension SR_11288_P4 where Self: AnyObject { // expected-note {{requirement spe } struct SR_11288_S4: SR_11288_P4 { - @SR_11288_Wrapper4 var answer = 42 // expected-error {{'SR_11288_S4.SR_11288_Wrapper4' (aka 'SR_11288_S0') requires that 'SR_11288_S4' be a class type}} + @SR_11288_Wrapper4 var answer = 42 // expected-error {{'Self.SR_11288_Wrapper4' (aka 'SR_11288_S0') requires that 'SR_11288_S4' be a class type}} } class SR_11288_C0: SR_11288_P4 { diff --git a/test/expr/closure/closures.swift b/test/expr/closure/closures.swift index 37c704b492714..f2b5eb5a0cf9f 100644 --- a/test/expr/closure/closures.swift +++ b/test/expr/closure/closures.swift @@ -141,6 +141,7 @@ func anonymousClosureArgsInClosureWithArgs() { var a5 = { (_: [Int], w: [Int]) in f($0.count) // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments}} f($1.count) // expected-error {{anonymous closure arguments cannot be used inside a closure that has explicit arguments; did you mean 'w'?}} {{7-9=w}} + // expected-error@-1 {{cannot convert value of type 'Int' to expected argument type 'String'}} } } diff --git a/test/expr/closure/single_expr.swift b/test/expr/closure/single_expr.swift index ac3d7a7a94aad..62960ff837b6f 100644 --- a/test/expr/closure/single_expr.swift +++ b/test/expr/closure/single_expr.swift @@ -104,3 +104,20 @@ missionCritical(storage: { haltAndCatchFire() }) enum E { } func takesAnotherUninhabitedType(e: () -> E) {} takesAnotherUninhabitedType { haltAndCatchFire() } + +// Weak capture bug caught by rdar://problem/67351438 +class Y { + var toggle: Bool = false + + func doSomething(animated: Bool, completionHandler: (Int, Int) -> Void) { } +} + +class X { + private(set) var someY: Y! + + func doSomething() { + someY?.doSomething(animated: true, completionHandler: { [weak someY] _, _ in + someY?.toggle = true + }) + } +} diff --git a/test/expr/delayed-ident/member_chains.swift b/test/expr/delayed-ident/member_chains.swift new file mode 100644 index 0000000000000..2691574dbd321 --- /dev/null +++ b/test/expr/delayed-ident/member_chains.swift @@ -0,0 +1,346 @@ +// RUN: %target-typecheck-verify-swift -swift-version 5 + +struct ImplicitMembers: Equatable { + struct Other { + var implicit: ImplicitMembers { ImplicitMembers() } + } + + static var other = Other() + static func createOther() -> Other { + Other() + } + var anotherOther: Other { Other() } + func getAnotherOther() -> Other { + Other() + } + + static var implicit = ImplicitMembers() + static let implicitLet = ImplicitMembers() // expected-note2 {{change 'let' to 'var' to make it mutable}} + static var implicitImmutable: ImplicitMembers { ImplicitMembers() } + static func createImplicit() -> ImplicitMembers { + ImplicitMembers() + } + + static var optional: ImplicitMembers? = ImplicitMembers() + static func createOptional() -> ImplicitMembers? { + ImplicitMembers() + } + static var superOptional: ImplicitMembers??? = ImplicitMembers() + + static func createIUOArg(_: Int) -> ImplicitMembers { ImplicitMembers() } + var anotherIUO: ImplicitMembers! { ImplicitMembers() } + func getAnotherIUO() -> ImplicitMembers! { ImplicitMembers() } + + var another: ImplicitMembers { ImplicitMembers() } + var anotherMutable: ImplicitMembers { + get { ImplicitMembers() } + set {} + } + + func getAnother() -> ImplicitMembers { + ImplicitMembers() + } + + func getAnother(arg: Int) -> ImplicitMembers { + ImplicitMembers() + } + + var anotherOptional: ImplicitMembers? { ImplicitMembers() } + var anotherOptionalMutable: ImplicitMembers? { + get { ImplicitMembers() } + set {} + } + + func getAnotherOptional() -> ImplicitMembers? { + ImplicitMembers() + } + + func getAnotherOptional(arg: Int) -> ImplicitMembers? { + ImplicitMembers() + } + + static func takesClosure(_: (Int) -> Void) -> ImplicitMembers { ImplicitMembers() } + static func takesArgClosure(_: Int, _: (Int) -> Void) -> ImplicitMembers { ImplicitMembers() } + func methodTakesClosure(_: (Int) -> Void) -> ImplicitMembers { ImplicitMembers() } + func methodTakesArgClosure(_: Int, _: (Int) -> Void) -> ImplicitMembers { ImplicitMembers() } + + subscript(arg: Void) -> ImplicitMembers { + get { ImplicitMembers() } + set {} + } + subscript(optional arg: Void) -> ImplicitMembers? { + get { ImplicitMembers() } + set {} + } + subscript(immutable arg: Void) -> ImplicitMembers { ImplicitMembers() } + subscript(func arg: Void) -> (() -> ImplicitMembers) { { ImplicitMembers() } } + subscript(funcOptional arg: Void) -> (() -> ImplicitMembers?) { { ImplicitMembers() } } + subscript(optionalFunc arg: Void) -> (() -> ImplicitMembers)? { { ImplicitMembers() } } + subscript(other arg: Void) -> Other { Other() } +} + +let _: ImplicitMembers = .implicit +let _: ImplicitMembers? = .implicit +let _: ImplicitMembers? = .optional + +let _: ImplicitMembers = .implicit.another.another +let _: ImplicitMembers = .createImplicit().another.another +let _: ImplicitMembers = .init().another.another + +let _: ImplicitMembers = .implicit.getAnother().another +let _: ImplicitMembers = .createImplicit().getAnother().another +let _: ImplicitMembers = .init().getAnother().another + +let _: ImplicitMembers = .implicit.getAnother(arg: 0).another +let _: ImplicitMembers = .createImplicit().getAnother(arg: 0).another +let _: ImplicitMembers = .init().getAnother(arg: 0).another + +let _: ImplicitMembers = .implicit.another.getAnother() +let _: ImplicitMembers = .createImplicit().another.getAnother() +let _: ImplicitMembers = .init().another.getAnother() + +let _: ImplicitMembers = .implicit.another.getAnother(arg: 0) +let _: ImplicitMembers = .createImplicit().another.getAnother(arg: 0) +let _: ImplicitMembers = .init().another.getAnother(arg: 0) + +let _: ImplicitMembers = .implicit.getAnother().getAnother(arg: 0) +let _: ImplicitMembers = .createImplicit().getAnother().getAnother(arg: 0) +let _: ImplicitMembers = .init().getAnother().getAnother(arg: 0) + +let _: ImplicitMembers = .implicit.getAnother().getAnother(arg: 0).another +let _: ImplicitMembers = .createImplicit().getAnother().getAnother(arg: 0).another +let _: ImplicitMembers = .init().getAnother().getAnother(arg: 0).another + +let _: ImplicitMembers = .implicit.another.getAnother().getAnother(arg: 0) +let _: ImplicitMembers = .createImplicit().another.getAnother().getAnother(arg: 0) +let _: ImplicitMembers = .init().another.getAnother().getAnother(arg: 0) + +let _: ImplicitMembers = .implicit.another.another.another.another.another +let _: ImplicitMembers = .implicit.getAnother().getAnother().getAnother().getAnother().getAnother() +let _: ImplicitMembers = .implicit.getAnother(arg: 0).getAnother(arg: 0).getAnother(arg: 0).getAnother(arg: 0).getAnother(arg: 0) + +let _: ImplicitMembers = .implicit.another.getAnother().getAnother(arg: 0).anotherIUO +let _: ImplicitMembers = .createImplicit().another.getAnother().getAnother(arg: 0).anotherIUO +let _: ImplicitMembers = .init().another.getAnother().getAnother(arg: 0).anotherIUO + +let _: ImplicitMembers = .implicit.another.getAnother().getAnother(arg: 0).getAnotherIUO() +let _: ImplicitMembers = .createImplicit().another.getAnother().getAnother(arg: 0).getAnotherIUO() +let _: ImplicitMembers = .init().another.getAnother().getAnother(arg: 0).getAnotherIUO() + +let _: ImplicitMembers = .createIUOArg(_:)(0) + +let _: ImplicitMembers = .optional! +let _: ImplicitMembers = .optional!.another +let _: ImplicitMembers = .createOptional()!.another +let _: ImplicitMembers = .optional!.anotherOptional! +let _: ImplicitMembers = .createOptional()!.anotherOptional! +let _: ImplicitMembers = .optional!.getAnotherOptional()! +let _: ImplicitMembers = .createOptional()!.getAnotherOptional()! +let _: ImplicitMembers = .implicit.getAnotherIUO() +let _: ImplicitMembers = .createImplicit().anotherIUO +let _: ImplicitMembers = .implicit.anotherIUO +let _: ImplicitMembers = .createImplicit().anotherIUO + +let _: ImplicitMembers = .optional // expected-error {{value of optional type 'ImplicitMembers?' must be unwrapped to a value of type 'ImplicitMembers'}} expected-note {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{35-35= ?? <#default value#>}} expected-note {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{35-35=!}} +let _: ImplicitMembers = .implicit.anotherOptional // expected-error {{value of optional type 'ImplicitMembers?' must be unwrapped to a value of type 'ImplicitMembers'}} expected-note {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{51-51= ?? <#default value#>}} expected-note {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{51-51=!}} +let _: ImplicitMembers = .createOptional() // expected-error {{value of optional type 'ImplicitMembers?' must be unwrapped to a value of type 'ImplicitMembers'}} expected-note {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{43-43= ?? <#default value#>}} expected-note {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{43-43=!}} +let _: ImplicitMembers = .implicit.getAnotherOptional() // expected-error {{value of optional type 'ImplicitMembers?' must be unwrapped to a value of type 'ImplicitMembers'}} expected-note {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{56-56= ?? <#default value#>}} expected-note {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{56-56=!}} +let _: ImplicitMembers = .implicit[optional: ()] // expected-error {{value of optional type 'ImplicitMembers?' must be unwrapped to a value of type 'ImplicitMembers'}} expected-note {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{49-49= ?? <#default value#>}} expected-note {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{49-49=!}} +let _: ImplicitMembers = .implicit[funcOptional: ()]() // expected-error {{value of optional type 'ImplicitMembers?' must be unwrapped to a value of type 'ImplicitMembers'}} expected-note {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{55-55= ?? <#default value#>}} expected-note {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{55-55=!}} + +// FIXME: Improve these diagnostics (should probably offer unwrapping, as above) +let _: ImplicitMembers = .implicit.anotherOptional?.another // expected-error{{type of expression is ambiguous without more context}} +let _: ImplicitMembers = .implicit[optionalFunc: ()]?() // expected-error{{type of expression is ambiguous without more context}} + + +let _: ImplicitMembers = .other.implicit +let _: ImplicitMembers = .implicit.anotherOther.implicit +let _: ImplicitMembers = .createOther().implicit +let _: ImplicitMembers = .implicit.getAnotherOther().implicit +let _: ImplicitMembers = .implicit[other: ()].implicit + +let _: ImplicitMembers = .other // expected-error {{member 'other' in 'ImplicitMembers' produces result of type 'ImplicitMembers.Other', but context expects 'ImplicitMembers'}} +let _: ImplicitMembers = .implicit.anotherOther // expected-error {{member 'anotherOther' in 'ImplicitMembers' produces result of type 'ImplicitMembers.Other', but context expects 'ImplicitMembers'}} +let _: ImplicitMembers = .implicit.anotherOther.nonDeclaredMember // expected-error {{value of type 'ImplicitMembers.Other' has no member 'nonDeclaredMember'}} +let _: ImplicitMembers = .implicit.anotherOther.nonDeclaredMethod() // expected-error {{value of type 'ImplicitMembers.Other' has no member 'nonDeclaredMethod'}} +let _: ImplicitMembers = .implicit.anotherOther.nonDeclaredMember.another // expected-error {{value of type 'ImplicitMembers.Other' has no member 'nonDeclaredMember'}} +let _: ImplicitMembers = .implicit.anotherOther.nonDeclaredMethod().another // expected-error {{value of type 'ImplicitMembers.Other' has no member 'nonDeclaredMethod'}} +let _: ImplicitMembers = .implicit.getAnotherOther() // expected-error {{member 'getAnotherOther()' in 'ImplicitMembers' produces result of type 'ImplicitMembers.Other', but context expects 'ImplicitMembers'}} +let _: ImplicitMembers = .implicit[other: ()] // expected-error {{member 'subscript(other:)' in 'ImplicitMembers' produces result of type 'ImplicitMembers.Other', but context expects 'ImplicitMembers'}} + +let _: ImplicitMembers? = .implicit.another +let _: ImplicitMembers? = .implicit.anotherOptional + +let _: ImplicitMembers? = .optional +let _: ImplicitMembers? = .optional?.another +let _: ImplicitMembers? = .optional?.anotherOptional +let _: ImplicitMembers? = .optional?.getAnother() +let _: ImplicitMembers? = .optional?.getAnotherOptional() +let _: ImplicitMembers? = .optional?.anotherOptional?.another +let _: ImplicitMembers? = .optional?.getAnotherOptional()?.another +let _: ImplicitMembers? = .createOptional() +let _: ImplicitMembers? = .createOptional()?.another +let _: ImplicitMembers? = .createOptional()?.anotherOptional +let _: ImplicitMembers? = .createOptional()?.getAnother() +let _: ImplicitMembers? = .createOptional()?.getAnotherOptional() +let _: ImplicitMembers? = .createOptional()?.anotherOptional?.another +let _: ImplicitMembers? = .createOptional()?.getAnotherOptional()?.another +let _: ImplicitMembers? = .createOptional()?.getAnotherOptional()?.anotherIUO +let _: ImplicitMembers? = .createOptional()?.getAnotherOptional()?.getAnotherIUO() +// FIXME: This should be allowed +// let _: ImplicitMembers? = .superOptional???.another + +let _: ImplicitMembers = .takesClosure { _ in } +let _: ImplicitMembers = .takesArgClosure(0) { _ in } +let _: ImplicitMembers = .implicit.methodTakesClosure { _ in } +let _: ImplicitMembers = .implicit.methodTakesArgClosure(0) { _ in } +let _: ImplicitMembers? = .optional?.methodTakesClosure { _ in } +let _: ImplicitMembers? = .optional?.methodTakesArgClosure(0) { _ in } + +let _: ImplicitMembers = .implicit[()] +let _: ImplicitMembers = .implicit[optional: ()]! +let _: ImplicitMembers? = .implicit[optional: ()] +let _: ImplicitMembers = .implicit[func: ()]() +let _: ImplicitMembers = .implicit[funcOptional: ()]()! +let _: ImplicitMembers? = .implicit[funcOptional: ()]() +let _: ImplicitMembers = .implicit[optionalFunc: ()]!() +let _: ImplicitMembers? = .implicit[optionalFunc: ()]?() +let _: ImplicitMembers = .implicit.another[()] +let _: ImplicitMembers = .implicit.another[optional: ()]! +let _: ImplicitMembers? = .implicit.another[optional: ()] +let _: ImplicitMembers = .implicit.another[func: ()]() +let _: ImplicitMembers = .implicit.another[funcOptional: ()]()! +let _: ImplicitMembers? = .implicit.another[funcOptional: ()]() +let _: ImplicitMembers = .implicit.another[optionalFunc: ()]!() +let _: ImplicitMembers? = .implicit.another[optionalFunc: ()]?() +let _: ImplicitMembers = .implicit[()].another +let _: ImplicitMembers = .implicit[optional: ()]!.another +let _: ImplicitMembers? = .implicit[optional: ()]?.another +let _: ImplicitMembers = .implicit[func: ()]().another +let _: ImplicitMembers = .implicit[funcOptional: ()]()!.another +let _: ImplicitMembers? = .implicit[funcOptional: ()]()?.another +let _: ImplicitMembers = .implicit[optionalFunc: ()]!().another +let _: ImplicitMembers? = .implicit[optionalFunc: ()]?().another + +func implicit(_ i: inout ImplicitMembers) { + if i == .implicit {} + if i == .implicit.another {} + if i == .implicit.getAnother() {} + if i == .optional?.another {} + if i == .optional!.another {} + if i == .createOptional()?.another {} +} + +func testLValues() { + let local = ImplicitMembers(); + + .implicit = local; + .implicit.anotherMutable = local; + .implicit.anotherOptionalMutable? = local; + .implicit.anotherOptionalMutable! = local; + .implicit[()] = local; + .implicit[()].anotherMutable = local; + .optional?[optional: ()]?.anotherOptionalMutable! = local; + + .implicitLet = local; // expected-error {{cannot assign to property: 'implicitLet' is a 'let' constant}} + .implicitImmutable = local; // expected-error {{cannot assign to property: 'implicitImmutable' is a get-only property}} + .createImplicit() = local; // expected-error {{expression is not assignable: function call returns immutable value}} + .implicit.another = local; // expected-error {{cannot assign to property: 'another' is a get-only property}} + .implicit[immutable: ()] = local; // expected-error {{cannot assign through subscript: subscript is get-only}} + .implicit.getAnother() = local; // expected-error {{expression is not assignable: function call returns immutable value}} + + .implicitLet.anotherMutable = local; // expected-error {{cannot assign to property: 'implicitLet' is a 'let' constant}} + .implicitImmutable.anotherMutable = local; // expected-error {{cannot assign to property: 'implicitImmutable' is a get-only property}} + .createImplicit().anotherMutable = local; // expected-error {{cannot assign to property: function call returns immutable value}} + .implicit.another.anotherMutable = local; // expected-error {{cannot assign to property: 'another' is a get-only property}} + .implicit[immutable: ()].anotherMutable = local; // expected-error {{cannot assign to property: subscript is get-only}} + .implicit.getAnother().anotherMutable = local; // expected-error {{cannot assign to property: function call returns immutable value}} + + + // FIXME: These should probably be allowed + //.implicit.anotherOptionalMutable = local; + //.optional = local; +} + +struct ImplicitGeneric { // expected-note4 {{arguments to generic parameter 'T' ('Int' and 'String') are expected to be equal}} + static var implicit: ImplicitGeneric { ImplicitGeneric() } + var another: ImplicitGeneric { ImplicitGeneric() } + func getAnother() -> ImplicitGeneric { + ImplicitGeneric() + } +} + +extension ImplicitGeneric where T == Int { + static var implicitInt: ImplicitGeneric { ImplicitGeneric() } + static var implicitString: ImplicitGeneric { ImplicitGeneric() } + var anotherInt: ImplicitGeneric { ImplicitGeneric() } + var anotherIntString: ImplicitGeneric { ImplicitGeneric() } + func getAnotherInt() -> ImplicitGeneric { + ImplicitGeneric() + } +} + +extension ImplicitGeneric where T == String { + static var implicitString: ImplicitGeneric { ImplicitGeneric() } + var anotherString: ImplicitGeneric { ImplicitGeneric() } + var anotherStringInt: ImplicitGeneric { ImplicitGeneric() } + func getAnotherString() -> ImplicitGeneric { + ImplicitGeneric() + } + func getAnotherStringInt() -> ImplicitGeneric { + ImplicitGeneric() + } +} + +func implicit(_ arg: ImplicitGeneric) {} + +implicit(.implicitInt) +implicit(.implicit.anotherInt) +implicit(.implicit.anotherInt.another) +implicit(.implicit.another.anotherInt) +implicit(.implicit.getAnotherInt()) +implicit(.implicit.another.getAnotherInt()) +implicit(.implicit.getAnother().anotherInt) +implicit(.implicit.getAnotherInt()) +implicit(.implicit.getAnother().getAnotherInt()) +implicit(.implicitString.anotherStringInt) +// Member types along the chain can have different generic arguments +implicit(.implicit.anotherIntString.anotherStringInt) + +implicit(.implicit.anotherString.anotherStringInt) // expected-error {{member chain produces result of type 'ImplicitGeneric' but contextual base was inferred as 'ImplicitGeneric'}} +implicit(.implicit.getAnotherString().anotherStringInt) // expected-error {{member chain produces result of type 'ImplicitGeneric' but contextual base was inferred as 'ImplicitGeneric'}} +implicit(.implicit.anotherString.getAnotherStringInt()) // expected-error {{member chain produces result of type 'ImplicitGeneric' but contextual base was inferred as 'ImplicitGeneric'}} +implicit(.implicit.getAnotherString().getAnotherStringInt()) // expected-error {{member chain produces result of type 'ImplicitGeneric' but contextual base was inferred as 'ImplicitGeneric'}} + +// Implicit member syntax can be used to apply curried instance methods: +struct Curried { + func method() -> Curried { Curried() } + func method(with arg: Int) -> Curried { Curried() } + func method(with arg1: Int, and arg2: String) -> Curried { Curried() } + func takesClosure(_: (Int) -> Void) -> Curried { Curried() } + func takesArgClosure(_: Int, _: (Int) -> Void) -> Curried { Curried() } + static func curried(_ _self: Curried) -> () -> Curried{ return { _self } } + static func curriedWithArgs(_ _self: Curried) -> (Int, String) -> Curried { return { _, _ in _self } } +} + +let _: Curried = .method(Curried())() +let _: Curried = .method(Curried())(with: 0) +let _: Curried = .method(Curried())(with: 0, and: "") +let _: Curried = .takesClosure(Curried())() { _ in } +let _: Curried = .takesArgClosure(Curried())(0) { _ in } +let _: Curried = .curried(Curried())() +let _: Curried = .curriedWithArgs(Curried())(0, "") + + +struct CurriedGeneric { + func create(_: U.Type) -> CurriedGeneric { return CurriedGeneric() } +} + +extension CurriedGeneric where T == Int { + func createInt() -> Self { + return self + } +} + +let _: CurriedGeneric = .createInt(CurriedGeneric())() +let _: CurriedGeneric = .create(CurriedGeneric())(Int.self) diff --git a/test/expr/delayed-ident/nested_type.swift b/test/expr/delayed-ident/nested_type.swift index da8a3fece6538..520d08c90dea9 100644 --- a/test/expr/delayed-ident/nested_type.swift +++ b/test/expr/delayed-ident/nested_type.swift @@ -4,12 +4,21 @@ class Base { class Derived : Base { init(x: Int) {} + class Sub: Derived { + init(y: Int) {} + } + typealias Ident = Derived + typealias Ident2 = Base } typealias Ident = Base } let _: Base = .Derived(x: 12) let _: Base = .Ident() +let _: Base = .Derived.Sub(y: 1) +let _: Base = .Derived.init(x: 3) +let _: Base = .Derived.Ident(x: 3) +let _: Base = .Derived.Ident2() // Typealias in protocol. protocol P { @@ -19,9 +28,19 @@ extension P { typealias Impl2 = ConcreteP } struct ConcreteP : P { + struct NestedP: P {} + typealias Same = ConcreteP } let _: P = .Impl1() let _: P = .Impl2() let _: ConcreteP = .Impl1() let _: ConcreteP = .Impl2() +let _: P = .Impl1.NestedP() +let _: P = .Impl2.NestedP() +let _: ConcreteP = .Impl1.Same() +let _: ConcreteP = .Impl2.Same() +let _: P = .Impl1.init() +let _: P = .Impl2.init() +let _: ConcreteP = .Impl1.init() +let _: ConcreteP = .Impl2.init() diff --git a/test/expr/delayed-ident/static_var.swift b/test/expr/delayed-ident/static_var.swift index cfe701754f791..3a01e7ff4137c 100644 --- a/test/expr/delayed-ident/static_var.swift +++ b/test/expr/delayed-ident/static_var.swift @@ -50,8 +50,7 @@ var _: HasClosure = .factoryOpt(3) // expected-error@-1 {{value of optional type '((Int) -> HasClosure)?' must be unwrapped to a value of type '(Int) -> HasClosure'}} // expected-note@-2 {{coalesce}} // expected-note@-3 {{force-unwrap}} -// FIXME: we should accept this -var _: HasClosure = .factoryOpt!(4) // expected-error {{cannot infer contextual base in reference to member 'factoryOpt'}} +var _: HasClosure = .factoryOpt!(4) infix operator =%: ComparisonPrecedence diff --git a/test/expr/postfix/dot/optional_context_member.swift b/test/expr/postfix/dot/optional_context_member.swift index b761c21657ab6..c3279781e40b0 100644 --- a/test/expr/postfix/dot/optional_context_member.swift +++ b/test/expr/postfix/dot/optional_context_member.swift @@ -27,9 +27,8 @@ func nonOptContext() -> Foo { // expected-error@-1 {{value of optional type 'Foo?' must be unwrapped to a value of type 'Foo'}} // expected-note@-2 {{coalesce}} // expected-note@-3 {{force-unwrap}} - // TODO - //case (): - // return .someOptFunc()! + case (): // expected-warning {{case is already handled by previous patterns; consider removing it}} + return .someOptFunc()! } } diff --git a/test/expr/unary/async_await.swift b/test/expr/unary/async_await.swift index 2ab75eae60eb4..3601108f8e90c 100644 --- a/test/expr/unary/async_await.swift +++ b/test/expr/unary/async_await.swift @@ -1,10 +1,74 @@ // RUN: %target-swift-frontend -typecheck -verify %s -enable-experimental-concurrency func test1(asyncfp : () async -> Int, fp : () -> Int) async { - _ = __await asyncfp() - _ = __await asyncfp() + asyncfp() - _ = __await asyncfp() + fp() - _ = __await fp() + 42 // expected-warning {{no calls to 'async' functions occur within 'await' expression}} + _ = await asyncfp() + _ = await asyncfp() + asyncfp() + _ = await asyncfp() + fp() + _ = await fp() + 42 // expected-warning {{no calls to 'async' functions occur within 'await' expression}} _ = asyncfp() // expected-error {{call is 'async' but is not marked with 'await'}} } +func getInt() async -> Int { return 5 } + +// Locations where "await" is prohibited. +func test2( + defaulted: Int = await getInt() // expected-error{{'async' call cannot occur in a default argument}} +) async { + defer { + _ = await getInt() // expected-error{{'async' call cannot occur in a defer body}} + } + print("foo") +} + +func test3() { // expected-note{{add 'async' to function 'test3()' to make it asynchronous}} + // expected-note@-1{{add '@asyncHandler' to function 'test3()' to create an implicit asynchronous context}}{{1-1=@asyncHandler }} + _ = await getInt() // expected-error{{'async' in a function that does not support concurrency}} +} + +enum SomeEnum: Int { +case foo = await 5 // expected-error{{raw value for enum case must be a literal}} +} + +struct SomeStruct { + var x = await getInt() // expected-error{{'async' call cannot occur in a property initializer}} + static var y = await getInt() // expected-error{{'async' call cannot occur in a global variable initializer}} +} + +func acceptAutoclosureNonAsync(_: @autoclosure () -> Int) async { } +func acceptAutoclosureAsync(_: @autoclosure () async -> Int) async { } + +func acceptAutoclosureNonAsyncBad(_: @autoclosure () async -> Int) -> Int { 0 } +// expected-error@-1{{'async' autoclosure parameter in a non-'async' function}} +// expected-note@-2{{add 'async' to function 'acceptAutoclosureNonAsyncBad' to make it asynchronous}} + +struct HasAsyncBad { + init(_: @autoclosure () async -> Int) { } + // expected-error@-1{{'async' autoclosure parameter in a non-'async' function}} +} + +func testAutoclosure() async { + await acceptAutoclosureAsync(getInt()) // expected-error{{call is 'async' in an autoclosure argument that is not marked with 'await'}} + await acceptAutoclosureNonAsync(getInt()) // expected-error{{'async' in an autoclosure that does not support concurrency}} + + await acceptAutoclosureAsync(await getInt()) + await acceptAutoclosureNonAsync(await getInt()) // expected-error{{'async' in an autoclosure that does not support concurrency}} + + await acceptAutoclosureAsync(getInt()) // expected-error{{call is 'async' in an autoclosure argument that is not marked with 'await'}} + await acceptAutoclosureNonAsync(getInt()) // expected-error{{'async' in an autoclosure that does not support concurrency}} +} + +// Test inference of 'async' from the body of a closure. +func testClosure() { + let closure = { + await getInt() + } + + let _: () -> Int = closure // expected-error{{cannot convert value of type '() async -> Int' to specified type '() -> Int'}} + + let closure2 = { () async -> Int in + print("here") + return await getInt() + } + + let _: () -> Int = closure2 // expected-error{{cannot convert value of type '() async -> Int' to specified type '() -> Int'}} +} diff --git a/test/expr/unary/keypath/keypath.swift b/test/expr/unary/keypath/keypath.swift index d6fd26dade0f4..326e148b5b6a7 100644 --- a/test/expr/unary/keypath/keypath.swift +++ b/test/expr/unary/keypath/keypath.swift @@ -36,7 +36,7 @@ struct A: Hashable { func hash(into hasher: inout Hasher) { fatalError() } } struct B {} -struct C { // expected-note 3 {{'T' declared as parameter to type 'C'}} +struct C { // expected-note 4 {{'T' declared as parameter to type 'C'}} var value: T subscript() -> T { get { return value } } subscript(sub: Sub) -> T { get { return value } set { } } @@ -224,15 +224,17 @@ func testKeyPathInGenericContext(hashable: H, anything: X) { } func testDisembodiedStringInterpolation(x: Int) { - \(x) // expected-error{{string interpolation}} expected-error{{}} - \(x, radix: 16) // expected-error{{string interpolation}} expected-error{{}} + \(x) // expected-error{{string interpolation can only appear inside a string literal}} + \(x, radix: 16) // expected-error{{string interpolation can only appear inside a string literal}} } func testNoComponents() { let _: KeyPath = \A // expected-error{{must have at least one component}} - let _: KeyPath = \C // expected-error{{must have at least one component}} expected-error{{}} + let _: KeyPath = \C // expected-error{{must have at least one component}} // expected-error@-1 {{generic parameter 'T' could not be inferred}} - // expected-error@-2 {{cannot convert value of type 'KeyPath' to specified type 'KeyPath, A>'}} + let _: KeyPath = \A // expected-error{{must have at least one component}} + // expected-error@-1 {{generic parameter 'T' could not be inferred}} + _ = \A // expected-error {{key path must have at least one component}} } struct TupleStruct { @@ -322,8 +324,8 @@ func testKeyPathSubscript(readonly: Z, writable: inout Z, var anySink2 = writable[keyPath: pkp] expect(&anySink2, toHaveType: Exactly.self) - readonly[keyPath: pkp] = anySink1 // expected-error{{cannot assign through subscript: 'readonly' is a 'let' constant}} - writable[keyPath: pkp] = anySink2 // expected-error{{cannot assign through subscript: 'writable' is immutable}} + readonly[keyPath: pkp] = anySink1 // expected-error{{cannot assign through subscript: 'pkp' is a read-only key path}} + writable[keyPath: pkp] = anySink2 // expected-error{{cannot assign through subscript: 'pkp' is a read-only key path}} let akp: AnyKeyPath = pkp @@ -441,12 +443,12 @@ func testKeyPathSubscriptLValue(base: Z, kp: inout KeyPath) { } func testKeyPathSubscriptExistentialBase(concreteBase: inout B, - existentialBase: inout P, - kp: KeyPath, - wkp: WritableKeyPath, - rkp: ReferenceWritableKeyPath, - pkp: PartialKeyPath

, - s: String) { + existentialBase: inout P, + kp: KeyPath, + wkp: WritableKeyPath, + rkp: ReferenceWritableKeyPath, + pkp: PartialKeyPath

, + s: String) { _ = concreteBase[keyPath: kp] _ = concreteBase[keyPath: wkp] _ = concreteBase[keyPath: rkp] @@ -455,9 +457,7 @@ func testKeyPathSubscriptExistentialBase(concreteBase: inout B, concreteBase[keyPath: kp] = s // expected-error {{cannot assign through subscript: 'kp' is a read-only key path}} concreteBase[keyPath: wkp] = s // expected-error {{key path with root type 'P' cannot be applied to a base of type 'B'}} concreteBase[keyPath: rkp] = s - // TODO(diagnostics): Improve this diagnostic message because concreteBase is mutable, the problem is related to assign - // through PartialKeyPath. - concreteBase[keyPath: pkp] = s // expected-error {{cannot assign through subscript: 'concreteBase' is immutable}} + concreteBase[keyPath: pkp] = s // expected-error {{cannot assign through subscript: 'pkp' is a read-only key path}} _ = existentialBase[keyPath: kp] _ = existentialBase[keyPath: wkp] @@ -467,9 +467,7 @@ func testKeyPathSubscriptExistentialBase(concreteBase: inout B, existentialBase[keyPath: kp] = s // expected-error {{cannot assign through subscript: 'kp' is a read-only key path}} existentialBase[keyPath: wkp] = s existentialBase[keyPath: rkp] = s - // TODO(diagnostics): Improve this diagnostic message because existentialBase is mutable, the problem is related to assign - // through PartialKeyPath. - existentialBase[keyPath: pkp] = s // expected-error {{cannot assign through subscript: 'existentialBase' is immutable}} + existentialBase[keyPath: pkp] = s // expected-error {{cannot assign through subscript: 'pkp' is a read-only key path}} } struct AA { @@ -1008,9 +1006,12 @@ func testMemberAccessOnOptionalKeyPathComponent() { // expected-error@-1 {{value of optional type '(Int, Int)?' must be unwrapped to refer to member '0' of wrapped base type '(Int, Int)'}} // expected-note@-2 {{use unwrapped type '(Int, Int)' as key path root}}{{4-15=(Int, Int)}} - // TODO(diagnostics) Improve diagnostics refering to key path root not able to be infered as an optional type. - SR5688_KP(\.count) - // expected-error@-1 {{value of optional type 'String?' must be unwrapped to refer to member 'count' of wrapped base type 'String'}} + SR5688_KP(\.count) // expected-error {{key path root inferred as optional type 'String?' must be unwrapped to refer to member 'count' of unwrapped type 'String'}} + // expected-note@-1 {{chain the optional using '?.' to access unwrapped type member 'count'}} {{15-15=?.}} + // expected-note@-2 {{unwrap the optional using '!.' to access unwrapped type member 'count'}} {{15-15=!.}} + let _ : KeyPath = \.count // expected-error {{key path root inferred as optional type 'String?' must be unwrapped to refer to member 'count' of unwrapped type 'String'}} + // expected-note@-1 {{chain the optional using '?.' to access unwrapped type member 'count'}} {{37-37=?.}} + // expected-note@-2 {{unwrap the optional using '!.' to access unwrapped type member 'count'}} {{37-37=!.}} } func testSyntaxErrors() { diff --git a/test/lit.cfg b/test/lit.cfg index f7f82f9c21c33..eb89863eded81 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -283,6 +283,7 @@ config.complete_test = inferSwiftBinary('complete-test') config.swift_api_digester = inferSwiftBinary('swift-api-digester') config.swift_refactor = inferSwiftBinary('swift-refactor') config.swift_demangle_yamldump = inferSwiftBinary('swift-demangle-yamldump') +config.swift_demangle = inferSwiftBinary('swift-demangle') config.benchmark_o = inferSwiftBinary('Benchmark_O') config.benchmark_driver = inferSwiftBinary('Benchmark_Driver') config.wasmer = inferSwiftBinary('wasmer') @@ -440,6 +441,7 @@ config.substitutions.append( ('%llvm-readelf', config.llvm_readelf) ) config.substitutions.append( ('%llvm-dis', config.llvm_dis) ) config.substitutions.append( ('%llvm-nm', config.llvm_nm) ) config.substitutions.append( ('%swift-demangle-yamldump', config.swift_demangle_yamldump) ) +config.substitutions.append( ('%swift-demangle', config.swift_demangle) ) config.substitutions.append( ('%Benchmark_O', config.benchmark_o) ) config.substitutions.append( ('%Benchmark_Driver', config.benchmark_driver) ) config.substitutions.append( ('%llvm-strings', config.llvm_strings) ) @@ -2062,4 +2064,3 @@ else: num_extra_inhabitants_64bit = 4096 add_num_extra_inhabitants = "-D#num_extra_inhabitants_64bit={} ".format(num_extra_inhabitants_64bit) config.substitutions.append(('%add_num_extra_inhabitants', add_num_extra_inhabitants)) - diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index 7166762c20712..f1a01a1dff791 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -90,8 +90,8 @@ if "@SWIFT_AST_VERIFIER@" == "TRUE": if "@SWIFT_OPTIMIZED@" == "TRUE": config.available_features.add("optimized_stdlib") -if "@SWIFT_STDLIB_USE_NONATOMIC_RC@" == "TRUE": - config.available_features.add("nonatomic_rc") +if "@SWIFT_STDLIB_SINGLE_THREADED_RUNTIME@" == "TRUE": + config.available_features.add("single_threaded_runtime") if "@SWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS@" == "TRUE": config.available_features.add('runtime_function_counters') diff --git a/test/stdlib/Casts.swift b/test/stdlib/Casts.swift deleted file mode 100644 index 5e81f6643b154..0000000000000 --- a/test/stdlib/Casts.swift +++ /dev/null @@ -1,236 +0,0 @@ -// Casts.swift - Tests for conversion between types. -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2017 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 -// -// ----------------------------------------------------------------------------- -/// -/// Contains tests for conversions between types which shouldn't trap. -/// -// ----------------------------------------------------------------------------- -// RUN: %target-run-simple-swift(-Xfrontend -enable-experimental-concurrency) -// REQUIRES: executable_test -// UNSUPPORTED: use_os_stdlib - -import StdlibUnittest -#if _runtime(_ObjC) -import Foundation -#endif - -private func blackhole(_ t: T) {} - -let CastsTests = TestSuite("Casts") - -// Test for SR-426: missing release for some types after failed conversion -CastsTests.test("No leak for failed tuple casts") { - let t: Any = (1, LifetimeTracked(0)) - expectFalse(t is Any.Type) -} - -protocol P {} -class ErrClass : Error { } - -CastsTests.test("No overrelease of existential boxes in failed casts") { - // Test for crash from SR-392 - // We fail casts of an existential box repeatedly - // to ensure it does not get over-released. - func bar(_ t: T) { - for _ in 0..<10 { - if case let a as P = t { - _ = a - } - } - } - - let err: Error = ErrClass() - bar(err) -} - -extension Int : P {} - -// Test for SR-7664: Inconsistent optional casting behaviour with generics -// Runtime failed to unwrap multiple levels of Optional when casting. -CastsTests.test("Multi-level optionals can be casted") { - func testSuccess(_ x: From, from: From.Type, to: To.Type) { - expectNotNil(x as? To) - } - func testFailure(_ x: From, from: From.Type, to: To.Type) { - expectNil(x as? To) - } - testSuccess(42, from: Int?.self, to: Int.self) - testSuccess(42, from: Int??.self, to: Int.self) - testSuccess(42, from: Int???.self, to: Int.self) - testSuccess(42, from: Int???.self, to: Int?.self) - testSuccess(42, from: Int???.self, to: Int??.self) - testSuccess(42, from: Int???.self, to: Int???.self) - testFailure(42, from: Int?.self, to: String.self) - testFailure(42, from: Int??.self, to: String.self) - testFailure(42, from: Int???.self, to: String.self) -} - -// Test for SR-9837: Optional.none not casting to Optional.none in generic context -CastsTests.test("Optional.none can be casted to Optional.none in generic context") { - func test(_ type: T.Type) -> T? { - return Any?.none as? T - } - - expectEqual(type(of: test(Bool.self)), Bool?.self) - expectEqual(type(of: test(Bool?.self)), Bool??.self) -} - -// Test for SR-3871: Cannot cast from ObjC existential without going through AnyObject -#if _runtime(_ObjC) -protocol P2 {} -CastsTests.test("Cast from ObjC existential to Protocol (SR-3871)") { - if #available(macOS 10.16, iOS 14.0, watchOS 7.0, tvOS 14.0, *) { - struct S: P2 {} - - class ObjCWrapper { - @objc dynamic let any: Any = S() - init() {} - } - let a = ObjCWrapper().any - expectTrue(a is P2) - // In SR-3871, the following cast failed (everything else here succeeded) - expectNotNil(a as? P2) - expectNotNil(a as? S) - let b = a as AnyObject - expectTrue(a is P2) - expectNotNil(b as? P2) - expectNotNil(b as? S) - } -} -#endif - -protocol P3 {} -CastsTests.test("Cast from Swift existential to Protocol") { - struct S: P3 {} - class SwiftWrapper { - let any: Any = S() - init() {} - } - let a = SwiftWrapper().any - expectTrue(a is P3) - expectNotNil(a as? P3) - expectNotNil(a as? S) - let b = a as AnyObject - expectTrue(b is P3) - expectNotNil(b as? P3) - expectNotNil(b as? S) -} - - -#if _runtime(_ObjC) -extension CFBitVector : P { - static func makeImmutable(from values: Array) -> CFBitVector { - return CFBitVectorCreate(/*allocator:*/ nil, values, values.count * 8) - } -} - -extension CFMutableBitVector { - static func makeMutable(from values: Array) -> CFMutableBitVector { - return CFBitVectorCreateMutableCopy( - /*allocator:*/ nil, - /*capacity:*/ 0, - CFBitVector.makeImmutable(from: values)) - } -} - -func isP(_ t: T) -> Bool { - return t is P -} - -CastsTests.test("Dynamic casts of CF types to protocol existentials") - .skip(.custom( - { !_isDebugAssertConfiguration() }, - reason: "This test behaves unpredictably in optimized mode.")) - .code { - expectTrue(isP(10 as Int)) - - // FIXME: SR-2289: dynamic casting of CF types to protocol existentials - // should work, but there is a bug in the runtime that prevents them from - // working. - expectFailure { - expectTrue(isP(CFBitVector.makeImmutable(from: [10, 20]))) - } - expectFailure { - expectTrue(isP(CFMutableBitVector.makeMutable(from: [10, 20]))) - } -} -#endif - -CastsTests.test("Any.Protocol") { - class C {} - struct S {} - func isAnyProtocol(_ type: T.Type) -> Bool { - let result = T.self is Any.Protocol - if result { - // `as!` should succeed if `is` does - blackhole(T.self as! Any.Protocol) - } - return result - } - func isAnyType(_ type: T.Type) -> Bool { - return T.self is Any.Type - } - func isType(_ type: T.Type, to: U.Type) -> Bool { - return T.self is U.Type - } - - expectTrue(Int.self is Any.Type) - expectNotNil(Int.self as? Any.Type) - expectTrue(isAnyType(Int.self)) - expectFalse(Int.self is Any.Protocol) - expectNil(Int.self as? Any.Protocol) - expectFalse(isAnyProtocol(Int.self)) - expectFalse(isType(Int.self, to: Any.self)) - - expectTrue(C.self is Any.Type) - expectNotNil(C.self as? Any.Type) - expectTrue(isAnyType(C.self)) - expectFalse(C.self is Any.Protocol) - expectNil(C.self as? Any.Protocol) - expectFalse(isAnyProtocol(C.self)) - expectFalse(isType(C.self, to: Any.self)) - - expectTrue(S.self is Any.Type) - expectNotNil(S.self as? Any.Type) - expectTrue(isAnyType(S.self)) - expectFalse(S.self is Any.Protocol) - expectNil(S.self as? Any.Protocol) - expectFalse(isAnyProtocol(S.self)) - expectFalse(isType(S.self, to: Any.self)) - - expectTrue(Any.self is Any.Type) - expectNotNil(Any.self as? Any.Type) - expectTrue(isAnyType(Any.self)) - expectTrue(Any.self is Any.Protocol) - expectNotNil(Any.self as? Any.Protocol) - expectTrue(isAnyProtocol(Any.self)) - expectTrue(isType(Any.self, to: Any.self)) - - expectTrue(Any?.self is Any.Type) - expectNotNil(Any?.self as? Any.Type) - expectTrue(isAnyType(Any?.self)) - expectFalse(Any?.self is Any.Protocol) - expectNil(Any?.self as? Any.Protocol) - expectFalse(isAnyProtocol(Any?.self)) - expectFalse(isType(Any?.self, to: Any.self)) -} - -CastsTests.test("Async function types") { - let asyncFnType: Any.Type = (() async -> Void).self - let fnType: Any.Type = (() -> Void).self - - expectTrue(fnType is (() -> Void).Type) - expectTrue(asyncFnType is (() async -> Void).Type) - expectFalse(fnType is (() async -> Void).Type) - expectFalse(asyncFnType is (() -> Void).Type) -} - -runAllTests() diff --git a/test/stdlib/Error.swift b/test/stdlib/Error.swift index e21e525ad02b0..7c95c04c72481 100644 --- a/test/stdlib/Error.swift +++ b/test/stdlib/Error.swift @@ -1,11 +1,11 @@ // RUN: %empty-directory(%t) // RUN: %target-build-swift -o %t/Error -DPTR_SIZE_%target-ptrsize -module-name main %/s +// RUN: %target-codesign %t/Error // RUN: %target-run %t/Error // REQUIRES: executable_test import StdlibUnittest - var ErrorTests = TestSuite("Error") var NoisyErrorLifeCount = 0 diff --git a/test/stdlib/Reflection_jit.swift b/test/stdlib/Reflection_jit.swift index c36b6b6e8cc9f..8704ba6069ceb 100644 --- a/test/stdlib/Reflection_jit.swift +++ b/test/stdlib/Reflection_jit.swift @@ -2,3 +2,8 @@ // RUN: %target-jit-run -parse-stdlib %S/Reflection.swift -- %S/Inputs/shuffle.jpg | %FileCheck %S/Reflection.swift // REQUIRES: swift_interpreter + +// Only run this test when we build host tools (e.g. bin/swift-frontend), avoid running it for standalone stdlib builds. +// Standalone stdlib builds use downloadable toolchains from swift.org, which are codesigned in a way that doesn't let +// the interpreter process (swift-frontend) dynamically load locally-built modules (libswiftCore). +// REQUIRES: swift_tools_extra diff --git a/test/stdlib/symbol-visibility-linux.test-sh b/test/stdlib/symbol-visibility-linux.test-sh index 62be057f4d919..2472610c3e51b 100644 --- a/test/stdlib/symbol-visibility-linux.test-sh +++ b/test/stdlib/symbol-visibility-linux.test-sh @@ -19,6 +19,7 @@ // RUN: -e _ZNSt6vectorIjSaIjEE13_M_insert_auxIJjEEEvN9__gnu_cxx17__normal_iteratorIPjS1_EEDpOT_ \ // RUN: -e _ZNSt6vectorISt10unique_ptrIKvSt8functionIFvPS1_EEESaIS6_EE19_M_emplace_back_auxIJS6_EEEvDpOT_ \ // RUN: -e _ZNSt6vectorISt10unique_ptrIKvSt8functionIFvPS1_EEESaIS6_EE17_M_realloc_insertIJS6_EEEvN9__gnu_cxx17__normal_iteratorIPS6_S8_EEDpOT_ \ +// RUN: -e _ZNSt3_V28__rotateIPcEET_S2_S2_S2_St26random_access_iterator_tag \ // RUN: -e _ZN9__gnu_cxx12__to_xstringINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEcEET_PFiPT0_mPKS8_P13__va_list_tagEmSB_z \ // RUN: -e _ZZNSt19_Sp_make_shared_tag5_S_tiEvE5__tag \ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEDnEEEvv \ @@ -30,6 +31,8 @@ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA80_cEEEvv \ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA88_cEEEvv \ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA104_cEEEvv \ +// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA168_cEEEvv \ +// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA216_cEEEvv \ // RUN: -e _ZN9__gnu_cxx12__to_xstringISscEET_PFiPT0_mPKS2_P13__va_list_tagEmS5_z \ // RUN: > %t/swiftCore-all.txt // RUN: %llvm-nm --defined-only --extern-only --no-weak %platform-dylib-dir/%target-library-name(swiftCore) > %t/swiftCore-no-weak.txt @@ -41,6 +44,7 @@ // RUN: -e _ZNSt6vectorIjSaIjEE13_M_insert_auxIJjEEEvN9__gnu_cxx17__normal_iteratorIPjS1_EEDpOT_ \ // RUN: -e _ZNSt6vectorISt10unique_ptrIKvSt8functionIFvPS1_EEESaIS6_EE19_M_emplace_back_auxIJS6_EEEvDpOT_ \ // RUN: -e _ZNSt6vectorISt10unique_ptrIKvSt8functionIFvPS1_EEESaIS6_EE17_M_realloc_insertIJS6_EEEvN9__gnu_cxx17__normal_iteratorIPS6_S8_EEDpOT_ \ +// RUN: -e _ZNSt3_V28__rotateIPcEET_S2_S2_S2_St26random_access_iterator_tag \ // RUN: -e _ZN9__gnu_cxx12__to_xstringINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEcEET_PFiPT0_mPKS8_P13__va_list_tagEmSB_z \ // RUN: -e _ZZNSt19_Sp_make_shared_tag5_S_tiEvE5__tag \ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEDnEEEvv \ @@ -52,6 +56,8 @@ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA80_cEEEvv \ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA88_cEEEvv \ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA104_cEEEvv \ +// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA168_cEEEvv \ +// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA216_cEEEvv \ // RUN: -e _ZN9__gnu_cxx12__to_xstringISscEET_PFiPT0_mPKS2_P13__va_list_tagEmS5_z \ // RUN: > %t/swiftRemoteMirror-all.txt // RUN: %llvm-nm --defined-only --extern-only --no-weak %platform-dylib-dir/%target-library-name(swiftRemoteMirror) > %t/swiftRemoteMirror-no-weak.txt diff --git a/test/stmt/statements.swift b/test/stmt/statements.swift index b2594eb8f3398..93de7f6efabc8 100644 --- a/test/stmt/statements.swift +++ b/test/stmt/statements.swift @@ -280,7 +280,7 @@ func RepeatWhileStmt4() { func brokenSwitch(_ x: Int) -> Int { switch x { - case .Blah(var rep): // expected-error{{pattern cannot match values of type 'Int'}} + case .Blah(var rep): // expected-error{{type 'Int' has no member 'Blah'}} return rep } } diff --git a/tools/SourceKit/lib/Support/CMakeLists.txt b/tools/SourceKit/lib/Support/CMakeLists.txt index 901720a521069..3b18cc18e98c9 100644 --- a/tools/SourceKit/lib/Support/CMakeLists.txt +++ b/tools/SourceKit/lib/Support/CMakeLists.txt @@ -1,6 +1,5 @@ add_sourcekit_library(SourceKitSupport Concurrency-libdispatch.cpp - FuzzyStringMatcher.cpp Logging.cpp ImmutableTextBuffer.cpp ThreadSafeRefCntPtr.cpp diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletion.h b/tools/SourceKit/lib/SwiftLang/CodeCompletion.h index 266282ab3f15b..f8098fbaf8390 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletion.h +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletion.h @@ -132,12 +132,6 @@ class CompletionBuilder { Optional moduleImportDepth; PopularityFactor popularityFactor; -public: - static void getFilterName(CodeCompletionString *str, raw_ostream &OS); - static void getDescription(SwiftResult *result, raw_ostream &OS, - bool leadingPunctuation, - bool annotatedDecription = false); - public: CompletionBuilder(CompletionSink &sink, SwiftResult &base); diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp index 8ac901da4de3c..c24e17a0e1afd 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp @@ -11,10 +11,10 @@ //===----------------------------------------------------------------------===// #include "CodeCompletionOrganizer.h" -#include "SourceKit/Support/FuzzyStringMatcher.h" #include "swift/AST/ASTContext.h" #include "swift/AST/Module.h" #include "swift/IDE/CodeCompletionResultPrinter.h" +#include "swift/IDE/FuzzyStringMatcher.h" #include "swift/Frontend/Frontend.h" #include "swift/Markup/XMLUtils.h" #include "clang/Basic/CharInfo.h" @@ -1209,72 +1209,6 @@ bool LimitedResultView::walk(CodeCompletionView::Walker &walker) const { // CompletionBuilder //===----------------------------------------------------------------------===// -void CompletionBuilder::getFilterName(CodeCompletionString *str, - raw_ostream &OS) { - using ChunkKind = CodeCompletionString::Chunk::ChunkKind; - - // FIXME: we need a more uniform way to handle operator completions. - if (str->getChunks().size() == 1 && str->getChunks()[0].is(ChunkKind::Dot)) { - OS << "."; - return; - } else if (str->getChunks().size() == 2 && - str->getChunks()[0].is(ChunkKind::QuestionMark) && - str->getChunks()[1].is(ChunkKind::Dot)) { - OS << "?."; - return; - } - - auto FirstTextChunk = str->getFirstTextChunkIndex(); - if (FirstTextChunk.hasValue()) { - auto chunks = str->getChunks().slice(*FirstTextChunk); - for (auto i = chunks.begin(), e = chunks.end(); i != e; ++i) { - auto &C = *i; - - if (C.is(ChunkKind::BraceStmtWithCursor)) - break; // Don't include brace-stmt in filter name. - - if (C.is(ChunkKind::Equal)) { - OS << C.getText(); - break; - } - - bool shouldPrint = !C.isAnnotation(); - switch (C.getKind()) { - case ChunkKind::TypeAnnotation: - case ChunkKind::CallParameterInternalName: - case ChunkKind::CallParameterClosureType: - case ChunkKind::CallParameterClosureExpr: - case ChunkKind::CallParameterType: - case ChunkKind::DeclAttrParamColon: - case ChunkKind::Comma: - case ChunkKind::Whitespace: - case ChunkKind::Ellipsis: - case ChunkKind::Ampersand: - case ChunkKind::OptionalMethodCallTail: - continue; - case ChunkKind::CallParameterTypeBegin: - case ChunkKind::TypeAnnotationBegin: { - // Skip call parameter type or type annotation structure. - auto nestingLevel = C.getNestingLevel(); - do { ++i; } while (i != e && !i->endsPreviousNestedGroup(nestingLevel)); - --i; - continue; - } - case ChunkKind::CallParameterColon: - // Since we don't add the type, also don't add the space after ':'. - if (shouldPrint) - OS << ":"; - continue; - default: - break; - } - - if (C.hasText() && shouldPrint) - OS << C.getText(); - } - } -} - CompletionBuilder::CompletionBuilder(CompletionSink &sink, SwiftResult &base) : sink(sink), current(base) { typeRelation = current.getExpectedTypeRelation(); @@ -1286,7 +1220,7 @@ CompletionBuilder::CompletionBuilder(CompletionSink &sink, SwiftResult &base) // strings for our inner "." result. if (current.getCompletionString()->getFirstTextChunkIndex().hasValue()) { llvm::raw_svector_ostream OSS(originalName); - getFilterName(current.getCompletionString(), OSS); + ide::printCodeCompletionResultFilterName(current, OSS); } } @@ -1336,7 +1270,7 @@ Completion *CompletionBuilder::finish() { } llvm::raw_svector_ostream OSS(nameStorage); - getFilterName(base.getCompletionString(), OSS); + ide::printCodeCompletionResultFilterName(base, OSS); name = OSS.str(); } diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp index 7b30a003845b7..dfc5ea55b7daf 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp @@ -40,36 +40,6 @@ using namespace SourceKit; using namespace swift; using namespace swift::sys; -namespace { -class StreamDiagConsumer : public DiagnosticConsumer { - llvm::raw_ostream &OS; - -public: - StreamDiagConsumer(llvm::raw_ostream &OS) : OS(OS) {} - - void handleDiagnostic(SourceManager &SM, - const DiagnosticInfo &Info) override { - // FIXME: Print location info if available. - switch (Info.Kind) { - case DiagnosticKind::Error: - OS << "error: "; - break; - case DiagnosticKind::Warning: - OS << "warning: "; - break; - case DiagnosticKind::Note: - OS << "note: "; - break; - case DiagnosticKind::Remark: - OS << "remark: "; - break; - } - DiagnosticEngine::formatDiagnosticText(OS, Info.FormatString, - Info.FormatArgs); - } -}; -} // end anonymous namespace - void SwiftASTConsumer::failed(StringRef Error) { } //===----------------------------------------------------------------------===// @@ -433,46 +403,6 @@ convertFileContentsToInputs(const SmallVectorImpl &contents) { return inputsAndOutputs; } -static FrontendInputsAndOutputs resolveSymbolicLinksInInputs( - FrontendInputsAndOutputs &inputsAndOutputs, StringRef UnresolvedPrimaryFile, - llvm::IntrusiveRefCntPtr FileSystem, - std::string &Error) { - assert(FileSystem); - - llvm::SmallString<128> PrimaryFile; - if (auto err = FileSystem->getRealPath(UnresolvedPrimaryFile, PrimaryFile)) - PrimaryFile = UnresolvedPrimaryFile; - - unsigned primaryCount = 0; - // FIXME: The frontend should be dealing with symlinks, maybe similar to - // clang's FileManager ? - FrontendInputsAndOutputs replacementInputsAndOutputs; - for (const InputFile &input : inputsAndOutputs.getAllInputs()) { - llvm::SmallString<128> newFilename; - if (auto err = FileSystem->getRealPath(input.file(), newFilename)) - newFilename = input.file(); - llvm::sys::path::native(newFilename); - bool newIsPrimary = input.isPrimary() || - (!PrimaryFile.empty() && PrimaryFile == newFilename); - if (newIsPrimary) { - ++primaryCount; - } - assert(primaryCount < 2 && "cannot handle multiple primaries"); - replacementInputsAndOutputs.addInput( - InputFile(newFilename.str(), newIsPrimary, input.buffer())); - } - - if (PrimaryFile.empty() || primaryCount == 1) { - return replacementInputsAndOutputs; - } - - llvm::SmallString<64> Err; - llvm::raw_svector_ostream OS(Err); - OS << "'" << PrimaryFile << "' is not part of the input files"; - Error = std::string(OS.str()); - return replacementInputsAndOutputs; -} - bool SwiftASTManager::initCompilerInvocation( CompilerInvocation &Invocation, ArrayRef OrigArgs, DiagnosticEngine &Diags, StringRef UnresolvedPrimaryFile, @@ -488,101 +418,10 @@ bool SwiftASTManager::initCompilerInvocation( DiagnosticEngine &Diags, StringRef UnresolvedPrimaryFile, llvm::IntrusiveRefCntPtr FileSystem, std::string &Error) { - SmallVector Args; - // Make sure to put '-resource-dir' and '-diagnostic-documentation-path' at - // the top to allow overriding them with the passed in arguments. - Args.push_back("-resource-dir"); - Args.push_back(Impl.RuntimeResourcePath.c_str()); - Args.push_back("-Xfrontend"); - Args.push_back("-diagnostic-documentation-path"); - Args.push_back("-Xfrontend"); - Args.push_back(Impl.DiagnosticDocumentationPath.c_str()); - Args.append(OrigArgs.begin(), OrigArgs.end()); - - SmallString<32> ErrStr; - llvm::raw_svector_ostream ErrOS(ErrStr); - StreamDiagConsumer DiagConsumer(ErrOS); - Diags.addConsumer(DiagConsumer); - - bool HadError = driver::getSingleFrontendInvocationFromDriverArguments( - Args, Diags, [&](ArrayRef FrontendArgs) { - return Invocation.parseArgs(FrontendArgs, Diags); - }, /*ForceNoOutputs=*/true); - - // Remove the StreamDiagConsumer as it's no longer needed. - Diags.removeConsumer(DiagConsumer); - - if (HadError) { - Error = std::string(ErrOS.str()); - return true; - } - - Invocation.getFrontendOptions().InputsAndOutputs = - resolveSymbolicLinksInInputs( - Invocation.getFrontendOptions().InputsAndOutputs, - UnresolvedPrimaryFile, FileSystem, Error); - if (!Error.empty()) - return true; - - ClangImporterOptions &ImporterOpts = Invocation.getClangImporterOptions(); - ImporterOpts.DetailedPreprocessingRecord = true; - - assert(!Invocation.getModuleName().empty()); - - auto &LangOpts = Invocation.getLangOptions(); - LangOpts.AttachCommentsToDecls = true; - LangOpts.DiagnosticsEditorMode = true; - LangOpts.CollectParsedToken = true; - if (LangOpts.PlaygroundTransform) { - // The playground instrumenter changes the AST in ways that disrupt the - // SourceKit functionality. Since we don't need the instrumenter, and all we - // actually need is the playground semantics visible to the user, like - // silencing the "expression resolves to an unused l-value" error, disable it. - LangOpts.PlaygroundTransform = false; - } - - // Disable the index-store functionality for the sourcekitd requests. - auto &FrontendOpts = Invocation.getFrontendOptions(); - FrontendOpts.IndexStorePath.clear(); - ImporterOpts.IndexStorePath.clear(); - - // Force the action type to be -typecheck. This affects importing the - // SwiftONoneSupport module. - FrontendOpts.RequestedAction = FrontendOptions::ActionType::Typecheck; - - // We don't care about LLVMArgs - FrontendOpts.LLVMArgs.clear(); - - // SwiftSourceInfo files provide source location information for decls coming - // from loaded modules. For most IDE use cases it either has an undesirable - // impact on performance with no benefit (code completion), results in stale - // locations being used instead of more up-to-date indexer locations (cursor - // info), or has no observable effect (diagnostics, which are filtered to just - // those with a location in the primary file, and everything else). - if (Impl.Config->shouldOptimizeForIDE()) - FrontendOpts.IgnoreSwiftSourceInfo = true; - - // To save the time for module validation, consider the lifetime of ASTManager - // as a single build session. - // NOTE: Do this only if '-disable-modules-validate-system-headers' is *not* - // explicitly enabled. - auto &SearchPathOpts = Invocation.getSearchPathOptions(); - if (!SearchPathOpts.DisableModulesValidateSystemDependencies) { - // NOTE: 'SessionTimestamp - 1' because clang compares it with '<=' that may - // cause unnecessary validations if they happens within one second - // from the SourceKit startup. - ImporterOpts.ExtraArgs.push_back("-fbuild-session-timestamp=" + - std::to_string(Impl.SessionTimestamp - 1)); - ImporterOpts.ExtraArgs.push_back( - "-fmodules-validate-once-per-build-session"); - - SearchPathOpts.DisableModulesValidateSystemDependencies = true; - } - - // Disable expensive SIL options to reduce time spent in SILGen. - disableExpensiveSILOptions(Invocation.getSILOptions()); - - return false; + return ide::initCompilerInvocation( + Invocation, OrigArgs, Diags, UnresolvedPrimaryFile, FileSystem, + Impl.RuntimeResourcePath, Impl.DiagnosticDocumentationPath, + Impl.Config->shouldOptimizeForIDE(), Impl.SessionTimestamp, Error); } bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &CompInvok, diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp index 0870461fede85..06d3a912d4b51 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp @@ -49,8 +49,7 @@ struct SwiftToSourceKitCompletionAdapter { llvm::SmallString<64> name; { llvm::raw_svector_ostream OSS(name); - CodeCompletion::CompletionBuilder::getFilterName( - result->getCompletionString(), OSS); + ide::printCodeCompletionResultFilterName(*result, OSS); } llvm::SmallString<64> description; @@ -75,9 +74,6 @@ struct SwiftToSourceKitCompletionAdapter { bool legacyLiteralToKeyword, bool annotatedDescription); - static void getResultSourceText(const CodeCompletionString *CCStr, - raw_ostream &OS); - static void getResultAssociatedUSRs(ArrayRef AssocUSRs, raw_ostream &OS); }; @@ -466,7 +462,7 @@ bool SwiftToSourceKitCompletionAdapter::handleResult( unsigned TextBegin = SS.size(); { llvm::raw_svector_ostream ccOS(SS); - getResultSourceText(Result->getCompletionString(), ccOS); + ide::printCodeCompletionResultSourceText(*Result, ccOS); } unsigned TextEnd = SS.size(); @@ -603,121 +599,6 @@ getCodeCompletionKeywordKindForUID(UIdent uid) { return CodeCompletionKeywordKind::None; } -using ChunkKind = CodeCompletionString::Chunk::ChunkKind; - -/// Provide the text for the call parameter, including constructing a typed -/// editor placeholder for it. -static void constructTextForCallParam( - ArrayRef ParamGroup, raw_ostream &OS) { - assert(ParamGroup.front().is(ChunkKind::CallParameterBegin)); - - for (; !ParamGroup.empty(); ParamGroup = ParamGroup.slice(1)) { - auto &C = ParamGroup.front(); - if (C.isAnnotation()) - continue; - if (C.is(ChunkKind::CallParameterInternalName) || - C.is(ChunkKind::CallParameterType) || - C.is(ChunkKind::CallParameterTypeBegin) || - C.is(ChunkKind::CallParameterClosureExpr)) { - break; - } - if (!C.hasText()) - continue; - OS << C.getText(); - } - - SmallString<32> DisplayString; - SmallString<32> TypeString; - SmallString<32> ExpansionTypeString; - - for (auto i = ParamGroup.begin(), e = ParamGroup.end(); i != e; ++i) { - auto &C = *i; - if (C.is(ChunkKind::CallParameterTypeBegin)) { - assert(TypeString.empty()); - auto nestingLevel = C.getNestingLevel(); - ++i; - for (; i != e; ++i) { - if (i->endsPreviousNestedGroup(nestingLevel)) - break; - if (!i->isAnnotation() && i->hasText()) { - TypeString += i->getText(); - DisplayString += i->getText(); - } - } - --i; - continue; - } - if (C.is(ChunkKind::CallParameterClosureType)) { - assert(ExpansionTypeString.empty()); - ExpansionTypeString = C.getText(); - continue; - } - if (C.is(ChunkKind::CallParameterType)) { - assert(TypeString.empty()); - TypeString = C.getText(); - } - if (C.is(ChunkKind::CallParameterClosureExpr)) { - // We have a closure expression, so provide it directly instead of in - // a placeholder. - OS << "{"; - if (!C.getText().empty()) - OS << " " << C.getText(); - OS << "\n" << getCodePlaceholder() << "\n}"; - return; - } - if (C.isAnnotation() || !C.hasText()) - continue; - DisplayString += C.getText(); - } - - StringRef Display = DisplayString.str(); - StringRef Type = TypeString.str(); - StringRef ExpansionType = ExpansionTypeString.str(); - if (ExpansionType.empty()) - ExpansionType = Type; - - OS << "<#T##" << Display; - if (Display == Type && Display == ExpansionType) { - // Short version, display and type are the same. - } else { - OS << "##" << Type; - if (ExpansionType != Type) - OS << "##" << ExpansionType; - } - OS << "#>"; -} - -void SwiftToSourceKitCompletionAdapter::getResultSourceText( - const CodeCompletionString *CCStr, raw_ostream &OS) { - auto Chunks = CCStr->getChunks(); - for (size_t i = 0; i < Chunks.size(); ++i) { - auto &C = Chunks[i]; - if (C.is(ChunkKind::BraceStmtWithCursor)) { - OS << " {\n" << getCodePlaceholder() << "\n}"; - continue; - } - if (C.is(ChunkKind::CallParameterBegin)) { - size_t Start = i++; - for (; i < Chunks.size(); ++i) { - if (Chunks[i].endsPreviousNestedGroup(C.getNestingLevel())) - break; - } - constructTextForCallParam(Chunks.slice(Start, i-Start), OS); - --i; - continue; - } - if (C.is(ChunkKind::TypeAnnotationBegin)) { - // Skip type annotation structure. - auto level = C.getNestingLevel(); - do { ++i; } while (i != Chunks.size() && !Chunks[i].endsPreviousNestedGroup(level)); - --i; - } - if (!C.isAnnotation() && C.hasText()) { - OS << C.getText(); - } - } -} - void SwiftToSourceKitCompletionAdapter::getResultAssociatedUSRs( ArrayRef AssocUSRs, raw_ostream &OS) { bool First = true; @@ -1005,8 +886,7 @@ filterInnerResults(ArrayRef results, bool includeInner, llvm::SmallString<64> filterName; { llvm::raw_svector_ostream OSS(filterName); - CodeCompletion::CompletionBuilder::getFilterName( - result->getCompletionString(), OSS); + ide::printCodeCompletionResultFilterName(*result, OSS); } llvm::SmallString<64> description; { @@ -1140,8 +1020,7 @@ static void transformAndForwardResults( std::string str = inputBuf->getBuffer().slice(0, offset).str(); { llvm::raw_string_ostream OSS(str); - SwiftToSourceKitCompletionAdapter::getResultSourceText( - exactMatch->getCompletionString(), OSS); + ide::printCodeCompletionResultSourceText(*exactMatch, OSS); } auto buffer = diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp index 6b0fe110a774c..d77474f197d5c 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp @@ -1601,9 +1601,6 @@ class PlaceholderExpansionScanner { if (auto *CE = dyn_cast(E)) { // Call expression can have argument. Arg = CE->getArg(); - } else if (auto UME = dyn_cast(E)) { - // Unresolved member can have argument too. - Arg = UME->getArgument(); } if (!Arg) return false; diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp index ff189f773ab28..9ab571c111982 100644 --- a/tools/driver/driver.cpp +++ b/tools/driver/driver.cpp @@ -140,14 +140,15 @@ static int run_driver(StringRef ExecName, argv.data()+argv.size()), argv[0], (void *)(intptr_t)getExecutablePath); } - } - // Run the integrated Swift frontend when called as "swift-frontend" but - // without a leading "-frontend". - if (ExecName == "swift-frontend") { - return performFrontend(llvm::makeArrayRef(argv.data()+1, - argv.data()+argv.size()), - argv[0], (void *)(intptr_t)getExecutablePath); + // Run the integrated Swift frontend when called as "swift-frontend" but + // without a leading "-frontend". + if (!FirstArg.startswith("--driver-mode=") + && ExecName == "swift-frontend") { + return performFrontend(llvm::makeArrayRef(argv.data()+1, + argv.data()+argv.size()), + argv[0], (void *)(intptr_t)getExecutablePath); + } } std::string Path = getExecutablePath(argv[0]); diff --git a/tools/swift-api-digester/ModuleAnalyzerNodes.cpp b/tools/swift-api-digester/ModuleAnalyzerNodes.cpp index 9e91584e84659..813a7bd843097 100644 --- a/tools/swift-api-digester/ModuleAnalyzerNodes.cpp +++ b/tools/swift-api-digester/ModuleAnalyzerNodes.cpp @@ -1603,6 +1603,11 @@ SDKContext::shouldIgnore(Decl *D, const Decl* Parent) const { if (isa(VD)) return true; } + // Exclude decls with @_alwaysEmitIntoClient if we are checking ABI. + // These decls are considered effectively public because they are usable + // from inline, so we have to manually exclude them here. + if (D->getAttrs().hasAttribute()) + return true; } else { if (D->isPrivateStdlibDecl(false)) return true; diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp index 6e69d0cf36eb8..ed3c61d7623c9 100644 --- a/tools/swift-api-digester/swift-api-digester.cpp +++ b/tools/swift-api-digester/swift-api-digester.cpp @@ -72,7 +72,7 @@ ModuleList("module-list-file", llvm::cl::cat(Category)); static llvm::cl::opt -ProtReqWhiteList("protocol-requirement-white-list", +ProtReqAllowList("protocol-requirement-allow-list", llvm::cl::desc("File containing a new-line separated list of protocol names"), llvm::cl::cat(Category)); @@ -1057,6 +1057,17 @@ void swift::ide::api::SDKNodeTypeFunc::diagnose(SDKNode *Right) { } namespace { +static void diagnoseRemovedDecl(const SDKNodeDecl *D) { + if (D->getSDKContext().checkingABI()) { + // Don't complain about removing @_alwaysEmitIntoClient if we are checking ABI. + // We shouldn't include these decls in the ABI baseline file. This line is + // added so the checker is backward compatible. + if (D->hasDeclAttribute(DeclAttrKind::DAK_AlwaysEmitIntoClient)) + return; + } + D->emitDiag(SourceLoc(), diag::removed_decl, D->isDeprecated()); +} + // This is first pass on two given SDKNode trees. This pass removes the common part // of two versions of SDK, leaving only the changed part. class PrunePass : public MatchedNodeListener, public SDKTreeDiffPass { @@ -1074,7 +1085,7 @@ class PrunePass : public MatchedNodeListener, public SDKTreeDiffPass { SDKContext &Ctx; UpdatedNodesMap &UpdateMap; - llvm::StringSet<> ProtocolReqWhitelist; + llvm::StringSet<> ProtocolReqAllowlist; SDKNodeRoot *LeftRoot; SDKNodeRoot *RightRoot; @@ -1123,10 +1134,10 @@ class PrunePass : public MatchedNodeListener, public SDKTreeDiffPass { public: PrunePass(SDKContext &Ctx): Ctx(Ctx), UpdateMap(Ctx.getNodeUpdateMap()) {} - PrunePass(SDKContext &Ctx, llvm::StringSet<> prWhitelist): + PrunePass(SDKContext &Ctx, llvm::StringSet<> prAllowlist): Ctx(Ctx), UpdateMap(Ctx.getNodeUpdateMap()), - ProtocolReqWhitelist(std::move(prWhitelist)) {} + ProtocolReqAllowlist(std::move(prAllowlist)) {} void diagnoseMissingAvailable(SDKNodeDecl *D) { // For extensions of external types, we diagnose individual member's missing @@ -1178,7 +1189,7 @@ class PrunePass : public MatchedNodeListener, public SDKTreeDiffPass { ShouldComplain = false; } if (ShouldComplain && - ProtocolReqWhitelist.count(getParentProtocolName(D))) { + ProtocolReqAllowlist.count(getParentProtocolName(D))) { // Ignore protocol requirement additions if the protocol has been added // to the allowlist. ShouldComplain = false; @@ -1241,7 +1252,7 @@ class PrunePass : public MatchedNodeListener, public SDKTreeDiffPass { TD->isProtocol()); } if (auto *Acc = dyn_cast(Left)) { - Acc->emitDiag(SourceLoc(), diag::removed_decl, Acc->isDeprecated()); + diagnoseRemovedDecl(Acc); } return; case NodeMatchReason::FuncToProperty: @@ -2084,7 +2095,7 @@ static bool diagnoseRemovedExtensionMembers(const SDKNode *Node) { if (DT->isExtension()) { for (auto *C: DT->getChildren()) { auto *MD = cast(C); - MD->emitDiag(SourceLoc(), diag::removed_decl, MD->isDeprecated()); + diagnoseRemovedDecl(MD); } return true; } @@ -2161,7 +2172,7 @@ void DiagnosisEmitter::handle(const SDKNodeDecl *Node, NodeAnnotation Anno) { } bool handled = diagnoseRemovedExtensionMembers(Node); if (!handled) - Node->emitDiag(SourceLoc(), diag::removed_decl, Node->isDeprecated()); + diagnoseRemovedDecl(Node); return; } case NodeAnnotation::Rename: { @@ -2311,7 +2322,7 @@ createDiagConsumer(llvm::raw_ostream &OS, bool &FailOnError) { static int diagnoseModuleChange(SDKContext &Ctx, SDKNodeRoot *LeftModule, SDKNodeRoot *RightModule, StringRef OutputPath, - llvm::StringSet<> ProtocolReqWhitelist) { + llvm::StringSet<> ProtocolReqAllowlist) { assert(LeftModule); assert(RightModule); llvm::raw_ostream *OS = &llvm::errs(); @@ -2334,7 +2345,7 @@ static int diagnoseModuleChange(SDKContext &Ctx, SDKNodeRoot *LeftModule, RightModule->getJsonFormatVersion())); TypeAliasDiffFinder(LeftModule, RightModule, Ctx.getTypeAliasUpdateMap()).search(); - PrunePass Prune(Ctx, std::move(ProtocolReqWhitelist)); + PrunePass Prune(Ctx, std::move(ProtocolReqAllowlist)); Prune.pass(LeftModule, RightModule); ChangeRefinementPass RefinementPass(Ctx.getNodeUpdateMap()); RefinementPass.pass(LeftModule, RightModule); @@ -2347,7 +2358,7 @@ static int diagnoseModuleChange(SDKContext &Ctx, SDKNodeRoot *LeftModule, static int diagnoseModuleChange(StringRef LeftPath, StringRef RightPath, StringRef OutputPath, CheckerOptions Opts, - llvm::StringSet<> ProtocolReqWhitelist) { + llvm::StringSet<> ProtocolReqAllowlist) { if (!fs::exists(LeftPath)) { llvm::errs() << LeftPath << " does not exist\n"; return 1; @@ -2362,7 +2373,7 @@ static int diagnoseModuleChange(StringRef LeftPath, StringRef RightPath, SwiftDeclCollector RightCollector(Ctx); RightCollector.deSerialize(RightPath); diagnoseModuleChange(Ctx, LeftCollector.getSDKRoot(), RightCollector.getSDKRoot(), - OutputPath, std::move(ProtocolReqWhitelist)); + OutputPath, std::move(ProtocolReqAllowlist)); return options::CompilerStyleDiags && Ctx.getDiags().hadAnyError() ? 1 : 0; } @@ -2548,6 +2559,8 @@ static int prepareForDump(const char *Main, InitInvok.getLangOptions().Target.isOSDarwin(); InitInvok.getClangImporterOptions().ModuleCachePath = options::ModuleCachePath; + // Module recovery issue shouldn't bring down the tool. + InitInvok.getLangOptions().AllowDeserializingImplementationOnly = true; if (!options::SwiftVersion.empty()) { using version::Version; @@ -2835,9 +2848,9 @@ int main(int argc, char *argv[]) { case ActionType::MigratorGen: case ActionType::DiagnoseSDKs: { ComparisonInputMode Mode = checkComparisonInputMode(); - llvm::StringSet<> protocolWhitelist; - if (!options::ProtReqWhiteList.empty()) { - if (readFileLineByLine(options::ProtReqWhiteList, protocolWhitelist)) + llvm::StringSet<> protocolAllowlist; + if (!options::ProtReqAllowList.empty()) { + if (readFileLineByLine(options::ProtReqAllowList, protocolAllowlist)) return 1; } if (options::Action == ActionType::MigratorGen) { @@ -2851,21 +2864,21 @@ int main(int argc, char *argv[]) { return diagnoseModuleChange(options::SDKJsonPaths[0], options::SDKJsonPaths[1], options::OutputFile, Opts, - std::move(protocolWhitelist)); + std::move(protocolAllowlist)); } case ComparisonInputMode::BaselineJson: { SDKContext Ctx(Opts); return diagnoseModuleChange(Ctx, getBaselineFromJson(argv[0], Ctx), getSDKRoot(argv[0], Ctx, false), options::OutputFile, - std::move(protocolWhitelist)); + std::move(protocolAllowlist)); } case ComparisonInputMode::BothLoad: { SDKContext Ctx(Opts); return diagnoseModuleChange(Ctx, getSDKRoot(argv[0], Ctx, true), getSDKRoot(argv[0], Ctx, false), options::OutputFile, - std::move(protocolWhitelist)); + std::move(protocolAllowlist)); } } } diff --git a/tools/swift-inspect/Sources/swift-inspect/Inspector.swift b/tools/swift-inspect/Sources/swift-inspect/Inspector.swift index 80f3668f111b3..05b77192adf68 100644 --- a/tools/swift-inspect/Sources/swift-inspect/Inspector.swift +++ b/tools/swift-inspect/Sources/swift-inspect/Inspector.swift @@ -121,8 +121,10 @@ private func QueryDataLayoutFn(context: UnsafeMutableRawPointer?, type: DataLayoutQueryType, inBuffer: UnsafeMutableRawPointer?, outBuffer: UnsafeMutableRawPointer?) -> CInt { + let is64 = MemoryLayout.stride == 8 + switch type { - case DLQ_GetPointerSize: + case DLQ_GetPointerSize, DLQ_GetSizeSize: let size = UInt8(MemoryLayout.stride) outBuffer!.storeBytes(of: size, toByteOffset: 0, as: UInt8.self) return 1 @@ -130,6 +132,26 @@ private func QueryDataLayoutFn(context: UnsafeMutableRawPointer?, let mask = GetPtrauthMask() outBuffer!.storeBytes(of: mask, toByteOffset: 0, as: UInt.self) return 1 + case DLQ_GetObjCReservedLowBits: + var size: UInt8 = 0 +#if os(macOS) + // The low bit is reserved only on 64-bit macOS. + if is64 { + size = 1 + } +#endif + outBuffer!.storeBytes(of: size, toByteOffset: 0, as: UInt8.self) + return 1 + case DLQ_GetLeastValidPointerValue: + var value: UInt64 = 0x1000 +#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) + // 64-bit Apple platforms reserve the low 4GB. + if is64 { + value = 0x100000000 + } +#endif + outBuffer!.storeBytes(of: value, toByteOffset: 0, as: UInt64.self) + return 1 default: return 0 } diff --git a/tools/swift-reflection-dump/swift-reflection-dump.cpp b/tools/swift-reflection-dump/swift-reflection-dump.cpp index c06ec35de5f81..8846f4452e855 100644 --- a/tools/swift-reflection-dump/swift-reflection-dump.cpp +++ b/tools/swift-reflection-dump/swift-reflection-dump.cpp @@ -668,12 +668,15 @@ static int doDumpReflectionSections(ArrayRef BinaryFilenames, Demangle::Demangler Dem; auto Demangled = Dem.demangleType(Line); - auto *TypeRef = - swift::Demangle::decodeMangledType(builder, Demangled); - if (TypeRef == nullptr) { - fprintf(file, "Invalid typeref:%s\n", Line.c_str()); + auto Result = swift::Demangle::decodeMangledType(builder, Demangled); + if (Result.isError()) { + auto *error = Result.getError(); + char *str = error->copyErrorString(); + fprintf(file, "Invalid typeref:%s - %s\n", Line.c_str(), str); + error->freeErrorString(str); continue; } + auto TypeRef = Result.getType(); TypeRef->dump(file); auto *TypeInfo = builder.getTypeConverter().getTypeInfo(TypeRef); diff --git a/tools/swift-serialize-diagnostics/CMakeLists.txt b/tools/swift-serialize-diagnostics/CMakeLists.txt index 13cf756c13c49..4a1ab49b59ed3 100644 --- a/tools/swift-serialize-diagnostics/CMakeLists.txt +++ b/tools/swift-serialize-diagnostics/CMakeLists.txt @@ -2,6 +2,5 @@ add_swift_host_tool(swift-serialize-diagnostics swift-serialize-diagnostics.cpp SWIFT_COMPONENT tools ) -target_link_libraries(swift-serialize-diagnostics - PRIVATE - swiftAST) +target_link_libraries(swift-serialize-diagnostics PRIVATE + swiftLocalization) diff --git a/tools/swift-serialize-diagnostics/swift-serialize-diagnostics.cpp b/tools/swift-serialize-diagnostics/swift-serialize-diagnostics.cpp index 01ea696002637..03b0118f2eef4 100644 --- a/tools/swift-serialize-diagnostics/swift-serialize-diagnostics.cpp +++ b/tools/swift-serialize-diagnostics/swift-serialize-diagnostics.cpp @@ -14,9 +14,9 @@ // //===----------------------------------------------------------------------===// -#include "swift/AST/LocalizationFormat.h" #include "swift/Basic/LLVMInitialize.h" #include "swift/Basic/STLExtras.h" +#include "swift/Localization/LocalizationFormat.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" diff --git a/tools/swift-syntax-test/swift-syntax-test.cpp b/tools/swift-syntax-test/swift-syntax-test.cpp index 7edcaae19779c..c492162111927 100644 --- a/tools/swift-syntax-test/swift-syntax-test.cpp +++ b/tools/swift-syntax-test/swift-syntax-test.cpp @@ -610,7 +610,6 @@ int parseFile( Invocation.getLangOptions().VerifySyntaxTree = options::VerifySyntaxTree; Invocation.getLangOptions().RequestEvaluatorGraphVizPath = options::GraphVisPath; Invocation.getLangOptions().DisablePoundIfEvaluation = true; - Invocation.getLangOptions().EnableExperimentalConcurrency = true; Invocation.getFrontendOptions().InputsAndOutputs.addInputFile(InputFileName); diff --git a/unittests/ClangImporter/ClangImporterTests.cpp b/unittests/ClangImporter/ClangImporterTests.cpp index e353fba57745f..4068678fd8433 100644 --- a/unittests/ClangImporter/ClangImporterTests.cpp +++ b/unittests/ClangImporter/ClangImporterTests.cpp @@ -6,6 +6,10 @@ #include "swift/Basic/SourceManager.h" #include "swift/ClangImporter/ClangImporter.h" #include "swift/ClangImporter/ClangImporterOptions.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/FileSystemOptions.h" +#include "clang/Basic/FileSystemStatCache.h" +#include "clang/Frontend/CompilerInstance.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -54,7 +58,6 @@ TEST(ClangImporterTest, emitPCHInMemory) { // Create the includes. std::string include = createFilename(temp, "include"); ASSERT_FALSE(llvm::sys::fs::create_directory(include)); - options.ExtraArgs.emplace_back("-nosysteminc"); options.ExtraArgs.emplace_back((llvm::Twine("-I") + include).str()); ASSERT_FALSE(emitFileWithContents(include, "module.modulemap", "module A {\n" @@ -88,3 +91,105 @@ TEST(ClangImporterTest, emitPCHInMemory) { ASSERT_FALSE(emitFileWithContents(PCH, "garbage")); ASSERT_TRUE(importer->canReadPCH(PCH)); } + +class ForgetfulStatCache : public clang::FileSystemStatCache { +private: + std::unique_ptr RealStatCache; + +public: + ForgetfulStatCache() { + RealStatCache = std::make_unique(); + } + ~ForgetfulStatCache() = default; + + std::error_code getStat(StringRef Path, llvm::vfs::Status &Status, + bool isFile, + std::unique_ptr *F, + llvm::vfs::FileSystem &FS) override { + if (llvm::sys::path::extension(Path) == ".pcm") { + const auto UID = llvm::sys::fs::UniqueID(1, std::numeric_limits::max()); + Status = llvm::vfs::Status(Path, UID, + /*MTime*/{}, /*User*/0, /*Group*/0, + /*Size*/0, + llvm::sys::fs::file_type::regular_file, + llvm::sys::fs::perms::all_all); + return std::error_code(); + } + + return clang::FileSystemStatCache::get(Path, Status, isFile, F, + RealStatCache.get(), FS); + } +}; + +TEST(ClangImporterTest, missingSubmodule) { + // Create a temporary cache on disk and clean it up at the end. + ClangImporterOptions options; + SmallString<256> temp; + ASSERT_FALSE(llvm::sys::fs::createUniqueDirectory( + "ClangImporterTest.missingSubmodule", temp)); + SWIFT_DEFER { llvm::sys::fs::remove_directories(temp); }; + + // Create a cache subdirectory for the modules and PCH. + std::string cache = createFilename(temp, "cache"); + ASSERT_FALSE(llvm::sys::fs::create_directory(cache)); + options.ModuleCachePath = cache; + options.PrecompiledHeaderOutputDir = cache; + + // Create the includes. + std::string include1 = createFilename(temp, "include1"); + ASSERT_FALSE(llvm::sys::fs::create_directory(include1)); + + std::string include2 = createFilename(temp, "include2"); + ASSERT_FALSE(llvm::sys::fs::create_directory(include2)); + + options.ExtraArgs.emplace_back((llvm::Twine("-I") + include1).str()); + options.ExtraArgs.emplace_back((llvm::Twine("-I") + include2).str()); + options.ExtraArgs.emplace_back("-DEXTRA_C_DEFINE=2"); + + ASSERT_FALSE(emitFileWithContents(include1, "module.modulemap", + "module CLib1 {\n" + " umbrella header \"" + include1 + "/Clib1.h\"\n" + " export * \n" + "}\n" + "module CLib2 {\n" + " umbrella header \"" + include2 + "/Clib2.h\"\n" + " export * \n" + "}\n")); + ASSERT_FALSE(emitFileWithContents(include1, "CLib1.h", + "#if !defined(EXTRA_C_DEFINE) || EXTRA_C_DEFINE != 2\n" + "#error \"unexpected compiler flags\"\n" + "#endif\n" + "void foo(void);\n")); + ASSERT_FALSE(emitFileWithContents(include2, "CLib2.h", + "#if !defined(EXTRA_C_DEFINE) || EXTRA_C_DEFINE != 2\n" + "#error \"unexpected compiler flags\"\n" + "#endif\n" + "void foo(void);\n")); + + // Set up the importer. + swift::LangOptions langOpts; + langOpts.Target = llvm::Triple("x86_64", "apple", "darwin"); + swift::TypeCheckerOptions typeckOpts; + INITIALIZE_LLVM(); + swift::SearchPathOptions searchPathOpts; + swift::SourceManager sourceMgr; + swift::DiagnosticEngine diags(sourceMgr); + std::unique_ptr context( + ASTContext::get(langOpts, typeckOpts, searchPathOpts, sourceMgr, diags)); + auto importer = ClangImporter::create(*context, options); + + // Install a stats cache that conveniently "forgets" that PCMs have different + // underlying FileEntry values. + importer->getClangInstance() + .getFileManager() + .setStatCache(std::make_unique()); + + context->addModuleLoader(std::move(importer)); + + auto CLib1 = context->getIdentifier("CLib1"); + auto CLib2 = context->getIdentifier("CLib2"); + // The first load succeeds and primes the ModuleManager with PCM data. + (void)context->getModule({ Located{ CLib1, {} } }); + // The second load fails because we collide in the ModuleManager. + ASSERT_TRUE(context->getModule({ Located{ CLib2, {} } }) == nullptr); +} diff --git a/unittests/FrontendTool/ModuleLoadingTests.cpp b/unittests/FrontendTool/ModuleLoadingTests.cpp index 7e343aaeeeab1..7185ffed81ded 100644 --- a/unittests/FrontendTool/ModuleLoadingTests.cpp +++ b/unittests/FrontendTool/ModuleLoadingTests.cpp @@ -116,7 +116,7 @@ class ModuleInterfaceLoaderTest : public testing::Test { loader->findModuleFilesInDirectory({moduleName, SourceLoc()}, SerializedModuleBaseName(tempDir, SerializedModuleBaseName("Library")), /*ModuleInterfacePath*/nullptr, - &moduleBuffer, &moduleDocBuffer, &moduleSourceInfoBuffer); + &moduleBuffer, &moduleDocBuffer, &moduleSourceInfoBuffer, /*IsFramework*/false); ASSERT_FALSE(error); ASSERT_FALSE(diags.hadAnyError()); diff --git a/unittests/IDE/CMakeLists.txt b/unittests/IDE/CMakeLists.txt index f55846dd2c6ad..607a574214a71 100644 --- a/unittests/IDE/CMakeLists.txt +++ b/unittests/IDE/CMakeLists.txt @@ -1,5 +1,6 @@ add_swift_unittest(SwiftIDETests CodeCompletionToken.cpp + FuzzyStringMatcherTest.cpp Placeholders.cpp ) target_link_libraries(SwiftIDETests diff --git a/unittests/SourceKit/Support/FuzzyStringMatcherTest.cpp b/unittests/IDE/FuzzyStringMatcherTest.cpp similarity index 99% rename from unittests/SourceKit/Support/FuzzyStringMatcherTest.cpp rename to unittests/IDE/FuzzyStringMatcherTest.cpp index e0e7e83b4220c..e190933fcd988 100644 --- a/unittests/SourceKit/Support/FuzzyStringMatcherTest.cpp +++ b/unittests/IDE/FuzzyStringMatcherTest.cpp @@ -10,10 +10,10 @@ // //===----------------------------------------------------------------------===// -#include "SourceKit/Support/FuzzyStringMatcher.h" +#include "swift/IDE/FuzzyStringMatcher.h" #include "gtest/gtest.h" -using FuzzyStringMatcher = SourceKit::FuzzyStringMatcher; +using FuzzyStringMatcher = swift::ide::FuzzyStringMatcher; TEST(FuzzyStringMatcher, BasicMatching) { { diff --git a/unittests/SourceKit/Support/CMakeLists.txt b/unittests/SourceKit/Support/CMakeLists.txt index da17a059b87b3..54cbdce081c87 100644 --- a/unittests/SourceKit/Support/CMakeLists.txt +++ b/unittests/SourceKit/Support/CMakeLists.txt @@ -1,5 +1,4 @@ add_swift_unittest(SourceKitSupportTests - FuzzyStringMatcherTest.cpp ImmutableTextBufferTest.cpp ) diff --git a/unittests/runtime/CompatibilityOverride.cpp b/unittests/runtime/CompatibilityOverride.cpp index 2dece35195619..6056f26117930 100644 --- a/unittests/runtime/CompatibilityOverride.cpp +++ b/unittests/runtime/CompatibilityOverride.cpp @@ -35,8 +35,8 @@ namespace { return MetadataResponse{nullptr, MetadataState::Complete}; } - template<> - TypeInfo getEmptyValue() { + template <> + TypeLookupErrorOr getEmptyValue>() { return TypeInfo(); } } @@ -168,22 +168,17 @@ TEST_F(CompatibilityOverrideTest, test_swift_conformsToProtocol) { ASSERT_EQ(Result, nullptr); } -TEST_F(CompatibilityOverrideTest, test_swift_conformsToSwiftProtocol) { - auto Result = swift_conformsToSwiftProtocol(nullptr, nullptr, StringRef()); - ASSERT_EQ(Result, nullptr); -} - TEST_F(CompatibilityOverrideTest, test_swift_getTypeByMangledNode) { Demangler demangler; auto Result = swift_getTypeByMangledNode(MetadataState::Abstract, demangler, nullptr, nullptr, nullptr,nullptr); - ASSERT_EQ(Result.getMetadata(), nullptr); + ASSERT_EQ(Result.getType().getMetadata(), nullptr); } TEST_F(CompatibilityOverrideTest, test_swift_getTypeByMangledName) { auto Result = swift_getTypeByMangledName(MetadataState::Abstract, "", nullptr, nullptr, nullptr); - ASSERT_EQ(Result.getMetadata(), nullptr); + ASSERT_EQ(Result.getType().getMetadata(), nullptr); } TEST_F(CompatibilityOverrideTest, test_swift_getAssociatedTypeWitnessSlow) { diff --git a/unittests/runtime/Concurrent.cpp b/unittests/runtime/Concurrent.cpp index 3f78805c53ff7..141b804f099d4 100644 --- a/unittests/runtime/Concurrent.cpp +++ b/unittests/runtime/Concurrent.cpp @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information @@ -13,6 +13,8 @@ #include "swift/Runtime/Concurrent.h" #include "gtest/gtest.h" +#include "ThreadingHelpers.h" + using namespace swift; TEST(ConcurrentReadableArrayTest, SingleThreaded) { @@ -42,3 +44,458 @@ TEST(ConcurrentReadableArrayTest, SingleThreaded) { add(1000000); check(); } + +TEST(ConcurrentReadableArrayTest, MultiThreaded) { + const int writerCount = 16; + const int readerCount = 8; + const int insertCount = 100000; + + struct Value { + int threadNumber; + int x; + }; + ConcurrentReadableArray array; + + // The writers will append values with their thread number and increasing + // values of x. + auto writer = [&](int threadNumber) { + for (int i = 0; i < insertCount; i++) + array.push_back({ threadNumber, i }); + }; + + auto reader = [&] { + // Track the maximum value we've seen for each writer thread. + int maxByThread[writerCount]; + bool done = false; + while (!done) { + for (int i = 0; i < writerCount; i++) + maxByThread[i] = -1; + for (auto element : array.snapshot()) { + ASSERT_LT(element.threadNumber, writerCount); + // Each element we see must be larger than the maximum element we've + // previously seen for that writer thread, otherwise that means that + // we're seeing mutations out of order. + ASSERT_GT(element.x, maxByThread[element.threadNumber]); + maxByThread[element.threadNumber] = element.x; + } + + // If the max for each thread is the max that'll be inserted, then we're + // done and should exit. + done = true; + for (int i = 0; i < writerCount; i++) { + if (maxByThread[i] < insertCount - 1) + done = false; + } + } + }; + + threadedExecute(writerCount + readerCount, [&](int i) { + if (i < writerCount) + writer(i); + else + reader(); + }); + + ASSERT_EQ(array.snapshot().count(), (size_t)writerCount * insertCount); +} + +TEST(ConcurrentReadableArrayTest, MultiThreaded2) { + const int writerCount = 16; + const int readerCount = 8; + const int insertCount = 100000; + + struct Value { + int threadNumber; + int x; + }; + ConcurrentReadableArray array; + + // The writers will append values with their thread number and increasing + // values of x. + auto writer = [&](int threadNumber) { + for (int i = 0; i < insertCount; i++) + array.push_back({ threadNumber, i }); + }; + + auto reader = [&] { + // Track the maximum value we've seen for each writer thread. + int maxByThread[writerCount]; + for (int i = 0; i < writerCount; i++) + maxByThread[i] = -1; + bool done = false; + while (!done) { + auto snapshot = array.snapshot(); + // Don't do anything until some data is actually added. + if (snapshot.count() == 0) + continue; + + // Grab the last element in the snapshot. + auto element = snapshot.begin()[snapshot.count() - 1]; + ASSERT_LT(element.threadNumber, writerCount); + // Each element we see must be equal to or larger than the maximum element + // we've previously seen for that writer thread, otherwise that means that + // we're seeing mutations out of order. + ASSERT_GE(element.x, maxByThread[element.threadNumber]); + maxByThread[element.threadNumber] = element.x; + + // We'll eventually see some thread add its maximum value. We'll call it + // done when we reach that point. + if (element.x == insertCount - 1) + done = true; + } + }; + + threadedExecute(writerCount + readerCount, [&](int i) { + if (i < writerCount) + writer(i); + else + reader(); + }); + + ASSERT_EQ(array.snapshot().count(), (size_t)writerCount * insertCount); +} + +struct SingleThreadedValue { + size_t key; + size_t x; + SingleThreadedValue(size_t key, size_t x) : key(key), x(x) {} + bool matchesKey(size_t key) { return this->key == key; } + friend llvm::hash_code hash_value(const SingleThreadedValue &value) { + return llvm::hash_value(value.key); + } +}; + +TEST(ConcurrentReadableHashMapTest, SingleThreaded) { + ConcurrentReadableHashMap map; + + auto permute = [](size_t value) { return value ^ 0x33333333U; }; + + auto add = [&](size_t limit) { + for (size_t i = 0; i < limit; i++) + map.getOrInsert(permute(i), + [&](SingleThreadedValue *value, bool created) { + if (created) + new (value) SingleThreadedValue(permute(i), i); + return true; + }); + }; + auto check = [&](size_t limit) { + auto snapshot = map.snapshot(); + ASSERT_EQ(snapshot.find((size_t)~0), nullptr); + for (size_t i = 0; i < limit; i++) { + auto *value = snapshot.find(permute(i)); + ASSERT_NE(value, nullptr); + ASSERT_EQ(permute(i), value->key); + ASSERT_EQ(i, value->x); + } + }; + + check(0); + add(1); + check(1); + add(16); + check(16); + add(100); + check(100); + add(1000); + check(1000); + add(1000000); + check(1000000); + + map.clear(); + check(0); + + add(1); + check(1); + map.clear(); + check(0); + + add(16); + check(16); + map.clear(); + check(0); + + add(100); + check(100); + map.clear(); + check(0); + + add(1000); + check(1000); + map.clear(); + check(0); + + add(1000000); + check(1000000); + map.clear(); + check(0); +} + +struct MultiThreadedKey { + int threadNumber; + int n; + friend llvm::hash_code hash_value(const MultiThreadedKey &value) { + return llvm::hash_combine(value.threadNumber, value.n); + } +}; + +struct MultiThreadedValue { + int threadNumber; + int n; + int x; + MultiThreadedValue(MultiThreadedKey key, int x) + : threadNumber(key.threadNumber), n(key.n), x(x) {} + bool matchesKey(const MultiThreadedKey &key) { + return threadNumber == key.threadNumber && n == key.n; + } + friend llvm::hash_code hash_value(const MultiThreadedValue &value) { + return llvm::hash_combine(value.threadNumber, value.n); + } +}; + +// Test simultaneous readers and writers. +TEST(ConcurrentReadableHashMapTest, MultiThreaded) { + const int writerCount = 16; + const int readerCount = 8; + const int insertCount = 10000; + + ConcurrentReadableHashMap map; + + // NOTE: The bizarre lambdas around the ASSERT_ statements works around the + // fact that these macros emit return statements, which conflict with our + // need to return true/false from these lambdas. Wrapping them in a lambda + // neutralizes the return. + + auto writer = [&](int threadNumber) { + // Insert half, then insert all, to test adding an existing key. + for (int i = 0; i < insertCount / 2; i++) + map.getOrInsert(MultiThreadedKey{threadNumber, i}, [&](MultiThreadedValue + *value, + bool created) { + [&] { ASSERT_TRUE(created); }(); + new (value) MultiThreadedValue(MultiThreadedKey{threadNumber, i}, i); + return true; + }); + // Test discarding a new entry. + for (int i = 0; i < insertCount; i++) + map.getOrInsert(MultiThreadedKey{threadNumber, i}, + [&](MultiThreadedValue *value, bool created) { + [&] { ASSERT_EQ(created, i >= insertCount / 2); }(); + return false; + }); + for (int i = 0; i < insertCount; i++) + map.getOrInsert(MultiThreadedKey{threadNumber, i}, [&](MultiThreadedValue + *value, + bool created) { + if (created) { + [&] { ASSERT_GE(i, insertCount / 2); }(); + new (value) MultiThreadedValue(MultiThreadedKey{threadNumber, i}, i); + } else { + [&] { ASSERT_LT(i, insertCount / 2); }(); + } + return true; + }); + }; + + auto reader = [&] { + bool done = false; + while (!done) { + done = true; + for (int threadNumber = 0; threadNumber < writerCount; threadNumber++) { + // Read from the top down. We should see zero or more missing entries, + // and then the rest are present. Any hole is a bug. + int firstSeen = -1; + auto snapshot = map.snapshot(); + for (int i = insertCount - 1; i >= 0; i--) { + MultiThreadedKey key = {threadNumber, i}; + const MultiThreadedValue *value = snapshot.find(key); + if (value) { + if (firstSeen == -1) + firstSeen = value->x; + ASSERT_EQ(value->x, i); + } else { + ASSERT_EQ(firstSeen, -1); + done = false; + } + } + } + } + }; + + threadedExecute(writerCount + readerCount, [&](int i) { + if (i < writerCount) + writer(i); + else + reader(); + }); +} + +// Test readers and writers while also constantly clearing the map. +TEST(ConcurrentReadableHashMapTest, MultiThreaded2) { + const int writerCount = 16; + const int readerCount = 8; + const int insertCount = 10000; + + ConcurrentReadableHashMap map; + + std::atomic writerDoneCount = {0}; + auto writer = [&](int threadNumber) { + for (int i = 0; i < insertCount; i++) + map.getOrInsert(MultiThreadedKey{threadNumber, i}, [&](MultiThreadedValue + *value, + bool created) { + [&] { ASSERT_TRUE(created); }(); + new (value) MultiThreadedValue(MultiThreadedKey{threadNumber, i}, i); + return true; + }); + writerDoneCount.fetch_add(1, std::memory_order_relaxed); + }; + + auto reader = [&] { + while (writerDoneCount.load(std::memory_order_relaxed) < writerCount) { + for (int threadNumber = 0; threadNumber < writerCount; threadNumber++) { + // Read from the top down. We should see a single contiguous region of + // entries. Multiple regions indicates a bug. + int firstSeen = -1; + int lastSeen = -1; + auto snapshot = map.snapshot(); + for (int i = insertCount - 1; i >= 0; i--) { + MultiThreadedKey key = {threadNumber, i}; + const MultiThreadedValue *value = snapshot.find(key); + if (value) { + if (firstSeen == -1) + firstSeen = value->x; + if (lastSeen != -1) + ASSERT_EQ(lastSeen, i + 1); + lastSeen = value->x; + ASSERT_EQ(value->x, i); + } + } + } + } + }; + + auto clear = [&] { + while (writerDoneCount.load(std::memory_order_relaxed) < writerCount) { + map.clear(); + } + }; + + threadedExecute(writerCount + readerCount + 1, [&](int i) { + if (i < writerCount) + writer(i); + else if (i < writerCount + readerCount) + reader(); + else + clear(); + }); +} + +// Test readers and writers, with readers taking lots of snapshots. +TEST(ConcurrentReadableHashMapTest, MultiThreaded3) { + const int writerCount = 16; + const int readerCount = 8; + const int insertCount = 10000; + + ConcurrentReadableHashMap map; + + std::atomic writerDoneCount = {0}; + auto writer = [&](int threadNumber) { + for (int i = 0; i < insertCount; i++) + map.getOrInsert(MultiThreadedKey{threadNumber, i}, [&](MultiThreadedValue + *value, + bool created) { + [&] { ASSERT_TRUE(created); }(); + new (value) MultiThreadedValue(MultiThreadedKey{threadNumber, i}, i); + return true; + }); + writerDoneCount.fetch_add(1, std::memory_order_relaxed); + }; + + auto reader = [&] { + while (writerDoneCount.load(std::memory_order_relaxed) < writerCount) { + for (int threadNumber = 0; threadNumber < writerCount; threadNumber++) { + // Read from the top down. When we're not clearing the map, we should + // see zero or more missing entries, and then the rest are present. Any + // hole is a bug. + int firstSeen = -1; + int lastSeen = -1; + for (int i = insertCount - 1; i >= 0; i--) { + auto snapshot = map.snapshot(); + MultiThreadedKey key = {threadNumber, i}; + const MultiThreadedValue *value = snapshot.find(key); + if (value) { + if (firstSeen == -1) + firstSeen = value->x; + if (lastSeen != -1) + ASSERT_EQ(lastSeen, i + 1); + lastSeen = value->x; + ASSERT_EQ(value->x, i); + } + } + } + } + }; + + threadedExecute(writerCount + readerCount, [&](int i) { + if (i < writerCount) + writer(i); + else + reader(); + }); +} + +// Test readers and writers, with readers taking lots of snapshots, and +// simultaneous clearing. +TEST(ConcurrentReadableHashMapTest, MultiThreaded4) { + const int writerCount = 16; + const int readerCount = 8; + const int insertCount = 10000; + + ConcurrentReadableHashMap map; + + std::atomic writerDoneCount = {0}; + auto writer = [&](int threadNumber) { + for (int i = 0; i < insertCount; i++) + map.getOrInsert(MultiThreadedKey{threadNumber, i}, [&](MultiThreadedValue + *value, + bool created) { + [&] { ASSERT_TRUE(created); }(); + new (value) MultiThreadedValue(MultiThreadedKey{threadNumber, i}, i); + return true; + }); + writerDoneCount.fetch_add(1, std::memory_order_relaxed); + }; + + auto reader = [&] { + while (writerDoneCount.load(std::memory_order_relaxed) < writerCount) { + for (int threadNumber = 0; threadNumber < writerCount; threadNumber++) { + // With clearing, we can't expect any particular pattern. Just validate + // the values we do see, and make sure we don't crash. + for (int i = insertCount - 1; i >= 0; i--) { + auto snapshot = map.snapshot(); + MultiThreadedKey key = {threadNumber, i}; + const MultiThreadedValue *value = snapshot.find(key); + if (value) { + ASSERT_EQ(value->x, i); + } + } + } + } + }; + + auto clear = [&] { + while (writerDoneCount.load(std::memory_order_relaxed) < writerCount) { + map.clear(); + } + }; + + threadedExecute(writerCount + readerCount + 1, [&](int i) { + if (i < writerCount) + writer(i); + else if (i < writerCount + readerCount) + reader(); + else + clear(); + }); +} diff --git a/unittests/runtime/Mutex.cpp b/unittests/runtime/Mutex.cpp index 7d5dac159b923..eb634d5346449 100644 --- a/unittests/runtime/Mutex.cpp +++ b/unittests/runtime/Mutex.cpp @@ -16,125 +16,10 @@ #include #include #include -#include -using namespace swift; - -// When true many of the threaded tests log activity to help triage issues. -static bool trace = false; - -template -void threadedExecute(int threadCount, ThreadBody threadBody, - AfterSpinRelease afterSpinRelease) { - - std::vector threads; - - // Block the threads we are about to create. - std::atomic spinWait(true); - std::atomic readyCount(0); - std::atomic activeCount(0); - - for (int i = 0; i < threadCount; ++i) { - threads.push_back(std::thread([&, i] { - readyCount++; - - while (spinWait) { - std::this_thread::sleep_for(std::chrono::microseconds(10)); - } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - - activeCount++; - - threadBody(i); - })); - } - - while (readyCount < threadCount) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - - // Allow our threads to fight for the lock. - spinWait = false; - - while (activeCount < threadCount) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - - afterSpinRelease(); - - // Wait until all of our threads have finished. - for (auto &thread : threads) { - thread.join(); - } -} - -template -void threadedExecute(int threadCount, ThreadBody threadBody) { - threadedExecute(threadCount, threadBody, [] {}); -} - -template -void threadedExecute(M &mutex, C &condition, bool &doneCondition, - ConsumerBody consumerBody, ProducerBody producerBody) { - - std::vector producers; - std::vector consumers; +#include "ThreadingHelpers.h" - // Block the threads we are about to create. - std::atomic spinWait(true); - - for (int i = 1; i <= 8; ++i) { - consumers.push_back(std::thread([&, i] { - while (spinWait) { - std::this_thread::sleep_for(std::chrono::microseconds(10)); - } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - - consumerBody(i); - - if (trace) - printf("### Consumer[%d] thread exiting.\n", i); - })); - } - - for (int i = 1; i <= 5; ++i) { - producers.push_back(std::thread([&, i] { - while (spinWait) { - std::this_thread::sleep_for(std::chrono::microseconds(10)); - } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - - producerBody(i); - - if (trace) - printf("### Producer[%d] thread exiting.\n", i); - })); - } - - // Poor mans attempt to get as many threads ready as possible before - // dropping spinWait, it doesn't have to be perfect. - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - - // Allow our threads to fight for the lock. - spinWait = false; - - // Wait until all of our producer threads have finished. - for (auto &thread : producers) { - thread.join(); - } - - // Inform consumers that producers are done. - mutex.withLockThenNotifyAll(condition, [&] { - if (trace) - printf("### Informing consumers we are done.\n"); - doneCondition = true; - }); - - // Wait for consumers to finish. - for (auto &thread : consumers) { - thread.join(); - } -} +using namespace swift; // ----------------------------------------------------------------------------- diff --git a/unittests/runtime/ThreadingHelpers.h b/unittests/runtime/ThreadingHelpers.h new file mode 100644 index 0000000000000..667c847959744 --- /dev/null +++ b/unittests/runtime/ThreadingHelpers.h @@ -0,0 +1,134 @@ +//===--- Concurrent.cpp - Concurrent data structure tests -----------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#ifndef THREADING_HELPERS_H +#define THREADING_HELPERS_H + +#include + +// When true many of the threaded tests log activity to help triage issues. +static bool trace = false; + +template +void threadedExecute(int threadCount, ThreadBody threadBody, + AfterSpinRelease afterSpinRelease) { + + std::vector threads; + + // Block the threads we are about to create. + std::atomic spinWait(true); + std::atomic readyCount(0); + std::atomic activeCount(0); + + for (int i = 0; i < threadCount; ++i) { + threads.push_back(std::thread([&, i] { + readyCount++; + + while (spinWait) { + std::this_thread::sleep_for(std::chrono::microseconds(10)); + } + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + + activeCount++; + + threadBody(i); + })); + } + + while (readyCount < threadCount) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + + // Allow our threads to fight for the lock. + spinWait = false; + + while (activeCount < threadCount) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + + afterSpinRelease(); + + // Wait until all of our threads have finished. + for (auto &thread : threads) { + thread.join(); + } +} + +template +void threadedExecute(int threadCount, ThreadBody threadBody) { + threadedExecute(threadCount, threadBody, [] {}); +} + +template +void threadedExecute(M &mutex, C &condition, bool &doneCondition, + ConsumerBody consumerBody, ProducerBody producerBody) { + + std::vector producers; + std::vector consumers; + + // Block the threads we are about to create. + std::atomic spinWait(true); + + for (int i = 1; i <= 8; ++i) { + consumers.push_back(std::thread([&, i] { + while (spinWait) { + std::this_thread::sleep_for(std::chrono::microseconds(10)); + } + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + + consumerBody(i); + + if (trace) + printf("### Consumer[%d] thread exiting.\n", i); + })); + } + + for (int i = 1; i <= 5; ++i) { + producers.push_back(std::thread([&, i] { + while (spinWait) { + std::this_thread::sleep_for(std::chrono::microseconds(10)); + } + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + + producerBody(i); + + if (trace) + printf("### Producer[%d] thread exiting.\n", i); + })); + } + + // Poor mans attempt to get as many threads ready as possible before + // dropping spinWait, it doesn't have to be perfect. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // Allow our threads to fight for the lock. + spinWait = false; + + // Wait until all of our producer threads have finished. + for (auto &thread : producers) { + thread.join(); + } + + // Inform consumers that producers are done. + mutex.withLockThenNotifyAll(condition, [&] { + if (trace) + printf("### Informing consumers we are done.\n"); + doneCondition = true; + }); + + // Wait for consumers to finish. + for (auto &thread : consumers) { + thread.join(); + } +} + +#endif diff --git a/utils/api_checker/dump-sdk.sh b/utils/api_checker/dump-sdk.sh new file mode 100755 index 0000000000000..5757eb23bdad4 --- /dev/null +++ b/utils/api_checker/dump-sdk.sh @@ -0,0 +1,65 @@ +#!/bin/bash +set -e + +DIR="$( cd "$( dirname "$0" )" && pwd )" +sh "$DIR/sdk-module-lists/create-module-lists.sh" + +MacSDKPath=$(xcrun -sdk macosx -show-sdk-path) +IphoneOSSDKPath=$(xcrun -sdk iphoneos -show-sdk-path) +AppleTVOSSDKPath=$(xcrun -sdk appletvos -show-sdk-path) +WathOSSDKPath=$(xcrun -sdk watchos -show-sdk-path) + +XCTestMac="$MacSDKPath/../../Library/Frameworks/" +XCTestIphone="$IphoneOSSDKPath/../../Library/Frameworks/" +XCTestTV="$AppleTVOSSDKPath/../../Library/Frameworks/" + +BASEDIR="$DIR/../../swift-sdk-digests/" + +mkdir -p "${BASEDIR}" + +DumpDir="/tmp/SDKDump" +rm -rf "/tmp/SDKDump" +mkdir "/tmp/SDKDump" + +XCODE_VER=$(xcodebuild -version | sed '1d' | sed 's/Build version //g') + +SWIFT_VER=${SWIFT_VER-3} +echo "SWIFT VERSION: ${SWIFT_VER}" + +function sdk_info() { + echo "Xcode Build: $XCODE_VER" + echo "macOS SDK Build: $(xcodebuild -version -sdk macosx ProductBuildVersion)" + echo "iOS SDK Build: $(xcodebuild -version -sdk iphoneos ProductBuildVersion)" + echo "watchOS SDK Build: $(xcodebuild -version -sdk watchos ProductBuildVersion)" + echo "tvOS SDK Build: $(xcodebuild -version -sdk appletvos ProductBuildVersion)" +} + +sdk_info + +XCODE_VER=-base-$SWIFT_VER + +if [[ -z "$MODULE" ]]; then + $SWIFT_API_DIGESTER -target x86_64-apple-macosx10.15 -o "$BASEDIR/macos$XCODE_VER.json" -dump-sdk -sdk "$MacSDKPath" -module-list-file "/tmp/modules-osx.txt" -F "$XCTestMac" -module-cache-path "$DumpDir/ModuleCache" -swift-version $SWIFT_VER + $SWIFT_API_DIGESTER -target arm64-apple-ios13.5 -o "$BASEDIR/ios$XCODE_VER.json" -dump-sdk -sdk "$IphoneOSSDKPath" -module-list-file "/tmp/modules-iphoneos.txt" -F "$XCTestIphone" -module-cache-path "$DumpDir/ModuleCache" -swift-version $SWIFT_VER + $SWIFT_API_DIGESTER -target arm64-apple-tvos13.4 -o "$BASEDIR/tvos$XCODE_VER.json" -dump-sdk -sdk "$AppleTVOSSDKPath" -module-list-file "/tmp/modules-tvos.txt" -F "$XCTestTV" -module-cache-path "$DumpDir/ModuleCache" -swift-version $SWIFT_VER + $SWIFT_API_DIGESTER -target armv7k-apple-watchos6.2 -o "$BASEDIR/watchos$XCODE_VER.json" -dump-sdk -sdk "$WathOSSDKPath" -module-list-file "/tmp/modules-watchos.txt" -module-cache-path "$DumpDir/ModuleCache" -swift-version $SWIFT_VER + $SWIFT_API_DIGESTER -target x86_64-apple-macosx10.15 -o "$BASEDIR/macos-stdlib$XCODE_VER.json" -dump-sdk -sdk "$MacSDKPath" -module Swift -module-cache-path "$DumpDir/ModuleCache" -swift-version $SWIFT_VER +else + ALL_MODULE_DIR="$BASEDIR/Xcode$XCODE_VER" + rm -rf "$ALL_MODULE_DIR" + mkdir "$ALL_MODULE_DIR" + declare -a MODULE_NAMES=("Accelerate" "Foundation" "AppKit" "UIKit" "AudioToolbox" "Automator" "AVFoundation" + "AVKit" "CloudKit" "CoreBluetooth" "GameKit" "iAd" "Metal" "MetalKit" + "MetalPerformanceShaders" "OpenGLES" "Quartz" "XCTest" "UserNotifications" "CoreMedia" "VideoToolbox" "MediaToolbox" "MapKit") + for MODULE in "${MODULE_NAMES[@]}" + do + echo "Generating baseline for framework ${MODULE}" + MODULE_DIR="$ALL_MODULE_DIR/$MODULE" + rm -rf "$MODULE_DIR" + mkdir "$MODULE_DIR" + $SWIFT_API_DIGESTER -target x86_64-apple-macosx10.15 -o "$MODULE_DIR/macos.json" -dump-sdk -sdk "$MacSDKPath" -module "$MODULE" -F "$XCTestMac" -module-cache-path "$DumpDir/ModuleCache" -swift-version $SWIFT_VER + $SWIFT_API_DIGESTER -target arm64-apple-ios13.5 -o "$MODULE_DIR/ios.json" -dump-sdk -sdk "$IphoneOSSDKPath" -module "$MODULE" -F "$XCTestIphone" -module-cache-path "$DumpDir/ModuleCache" -swift-version $SWIFT_VER + $SWIFT_API_DIGESTER -target arm64-apple-tvos13.4 -o "$MODULE_DIR/tvos.json" -dump-sdk -sdk "$AppleTVOSSDKPath" -module "$MODULE" -F "$XCTestTV" -module-cache-path "$DumpDir/ModuleCache" -swift-version $SWIFT_VER + $SWIFT_API_DIGESTER -target armv7k-apple-watchos6.2 -o "$MODULE_DIR/watchos.json" -dump-sdk -sdk "$WathOSSDKPath" -module "$MODULE" -module-cache-path "$DumpDir/ModuleCache" -swift-version $SWIFT_VER + done +fi diff --git a/utils/api_checker/sdk-module-lists/create-module-lists.sh b/utils/api_checker/sdk-module-lists/create-module-lists.sh new file mode 100755 index 0000000000000..c794567fcb043 --- /dev/null +++ b/utils/api_checker/sdk-module-lists/create-module-lists.sh @@ -0,0 +1,13 @@ +DIR="$( cd "$( dirname "$0" )" && pwd )" +$DIR/infer-imports.py -s $(xcrun --sdk macosx --show-sdk-path) > /tmp/modules-osx.txt && \ +$DIR/infer-imports.py -s $(xcrun --sdk iphoneos --show-sdk-path) > /tmp/modules-iphoneos.txt && \ +$DIR/infer-imports.py -s $(xcrun --sdk appletvos --show-sdk-path) > /tmp/modules-tvos.txt && \ +$DIR/infer-imports.py -s $(xcrun --sdk watchos --show-sdk-path) > /tmp/modules-watchos.txt && \ +cat $DIR/fixed-clang-modules-common.txt >> /tmp/modules-osx.txt && \ +cat $DIR/fixed-clang-modules-macosx.txt >> /tmp/modules-osx.txt && \ +cat $DIR/fixed-clang-modules-common.txt >> /tmp/modules-iphoneos.txt && \ +cat $DIR/fixed-clang-modules-iphoneos.txt >> /tmp/modules-iphoneos.txt && \ +cat $DIR/fixed-clang-modules-common.txt >> /tmp/modules-tvos.txt && \ +cat $DIR/fixed-clang-modules-appletvos.txt >> /tmp/modules-tvos.txt && \ +cat $DIR/fixed-clang-modules-common.txt >> /tmp/modules-watchos.txt && \ +cat $DIR/fixed-clang-modules-watchos.txt >> /tmp/modules-watchos.txt diff --git a/utils/api_checker/sdk-module-lists/fixed-clang-modules-appletvos.txt b/utils/api_checker/sdk-module-lists/fixed-clang-modules-appletvos.txt index 5154bd4dff5d3..7c352a57bb1d6 100644 --- a/utils/api_checker/sdk-module-lists/fixed-clang-modules-appletvos.txt +++ b/utils/api_checker/sdk-module-lists/fixed-clang-modules-appletvos.txt @@ -1 +1,3 @@ -XCTest \ No newline at end of file +XCTest +SceneKit.ModelIO +CoreImage.CIFilterBuiltins diff --git a/utils/api_checker/sdk-module-lists/fixed-clang-modules-iosmac.txt b/utils/api_checker/sdk-module-lists/fixed-clang-modules-iosmac.txt index d15abba59766b..bef2b6a46493e 100644 --- a/utils/api_checker/sdk-module-lists/fixed-clang-modules-iosmac.txt +++ b/utils/api_checker/sdk-module-lists/fixed-clang-modules-iosmac.txt @@ -1 +1,3 @@ // Empty +SceneKit.ModelIO +CoreImage.CIFilterBuiltins diff --git a/utils/api_checker/sdk-module-lists/fixed-clang-modules-iphoneos.txt b/utils/api_checker/sdk-module-lists/fixed-clang-modules-iphoneos.txt index 5154bd4dff5d3..7c352a57bb1d6 100644 --- a/utils/api_checker/sdk-module-lists/fixed-clang-modules-iphoneos.txt +++ b/utils/api_checker/sdk-module-lists/fixed-clang-modules-iphoneos.txt @@ -1 +1,3 @@ -XCTest \ No newline at end of file +XCTest +SceneKit.ModelIO +CoreImage.CIFilterBuiltins diff --git a/utils/api_checker/sdk-module-lists/fixed-clang-modules-macosx.txt b/utils/api_checker/sdk-module-lists/fixed-clang-modules-macosx.txt index 14aaee023d9ca..23fa920569b58 100644 --- a/utils/api_checker/sdk-module-lists/fixed-clang-modules-macosx.txt +++ b/utils/api_checker/sdk-module-lists/fixed-clang-modules-macosx.txt @@ -1,2 +1,4 @@ XPC XCTest +SceneKit.ModelIO +CoreImage.CIFilterBuiltins diff --git a/utils/api_checker/sdk-module-lists/infer-imports.py b/utils/api_checker/sdk-module-lists/infer-imports.py index a923c6b2f441c..c85348db9bcce 100755 --- a/utils/api_checker/sdk-module-lists/infer-imports.py +++ b/utils/api_checker/sdk-module-lists/infer-imports.py @@ -8,7 +8,8 @@ denylist = [ "Kernel", "Ruby", "Tk", "DriverKit", "HIDDriverKit", "SkywalkDriverKit", # has C++ code - "NetworkingDriverKit", "USBSerialDriverKit", # has C++ code + "NetworkingDriverKit", "USBSerialDriverKit", "PCIDriverKit", # has C++ code + "USBDriverKit", # has C++ code ] @@ -46,6 +47,8 @@ def get_frameworks(sdk_path, swift_frameworks_only): frameworks_path = sdk_path + "/System/Library/Frameworks" names = [] for frame in os.listdir(frameworks_path): + if frame[0] == '_': + continue if frame.endswith(".framework"): name = frame[:-len(".framework")] header_dir_path = frameworks_path + '/' + frame + '/Headers' @@ -106,8 +109,6 @@ def should_exclude_framework(frame_path): contents = open(module_map_path).read() if "requires !swift" in contents: return True - if "requires unavailable" in contents: - return True return False diff --git a/utils/build-presets.ini b/utils/build-presets.ini index 630e4c7c7cb0f..f0e82b37a4ab6 100644 --- a/utils/build-presets.ini +++ b/utils/build-presets.ini @@ -212,21 +212,6 @@ skip-test-ios-simulator skip-test-tvos-simulator skip-test-watchos-simulator -[preset: buildbot,tools=RA,stdlib=RD,single-thread] -mixin-preset= - mixin_buildbot_tools_RA_stdlib_RD - -dash-dash - -# Enable non-atomic build of the stdlib -swift-stdlib-use-nonatomic-rc=true - -# Don't run host tests for iOS, tvOS and watchOS platforms to make the build -# faster. -skip-test-ios-host -skip-test-tvos-host -skip-test-watchos-host - [preset: buildbot,tools=R,stdlib=RD] mixin-preset= mixin_buildbot_tools_R_stdlib_RD @@ -371,6 +356,7 @@ libcxx # Build llbuild & swiftpm here llbuild swiftpm +swift-driver indexstore-db sourcekit-lsp @@ -396,6 +382,7 @@ install-llvm install-swift install-llbuild install-swiftpm +install-swift-driver install-libcxx [preset: buildbot_incremental,tools=RA,stdlib=RA,xcode] @@ -418,6 +405,7 @@ swift-primary-variant-arch=x86_64 skip-build-llbuild skip-test-llbuild skip-test-swiftpm +skip-test-swift-driver skip-test-playgroundsupport # This preset is used by CI to test swift-corelibs-xctest. @@ -602,12 +590,14 @@ build-ninja libcxx llbuild swiftpm +swift-driver indexstore-db sourcekit-lsp install-llvm install-swift install-llbuild install-swiftpm +install-swift-driver install-libcxx # We need to build the unittest extras so we can test @@ -786,11 +776,12 @@ llvm-install-components=llvm-cov;llvm-profdata;IndexStore;clang;clang-resource-h [preset: mixin_linux_installation] mixin-preset= - mixin_lightweight_assertions + mixin_lightweight_assertions,no-stdlib-asserts mixin_linux_install_components_with_clang llbuild swiftpm +swift-driver xctest libicu libcxx @@ -803,6 +794,7 @@ install-swift install-lldb install-llbuild install-swiftpm +install-swift-driver install-xctest install-libicu install-prefix=/usr @@ -859,6 +851,7 @@ skip-test-lldb skip-test-swift skip-test-llbuild skip-test-swiftpm +skip-test-swift-driver skip-test-xctest skip-test-foundation skip-test-libdispatch @@ -1020,6 +1013,7 @@ lldb #test foundation swiftpm +swift-driver xctest build-subdir=buildbot_linux @@ -1032,6 +1026,7 @@ install-lldb install-llbuild install-foundation install-swiftpm +install-swift-driver install-xctest install-prefix=/usr swift-install-components=autolink-driver;compiler;clang-builtin-headers;stdlib;swift-remote-mirror;sdk-overlay;dev @@ -1079,6 +1074,7 @@ libcxx libicu llbuild swiftpm +swift-driver xctest foundation libdispatch @@ -1092,6 +1088,7 @@ install-swift install-llbuild install-libicu install-swiftpm +install-swift-driver install-foundation install-libdispatch install-xctest @@ -1195,6 +1192,7 @@ watchos lldb llbuild swiftpm +swift-driver swiftsyntax skstresstester swiftevolve @@ -1221,11 +1219,22 @@ verbose-build build-ninja build-swift-stdlib-unittest-extra +# When building for an Xcode toolchain, don't copy the Swift Resource/ directory +# into the LLDB.framework. LLDB.framework will be installed alongside a Swift +# compiler, so LLDB should use its resource directory directly. +# Also, to reduce the size of the final toolchain, limit debug info to be +# line-tables only. +extra-cmake-options= + -DLLDB_FRAMEWORK_COPY_SWIFT_RESOURCES=0 + -DCMAKE_C_FLAGS="-gline-tables-only" + -DCMAKE_CXX_FLAGS="-gline-tables-only" + install-llvm install-swift install-lldb install-llbuild install-swiftpm +install-swift-driver install-swiftsyntax install-skstresstester install-swiftevolve @@ -1304,6 +1313,8 @@ dash-dash no-assertions +# SKIP LLDB TESTS (67923799) +skip-test-lldb [preset: buildbot_osx_package,no_assertions,lto] mixin-preset=buildbot_osx_package,no_assertions @@ -1319,6 +1330,7 @@ dash-dash skip-test-swift skip-test-swiftpm +skip-test-swift-driver skip-test-llbuild skip-test-lldb skip-test-cmark @@ -1340,16 +1352,10 @@ debug-llvm debug-swift no-swift-stdlib-assertions - -# macOS package with out test -[preset: buildbot_osx_package,no_test] -mixin-preset= - buildbot_osx_package - -dash-dash - +[preset: mixin_buildbot_osx_package,no_test] skip-test-swift skip-test-swiftpm +skip-test-swift-driver skip-test-llbuild skip-test-lldb skip-test-cmark @@ -1358,9 +1364,11 @@ skip-test-swiftsyntax skip-test-skstresstester skip-test-swiftevolve -extra-cmake-options= - -DCMAKE_C_FLAGS="-gline-tables-only" - -DCMAKE_CXX_FLAGS="-gline-tables-only" +# macOS package with out test +[preset: buildbot_osx_package,no_test] +mixin-preset= + buildbot_osx_package + mixin_buildbot_osx_package,no_test #===------------------------------------------------------------------------===# # LLDB build configurations @@ -1487,6 +1495,7 @@ libcxx # Build llbuild & swiftpm here llbuild swiftpm +swift-driver swiftsyntax # Don't generate the SwiftSyntax gyb files. Instead verify that up-to-date ones @@ -1500,6 +1509,7 @@ install-llvm install-swift install-llbuild install-swiftpm +install-swift-driver install-libcxx # Build the stress tester and SwiftEvolve @@ -1686,6 +1696,22 @@ assertions # Downstream projects that import llbuild+SwiftPM. sourcekit-lsp +#===------------------------------------------------------------------------===# +# Test Swift Driver (new) +#===------------------------------------------------------------------------===# + +[preset: buildbot_swift-driver_macos] +mixin-preset=mixin_swiftpm_package_macos_platform +release +assertions +swift-driver + +[preset: buildbot_swift-driver_linux] +mixin-preset=mixin_swiftpm_package_linux_platform +release +assertions +swift-driver + #===------------------------------------------------------------------------===# # Test Swift Syntax #===------------------------------------------------------------------------===# @@ -2365,6 +2391,48 @@ mixin-preset=stdlib_DA_standalone,build test validation-test +[preset: stdlib_S_standalone,build] +mixin-preset=stdlib_base_standalone + +build-subdir=stdlib_S_standalone +min-size-release +no-assertions + +verbose-build + +[preset: stdlib_SA_standalone,build] +mixin-preset=stdlib_base_standalone + +build-subdir=stdlib_SA_standalone +min-size-release +assertions + +verbose-build + +[preset: mixin_stdlib_minimal] +enable-experimental-differentiable-programming=0 +enable-experimental-concurrency=0 +build-swift-dynamic-sdk-overlay=0 +build-swift-dynamic-stdlib=0 +build-swift-static-stdlib=1 +swift-objc-interop=0 +swift-enable-compatibility-overrides=0 +swift-runtime-macho-no-dyld=1 +swift-stdlib-single-threaded-runtime=1 + +[preset: stdlib_S_standalone_minimal_macho_x86_64,build] +mixin-preset= + stdlib_S_standalone,build + mixin_stdlib_minimal + +stdlib-deployment-targets=freestanding-x86_64 +swift-primary-variant-sdk=FREESTANDING +swift-primary-variant-arch=x86_64 +swift-freestanding-sdk=macosx +# For now, until clang/swiftc works correctly with "none-macho" as the OS part of target triple. +swift-freestanding-triple-name=macosx11.0 +swift-freestanding-archs=x86_64 + #===----------------------------------------------------------------------===# # Preset for Source Compatibility Suite #===----------------------------------------------------------------------===# @@ -2373,10 +2441,12 @@ validation-test build-ninja llbuild swiftpm +swift-driver install-llbuild install-llvm install-swift install-swiftpm +install-swift-driver reconfigure verbose-build skip-build-benchmarks @@ -2419,21 +2489,25 @@ swift-install-components=autolink-driver;compiler;clang-builtin-headers;stdlib;s mixin-preset=source_compat_suite_macos_base debug assertions +cross-compile-hosts=macosx-arm64 [preset: source_compat_suite_macos_RA] mixin-preset=source_compat_suite_macos_base release assertions +cross-compile-hosts=macosx-arm64 [preset: source_compat_suite_macos_R] mixin-preset=source_compat_suite_macos_base release no-assertions +cross-compile-hosts=macosx-arm64 [preset: source_compat_suite_macos_D] mixin-preset=source_compat_suite_macos_base debug no-assertions +cross-compile-hosts=macosx-arm64 [preset: source_compat_suite_linux_DA] mixin-preset=source_compat_suite_linux_base @@ -2468,9 +2542,10 @@ skip-build-benchmarks llvm-targets-to-build=X86;AArch64;WebAssembly install-destdir=%(INSTALL_DESTDIR)s swift-install-components=autolink-driver;compiler;clang-builtin-headers;stdlib;sdk-overlay;parser-lib;editor-integration;tools;testsuite-tools;toolchain-tools;license;sourcekit-inproc;swift-remote-mirror;swift-remote-mirror-headers;clang-resource-dir-symlink -llvm-install-components=clang +llvm-install-components=IndexStore;clang install-swift install-prefix=/%(TOOLCHAIN_NAME)s/usr +swift-darwin-supported-archs=x86_64 [preset: webassembly-host] @@ -2480,13 +2555,18 @@ extra-cmake-options= -DSWIFT_ENABLE_SOURCEKIT_TESTS=FALSE -DSWIFT_BUILD_SYNTAXPARSERLIB=FALSE +libcxx llbuild swiftpm +indexstore-db +sourcekit-lsp +install-libcxx install-llvm install-swift install-llbuild install-swiftpm +install-sourcekit-lsp [preset: webassembly-linux-host] @@ -2544,6 +2624,7 @@ extra-cmake-options= -DWASI_ICU_MD5:STRING="25943864ebbfff15cf5aee8d9d5cc4d7" -DSWIFT_PRIMARY_VARIANT_SDK:STRING=WASI -DSWIFT_PRIMARY_VARIANT_ARCH:STRING=wasm32 + -DSWIFT_SDKS='WASI' -DSWIFT_OSX_x86_64_ICU_STATICLIB=TRUE -DSWIFT_BUILD_SOURCEKIT=FALSE -DSWIFT_ENABLE_SOURCEKIT_TESTS=FALSE diff --git a/utils/build-script b/utils/build-script index 27097dea10d23..60f9398bca2c0 100755 --- a/utils/build-script +++ b/utils/build-script @@ -563,9 +563,6 @@ class BuildScriptInvocation(object): impl_args += ["--skip-build"] if not args.build_benchmarks: impl_args += ["--skip-build-benchmarks"] - # Currently we do not build external benchmarks by default. - if args.build_external_benchmarks: - impl_args += ["--skip-build-external-benchmarks=0"] # Then add subproject install flags that either skip building them /or/ # if we are going to build them and install_all is set, we also install @@ -599,26 +596,6 @@ class BuildScriptInvocation(object): if args.build_swift_static_sdk_overlay: impl_args += ["--build-swift-static-sdk-overlay"] - if not args.build_linux: - impl_args += ["--skip-build-linux"] - if not args.build_freebsd: - impl_args += ["--skip-build-freebsd"] - if not args.build_cygwin: - impl_args += ["--skip-build-cygwin"] - if not args.build_osx: - impl_args += ["--skip-build-osx"] - if not args.build_ios_device: - impl_args += ["--skip-build-ios-device"] - if not args.build_ios_simulator: - impl_args += ["--skip-build-ios-simulator"] - if not args.build_tvos_device: - impl_args += ["--skip-build-tvos-device"] - if not args.build_tvos_simulator: - impl_args += ["--skip-build-tvos-simulator"] - if not args.build_watchos_device: - impl_args += ["--skip-build-watchos-device"] - if not args.build_watchos_simulator: - impl_args += ["--skip-build-watchos-simulator"] if not args.build_android: impl_args += ["--skip-build-android"] if not args.build_wasm: @@ -638,36 +615,6 @@ class BuildScriptInvocation(object): "--skip-test-libdispatch", "--skip-test-libicu", ] - if not args.test_linux: - impl_args += ["--skip-test-linux"] - if not args.test_freebsd: - impl_args += ["--skip-test-freebsd"] - if not args.test_cygwin: - impl_args += ["--skip-test-cygwin"] - if not args.test_osx: - impl_args += ["--skip-test-osx"] - if not args.test_ios_host: - impl_args += ["--skip-test-ios-host"] - if not args.test_ios_simulator: - impl_args += ["--skip-test-ios-simulator"] - if not args.test_ios_32bit_simulator: - impl_args += ["--skip-test-ios-32bit-simulator"] - if not args.test_tvos_host: - impl_args += ["--skip-test-tvos-host"] - if not args.test_tvos_simulator: - impl_args += ["--skip-test-tvos-simulator"] - if not args.test_watchos_host: - impl_args += ["--skip-test-watchos-host"] - if not args.test_watchos_simulator: - impl_args += ["--skip-test-watchos-simulator"] - if not args.test_android: - impl_args += ["--skip-test-android"] - if not args.test_android_host: - impl_args += ["--skip-test-android-host"] - if not args.test_wasm: - impl_args += ["--skip-test-wasm"] - if not args.test_wasm_host: - impl_args += ["--skip-test-wasm-host"] if args.build_runtime_with_host_compiler: impl_args += ["--build-runtime-with-host-compiler"] if args.validation_test: @@ -682,12 +629,6 @@ class BuildScriptInvocation(object): impl_args += ["--only-executable-test"] if not args.benchmark: impl_args += ["--skip-test-benchmarks"] - if not args.test_optimized: - impl_args += ["--skip-test-optimized"] - if not args.test_optimize_for_size: - impl_args += ["--skip-test-optimize-for-size"] - if not args.test_optimize_none_with_implicit_dynamic: - impl_args += ["--skip-test-optimize-none-with-implicit-dynamic"] if args.build_libparser_only: impl_args += ["--build-libparser-only"] if args.android: @@ -1013,6 +954,9 @@ class BuildScriptInvocation(object): for product_class in impl_product_classes: self._execute_install_action(host_target, product_class) + # Lipo... + self._execute_merged_host_lipo_action() + # Non-build-script-impl products... # Note: currently only supports building for the host. for host_target in [self.args.host_target]: @@ -1032,6 +976,9 @@ class BuildScriptInvocation(object): toolchain=self.toolchain, source_dir=self.workspace.source_dir(product_source), build_dir=build_dir) + if product.should_clean(host_target): + print("--- Cleaning %s ---" % product_name) + product.clean(host_target) if product.should_build(host_target): print("--- Building %s ---" % product_name) product.build(host_target) @@ -1052,9 +999,6 @@ class BuildScriptInvocation(object): for host_target in all_hosts: self._execute_package_action(host_target) - # Lipo... - self._execute_merged_host_lipo_action() - def _execute_build_action(self, host_target, product_class): action_name = "{}-{}-build".format(host_target.name, product_class.product_name()) diff --git a/utils/build-script-impl b/utils/build-script-impl index c8d80d53f028d..c19831dda0acf 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -125,47 +125,14 @@ KNOWN_SETTINGS=( ## Skip Build ... skip-build "" "set to configure as usual while skipping the build step" skip-build-android "" "set to skip building Swift stdlibs for Android" + skip-build-wasm "" "set to skip building Swift stdlibs for WebAssembly" skip-build-benchmarks "" "set to skip building Swift Benchmark Suite" skip-build-clang-tools-extra "" "set to skip building clang-tools-extra as part of llvm" skip-build-compiler-rt "" "set to skip building Compiler-RT" skip-build-lld "" "set to skip building lld as part of llvm (linux only)" - skip-build-cygwin "" "set to skip building Swift stdlibs for Cygwin" - skip-build-external-benchmarks "1" "set to skip building the external Swift Benchmark Suite. (skipped by default)" - skip-build-freebsd "" "set to skip building Swift stdlibs for FreeBSD" - skip-build-haiku "" "set to skip building Swift stdlibs for Haiku" - skip-build-ios-device "" "set to skip building Swift stdlibs for iOS devices (i.e. build simulators only)" - skip-build-ios-simulator "" "set to skip building Swift stdlibs for iOS simulators (i.e. build devices only)" - skip-build-linux "" "set to skip building Swift stdlibs for Linux" - skip-build-maccatalyst "" "set to skip building Swift stdlibs for macCatalyst" - skip-build-osx "" "set to skip building Swift stdlibs for OS X" - skip-build-tvos-device "" "set to skip building Swift stdlibs for tvOS devices (i.e. build simulators only)" - skip-build-tvos-simulator "" "set to skip building Swift stdlibs for tvOS simulators (i.e. build devices only)" - skip-build-wasm "" "set to skip building Swift stdlibs for WebAssembly" - skip-build-watchos-device "" "set to skip building Swift stdlibs for Apple watchOS devices (i.e. build simulators only)" - skip-build-watchos-simulator "" "set to skip building Swift stdlibs for Apple watchOS simulators (i.e. build devices only)" ## Skip Test ... - skip-test-android "" "set to skip testing Swift stdlibs for Android" - skip-test-android-host "" "set to skip testing the host parts of the Android toolchain" - skip-test-cygwin "" "set to skip testing Swift stdlibs for Cygwin" - skip-test-freebsd "" "set to skip testing Swift stdlibs for FreeBSD" - skip-test-haiku "" "set to skip testing Swift stdlibs for Haiku" - skip-test-ios-32bit-simulator "" "set to skip testing Swift stdlibs for iOS 32bit simulators" - skip-test-ios-host "" "set to skip testing the host parts of the iOS toolchain" - skip-test-ios-simulator "" "set to skip testing Swift stdlibs for iOS simulators (i.e. test devices only)" - skip-test-linux "" "set to skip testing Swift stdlibs for Linux" - skip-test-maccatalyst "" "set to skip testing Swift stdlibs for macCatalyst" - skip-test-osx "" "set to skip testing Swift stdlibs for OS X" - skip-test-tvos-host "" "set to skip testing the host parts of the tvOS toolchain" - skip-test-tvos-simulator "" "set to skip testing Swift stdlibs for tvOS simulators (i.e. test devices only)" - skip-test-wasm "" "set to skip testing Swift stdlibs for WebAssembly" - skip-test-wasm-host "" "set to skip testing the host parts of the WebAssembly toolchain" - skip-test-watchos-host "" "set to skip testing the host parts of the watchOS toolchain" - skip-test-watchos-simulator "" "set to skip testing Swift stdlibs for Apple watchOS simulators (i.e. test devices only)" skip-test-benchmarks "" "set to skip running Swift Benchmark Suite" - skip-test-optimized "" "set to skip testing the test suite in optimized mode" - skip-test-optimize-for-size "" "set to skip testing the test suite in optimize for size mode" - skip-test-optimize-none-with-implicit-dynamic "" "set to skip testing the test suite in optimize none with implicit dynamic mode" skip-test-sourcekit "" "set to skip testing SourceKit" ## Extra ... CMake Options @@ -223,12 +190,20 @@ KNOWN_SETTINGS=( swift-primary-variant-sdk "" "default SDK for target binaries" swift-runtime-enable-leak-checker "0" "Enable leaks checking routines in the runtime" swift-stdlib-enable-assertions "1" "enable assertions in Swift" - swift-stdlib-use-nonatomic-rc "0" "build the Swift stdlib and overlays with nonatomic reference count operations enabled" swift-tools-enable-lto "" "enable LTO compilation of Swift tools. *NOTE* This does not include the swift standard library and runtime. Must be set to one of 'thin' or 'full'" extra-swift-args "" "Extra arguments to pass to swift modules which match regex. Assumed to be a flattened cmake list consisting of [module_regexp, args, module_regexp, args, ...]" report-statistics "0" "set to 1 to generate compilation statistics files for swift libraries" sil-verify-all "0" "If enabled, run the SIL verifier after each transform when building Swift files during this build process" stdlib-deployment-targets "" "space-separated list of targets to configure the Swift standard library to be compiled or cross-compiled for" + swift-objc-interop "" "whether to enable interoperability with Objective-C, default is 1 on Apple platfors, 0 otherwise" + swift-enable-compatibility-overrides "1" "whether to support back-deploying compatibility fixes for newer apps running on older runtimes" + swift-runtime-macho-no-dyld "0" "whether to build stdlib assuming the runtime environment does not support dynamic modules" + swift-stdlib-single-threaded-runtime "0" "whether to build stdlib as a single-threaded runtime only" + + ## FREESTANDING Stdlib Options + swift-freestanding-sdk "" "which SDK to use when building the FREESTANDING stdlib" + swift-freestanding-triple-name "" "which triple name (e.g. 'none-macho') to use when building the FREESTANDING stdlib" + swift-freestanding-archs "" "space-separated list of which architectures to build when building the FREESTANDING stdlib" ## Uncategorised install-prefix "" "installation prefix" @@ -1261,9 +1236,6 @@ function build_directory_bin() { ;; libicu) ;; - playgroundsupport) - echo "${root}/${PLAYGROUNDSUPPORT_BUILD_TYPE}/bin" - ;; *) echo "error: unknown product: ${product}" exit 1 @@ -1385,9 +1357,6 @@ function cmake_config_opt() { ;; libicu) ;; - playgroundsupport) - echo "--config ${PLAYGROUNDSUPPORT_BUILD_TYPE}" - ;; *) echo "error: unknown product: ${product}" exit 1 @@ -1446,6 +1415,13 @@ for host in "${ALL_HOSTS[@]}"; do fi fi + if [[ "${NATIVE_CLANG_TOOLS_PATH}" ]] ; then + common_cmake_options_host+=( + -DCMAKE_C_COMPILER="${NATIVE_CLANG_TOOLS_PATH}/clang" + -DCMAKE_CXX_COMPILER="${NATIVE_CLANG_TOOLS_PATH}/clang++" + ) + fi + llvm_cmake_options=( "${llvm_cmake_options[@]}" -DCMAKE_INSTALL_PREFIX:PATH="$(get_host_install_prefix ${host})" @@ -1610,8 +1586,6 @@ for host in "${ALL_HOSTS[@]}"; do "${cmake_options[@]}" -DCMAKE_C_FLAGS="$(llvm_c_flags ${host})" -DCMAKE_CXX_FLAGS="$(llvm_c_flags ${host})" - -DCMAKE_C_FLAGS_RELWITHDEBINFO="-O2 -DNDEBUG" - -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="-O2 -DNDEBUG" -DCMAKE_BUILD_TYPE:STRING="${LLVM_BUILD_TYPE}" -DLLVM_TOOL_SWIFT_BUILD:BOOL=NO -DLLVM_TOOL_LLD_BUILD:BOOL=TRUE @@ -1797,15 +1771,15 @@ for host in "${ALL_HOSTS[@]}"; do "${cmake_options[@]}" -DCMAKE_C_FLAGS="$(swift_c_flags ${host})" -DCMAKE_CXX_FLAGS="$(swift_c_flags ${host})" - -DCMAKE_C_FLAGS_RELWITHDEBINFO="-O2 -DNDEBUG" - -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="-O2 -DNDEBUG" -DCMAKE_BUILD_TYPE:STRING="${SWIFT_BUILD_TYPE}" -DLLVM_ENABLE_ASSERTIONS:BOOL=$(true_false "${SWIFT_ENABLE_ASSERTIONS}") -DSWIFT_ANALYZE_CODE_COVERAGE:STRING=$(toupper "${SWIFT_ANALYZE_CODE_COVERAGE}") -DSWIFT_STDLIB_BUILD_TYPE:STRING="${SWIFT_STDLIB_BUILD_TYPE}" -DSWIFT_STDLIB_ASSERTIONS:BOOL=$(true_false "${SWIFT_STDLIB_ENABLE_ASSERTIONS}") - -DSWIFT_STDLIB_USE_NONATOMIC_RC:BOOL=$(true_false "${SWIFT_STDLIB_USE_NONATOMIC_RC}") + -DSWIFT_ENABLE_COMPATIBILITY_OVERRIDES:BOOL=$(true_false "${SWIFT_ENABLE_COMPATIBILITY_OVERRIDES}") + -DSWIFT_STDLIB_SINGLE_THREADED_RUNTIME:BOOL=$(true_false "${SWIFT_STDLIB_SINGLE_THREADED_RUNTIME}") -DSWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS:BOOL=$(true_false "${SWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS}") + -DSWIFT_RUNTIME_MACHO_NO_DYLD:BOOL=$(true_false "${SWIFT_RUNTIME_MACHO_NO_DYLD}") -DSWIFT_NATIVE_LLVM_TOOLS_PATH:STRING="${native_llvm_tools_path}" -DSWIFT_NATIVE_CLANG_TOOLS_PATH:STRING="${native_clang_tools_path}" -DSWIFT_NATIVE_SWIFT_TOOLS_PATH:STRING="${native_swift_tools_path}" @@ -1859,6 +1833,13 @@ for host in "${ALL_HOSTS[@]}"; do ) fi + if [[ "${SWIFT_OBJC_INTEROP}" == "0" ]] ; then + cmake_options=( + "${cmake_options[@]}" + -DSWIFT_DISABLE_OBJC_INTEROP:BOOL=True + ) + fi + if [[ "${SWIFT_PRIMARY_VARIANT_SDK}" ]] ; then cmake_options=( "${cmake_options[@]}" @@ -1880,6 +1861,27 @@ for host in "${ALL_HOSTS[@]}"; do ) fi + if [ "${SWIFT_FREESTANDING_SDK}" ] ; then + cmake_options=( + "${cmake_options[@]}" + -DSWIFT_FREESTANDING_SDK:STRING="${SWIFT_FREESTANDING_SDK}" + ) + fi + + if [ "${SWIFT_FREESTANDING_TRIPLE_NAME}" ] ; then + cmake_options=( + "${cmake_options[@]}" + -DSWIFT_FREESTANDING_TRIPLE_NAME:STRING="${SWIFT_FREESTANDING_TRIPLE_NAME}" + ) + fi + + if [[ "${SWIFT_FREESTANDING_ARCHS}" ]] ; then + cmake_options=( + "${cmake_options[@]}" + -DSWIFT_FREESTANDING_ARCHS:STRING="$(join ";" ${SWIFT_FREESTANDING_ARCHS[@]})" + ) + fi + if [[ ! "${SKIP_BUILD_LLDB}" ]] ; then lldb_build_dir=$(build_directory ${host} lldb) cmake_options=( @@ -2998,12 +3000,13 @@ for host in "${ALL_HOSTS[@]}"; do # # Exclude shell scripts and static archives. # Exclude swift-api-digester dSYM to reduce debug toolchain size. + # Run sequentially -- dsymutil is multithreaded and can be memory intensive (cd "${host_symroot}" && find ./"${CURRENT_PREFIX}" -perm -0111 -type f -print | \ grep -v '.py$' | \ grep -v '.a$' | \ grep -v 'swift-api-digester' | \ - xargs -n 1 -P ${BUILD_JOBS} ${dsymutil_path}) + xargs -n 1 -P 1 ${dsymutil_path}) # Strip executables, shared libraries and static libraries in # `host_install_destdir`. diff --git a/utils/build-toolchain b/utils/build-toolchain index f89f30f3faf1d..8188482a0eb6d 100755 --- a/utils/build-toolchain +++ b/utils/build-toolchain @@ -29,6 +29,12 @@ function usage() { echo "--distcc" echo "Build with distcc to speed up the toolchain build" echo "" + echo "--preset-file" + echo "load build-script presets from the specified file" + echo "" + echo "--preset-prefix" + echo "Customize the preset invoked by prepending a prefix" + echo "" } RESULT_DIR=$PWD @@ -38,6 +44,8 @@ cd "$(dirname $0)/.." || exit DISTCC_FLAG= DRY_RUN= BUNDLE_PREFIX= +PRESET_FILE_FLAGS= +PRESET_PREFIX= case $(uname -s) in Darwin) SWIFT_PACKAGE=buildbot_osx_package,no_test @@ -69,6 +77,14 @@ while [ $# -ne 0 ]; do ;; --distcc) DISTCC_FLAG="--distcc" + ;; + --preset-file) + shift + PRESET_FILE_FLAGS="${PRESET_FILE_FLAGS} --preset-file=$1" + ;; + --preset-prefix) + shift + PRESET_PREFIX="$1" ;; -h|--help) usage @@ -115,8 +131,9 @@ SWIFT_TOOLCHAIN_DIR="/Library/Developer/Toolchains/${TOOLCHAIN_NAME}.xctoolchain SYMBOLS_PACKAGE="${RESULT_DIR}/${SYM_ARCHIVE}" DRY_RUN="${DRY_RUN}" DISTCC_FLAG="${DISTCC_FLAG}" +PRESET_FILE_FLAGS="${PRESET_FILE_FLAGS}" -./utils/build-script ${DRY_RUN} ${DISTCC_FLAG} --preset="${SWIFT_PACKAGE}" \ +./utils/build-script ${DRY_RUN} ${DISTCC_FLAG} ${PRESET_FILE_FLAGS} --preset="${PRESET_PREFIX}${SWIFT_PACKAGE}" \ install_destdir="${SWIFT_INSTALL_DIR}" \ installable_package="${SWIFT_INSTALLABLE_PACKAGE}" \ install_toolchain_dir="${SWIFT_TOOLCHAIN_DIR}" \ diff --git a/utils/build-windows-rebranch.bat b/utils/build-windows-rebranch.bat new file mode 100644 index 0000000000000..feb14fe07d361 --- /dev/null +++ b/utils/build-windows-rebranch.bat @@ -0,0 +1,349 @@ +:: build-windows.bat +:: +:: This source file is part of the Swift.org open source project +:: +:: Copyright (c) 2014 - 2019 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 + +:: REQUIRED ENVIRONMENT VARIABLES +:: This script requires to be executed inside one Visual Studio command line, +:: in order for many of the tools and environment variables to be available. +:: Additionally, it needs the following variables: +:: - CMAKE_BUILD_TYPE: Kind of build: Release, RelWithDebInfo, Debug. +:: - PYTHON_HOME: The Python installation directory. + +:: REQUIRED PERMISSIONS +:: Practically, it is easier to be in the Adminstrators group to run the +:: script, but it should be possible to execute as a normal user. +:: The user will need permission to write files into the Windows SDK and the +:: VisualC++ folder. + +:: @echo off + +setlocal enableextensions enabledelayedexpansion + +set icu_version_major=64 +set icu_version_minor=2 +set icu_version=%icu_version_major%_%icu_version_minor% +set icu_version_dashed=%icu_version_major%-%icu_version_minor% + +set "exitOnError=|| (exit /b)" +set current_directory=%~dp0 +set current_directory=%current_directory:~0,-1% +set source_root=%current_directory%\..\.. + +:: Resetting source_root with %CD% removes the ..\.. from the paths, and makes +:: the output easier to read. +cd %source_root% +set source_root=%CD% + +set full_build_root=%source_root%\build +mkdir %full_build_root% + +:: Use the shortest path we can for the build directory, to avoid Windows +:: path problems as much as we can. +subst T: /d +subst T: %full_build_root% %exitOnError% +set build_root=T: +set install_directory=%build_root%\Library\Developer\Toolchains\unknown-Asserts-development.xctoolchain\usr + +md %build_root%\tmp +set TMPDIR=%build_root%\tmp + +md %build_root%\tmp\org.llvm.clang +set CUSTOM_CLANG_MODULE_CACHE=%build_root%\tmp\org.llvm.clang.9999 + +md %build_root%\tmp\org.swift.package-manager +set SWIFTPM_MODULECACHE_OVERRIDE=%build_root%\tmp\org.swift.package-manager + +call :clone_repositories %exitOnError% +call :download_icu %exitOnError% +:: TODO: Disabled until we need LLBuild/SwiftPM in this build script. +:: call :download_sqlite3 + +call :build_llvm %exitOnError% +path %PATH%;%install_directory%\bin + +call :build_cmark %exitOnError% + +call :prepare_platform_modules %exitOnError% +call :build_swift %exitOnError% + +call :build_lldb %exitOnError% + +call :build_libdispatch %exitOnError% + +path %source_root%\icu-%icu_version%\bin64;%install_directory%\bin;%build_root%\swift\bin;%build_root%\swift\libdispatch-prefix\bin;%PATH%;C:\Program Files\Git\usr\bin +call :test_swift %exitOnError% +call :test_libdispatch %exitOnError% + +goto :end +endlocal + +:clone_repositories +:: Clones the repositories used by the Windows build. +:: It supposes that the swift repository is already cloned by CI. +:: It supposes the %CD% is the source root. +setlocal enableextensions enabledelayedexpansion + +git -C "%source_root%\swift" config --local core.autocrlf input +git -C "%source_root%\swift" config --local core.symlink true +git -C "%source_root%\swift" checkout-index --force --all + +git clone --depth 1 --single-branch https://github.com/apple/swift-cmark cmark %exitOnError% +git clone --depth 1 --single-branch --branch swift/master-rebranch https://github.com/apple/llvm-project llvm-project %exitOnError% +mklink /D "%source_root%\clang" "%source_root%\llvm-project\clang" +mklink /D "%source_root%\llvm" "%source_root%\llvm-project\llvm" +mklink /D "%source_root%\lld" "%source_root%\llvm-project\lld" +mklink /D "%source_root%\lldb" "%source_root%\llvm-project\lldb" +mklink /D "%source_root%\compiler-rt" "%source_root%\llvm-project\compiler-rt" +mklink /D "%source_root%\libcxx" "%source_root%\llvm-project\libcxx" +mklink /D "%source_root%\clang-tools-extra" "%source_root%\llvm-project\clang-tools-extra" +git clone --depth 1 --single-branch https://github.com/apple/swift-corelibs-libdispatch %exitOnError% + +goto :eof +endlocal + + +:download_icu +:: Downloads ICU, which will be used as a dependency for the Swift Standard +:: Library and Foundation. +setlocal enableextensions enabledelayedexpansion + +set file_name=icu4c-%icu_version%-Win64-MSVC2017.zip +curl -L -O "https://github.com/unicode-org/icu/releases/download/release-%icu_version_dashed%/%file_name%" %exitOnError% +:: unzip warns about the paths in the zip using slashes, which raises the +:: errorLevel to 1. We cannot use exitOnError, and have to ignore errors. +"C:\Program Files\Git\usr\bin\unzip.exe" -o %file_name% -d "%source_root%\icu-%icu_version%" +exit /b 0 + +goto :eof +endlocal + + +:download_sqlite3 +:: Downloads SQLite3, which will be used as a dependency for llbuild and +:: Swift Package Manager. +setlocal enableextensions enabledelayedexpansion + +set file_name=sqlite-amalgamation-3270200.zip +curl -L -O "https://www.sqlite.org/2019/%file_name%" %exitOnError% +"C:\Program Files\Git\usr\bin\unzip.exe" -o %file_name% %exitOnError% + +goto :eof +endlocal + + +:prepare_platform_modules +:: Create files into the right places of the Windows SDK to the files in the +:: swift repository, in order to consider the headers of the Windows SDK a +:: module to compile Swift code against them. +setlocal enableextensions enabledelayedexpansion + +copy /y "%source_root%\swift\stdlib\public\Platform\ucrt.modulemap" "%UniversalCRTSdkDir%\Include\%UCRTVersion%\ucrt\module.modulemap" %exitOnError% +copy /y "%source_root%\swift\stdlib\public\Platform\winsdk.modulemap" "%UniversalCRTSdkDir%\Include\%UCRTVersion%\um\module.modulemap" %exitOnError% +copy /y "%source_root%\swift\stdlib\public\Platform\visualc.modulemap" "%VCToolsInstallDir%\include\module.modulemap" %exitOnError% +copy /y "%source_root%\swift\stdlib\public\Platform\visualc.apinotes" "%VCToolsInstallDir%\include\visualc.apinotes" %exitOnError% + +goto :eof +endlocal + + +:build_llvm +:: Configures, builds, and installs LLVM +setlocal enableextensions enabledelayedexpansion + +cmake^ + -B "%build_root%\llvm"^ + -G Ninja^ + -DCMAKE_BUILD_TYPE=%CMAKE_BUILD_TYPE%^ + -DCMAKE_C_COMPILER=cl^ + -DCMAKE_CXX_COMPILER=cl^ + -DCMAKE_INSTALL_PREFIX:PATH=%install_directory%^ + -DLLVM_DEFAULT_TARGET_TRIPLE=x86_64-unknown-windows-msvc^ + -DLLVM_ENABLE_PDB:BOOL=YES^ + -DLLVM_ENABLE_ASSERTIONS:BOOL=YES^ + -DLLVM_ENABLE_PROJECTS:STRING=lld;clang^ + -DLLVM_TARGETS_TO_BUILD:STRING="AArch64;ARM;X86"^ + -DLLVM_INCLUDE_BENCHMARKS:BOOL=NO^ + -DLLVM_INCLUDE_DOCS:BOOL=NO^ + -DLLVM_INCLUDE_EXAMPLES:BOOL=NO^ + -DLLVM_INCLUDE_GO_TESTS:BOOL=NO^ + -DLLVM_TOOL_GOLD_BUILD:BOOL=NO^ + -DLLVM_ENABLE_OCAMLDOC:BOOL=NO^ + -DLLVM_ENABLE_LIBXML2:BOOL=NO^ + -DLLVM_ENABLE_ZLIB:BOOL=NO^ + -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON^ + -DENABLE_X86_RELAX_RELOCATIONS:BOOL=YES^ + -DLLVM_INSTALL_BINUTILS_SYMLINKS:BOOL=YES^ + -DLLVM_INSTALL_TOOLCHAIN_ONLY:BOOL=YES^ + -DLLVM_TOOLCHAIN_TOOLS:STRING="addr2line;ar;c++filt;dsymutil;dwp;llvm-ar;llvm-cov;llvm-cvtres;llvm-cxxfilt;llvm-dlltool;llvm-dwp;llvm-ranlib;llvm-lib;llvm-mt;llvm-nm;llvm-objdump;llvm-pdbutil;llvm-profdata;llvm-rc;llvm-readelf;llvm-readobj;llvm-size;llvm-strip;llvm-symbolizer;llvm-undname;nm;objcopy;objdump;ranlib;readelf;size;strings"^ + -DCLANG_TOOLS="clang;clang-format;clang-headers;clang-tidy"^ + -DCMAKE_CXX_FLAGS:STRING="/GS- /Oy"^ + -DCMAKE_EXE_LINKER_FLAGS:STRING=/INCREMENTAL:NO^ + -DCMAKE_SHARED_LINKER_FLAGS:STRING=/INCREMENTAL:NO^ + -S "%source_root%\llvm" %exitOnError% + +cmake --build "%build_root%\llvm" %exitOnError% +cmake --build "%build_root%\llvm" --target install %exitOnError% + +goto :eof +endlocal + + +:build_cmark +:: Configures and builds CMark +setlocal enableextensions enabledelayedexpansion + +cmake^ + -B "%build_root%\cmark"^ + -G Ninja^ + -DCMAKE_BUILD_TYPE=%CMAKE_BUILD_TYPE%^ + -DCMAKE_C_COMPILER=cl^ + -DCMAKE_CXX_COMPILER=cl^ + -DCMAKE_CXX_FLAGS:STRING="/GS- /Oy"^ + -DCMAKE_EXE_LINKER_FLAGS:STRING=/INCREMENTAL:NO^ + -DCMAKE_SHARED_LINKER_FLAGS:STRING=/INCREMENTAL:NO^ + -S "%source_root%\cmark" %exitOnError% + +cmake --build "%build_root%\cmark" %exitOnError% + +goto :eof +endlocal + + +:build_swift +:: Configures, builds, and installs Swift and the Swift Standard Library +setlocal enableextensions enabledelayedexpansion + +:: SWIFT_PARALLEL_LINK_JOBS=8 allows the build machine to use as many CPU as +:: possible, while not exhausting the RAM. +cmake^ + -B "%build_root%\swift"^ + -G Ninja^ + -DCMAKE_BUILD_TYPE=%CMAKE_BUILD_TYPE%^ + -DCMAKE_C_COMPILER=cl^ + -DCMAKE_CXX_COMPILER=cl^ + -DCMAKE_INSTALL_PREFIX:PATH=%install_directory%^ + -DClang_DIR:PATH=%build_root%\llvm\lib\cmake\clang^ + -DSWIFT_PATH_TO_CMARK_BUILD:PATH=%build_root%\cmark^ + -DSWIFT_PATH_TO_CMARK_SOURCE:PATH=%source_root%\cmark^ + -DSWIFT_PATH_TO_LIBDISPATCH_SOURCE:PATH=%source_root%\swift-corelibs-libdispatch^ + -DLLVM_DIR:PATH=%build_root%\llvm\lib\cmake\llvm^ + -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON^ + -DSWIFT_INCLUDE_DOCS:BOOL=NO^ + -DSWIFT_WINDOWS_x86_64_ICU_UC_INCLUDE:PATH=%source_root%\icu-%icu_version%\include\unicode^ + -DSWIFT_WINDOWS_x86_64_ICU_UC:PATH=%source_root%\icu-%icu_version%\lib64\icuuc.lib^ + -DSWIFT_WINDOWS_x86_64_ICU_I18N_INCLUDE:PATH=%source_root%\icu-%icu_version%\include^ + -DSWIFT_WINDOWS_x86_64_ICU_I18N:PATH=%source_root%\icu-%icu_version%\lib64\icuin.lib^ + -DSWIFT_BUILD_DYNAMIC_STDLIB:BOOL=YES^ + -DSWIFT_BUILD_DYNAMIC_SDK_OVERLAY:BOOL=YES^ + -DSWIFT_BUILD_STATIC_STDLIB:BOOL=NO^ + -DSWIFT_BUILD_STATIC_SDK_OVERLAY:BOOL=NO^ + -DLLVM_INSTALL_TOOLCHAIN_ONLY:BOOL=YES^ + -DSWIFT_BUILD_SOURCEKIT:BOOL=YES^ + -DSWIFT_ENABLE_SOURCEKIT_TESTS:BOOL=YES^ + -DSWIFT_INSTALL_COMPONENTS="autolink-driver;compiler;clang-resource-dir-symlink;stdlib;sdk-overlay;editor-integration;tools;sourcekit-inproc;swift-remote-mirror;swift-remote-mirror-headers"^ + -DSWIFT_PARALLEL_LINK_JOBS=8^ + -DPYTHON_EXECUTABLE:PATH=%PYTHON_HOME%\python.exe^ + -DCMAKE_CXX_FLAGS:STRING="/GS- /Oy"^ + -DCMAKE_EXE_LINKER_FLAGS:STRING=/INCREMENTAL:NO^ + -DCMAKE_SHARED_LINKER_FLAGS:STRING=/INCREMENTAL:NO^ + -S "%source_root%\swift" %exitOnError% + +cmake --build "%build_root%\swift" %exitOnError% +cmake --build "%build_root%\swift" --target install %exitOnError% + +goto :eof +endlocal + + +:test_swift +:: Tests the Swift compiler and the Swift Standard Library +setlocal enableextensions enabledelayedexpansion + +cmake --build "%build_root%\swift" --target check-swift %exitOnError% + +goto :eof +endlocal + + +:build_lldb +:: Configures, builds, and installs LLDB +setlocal enableextensions enabledelayedexpansion + +cmake^ + -B "%build_root%\lldb"^ + -G Ninja^ + -DCMAKE_BUILD_TYPE=%CMAKE_BUILD_TYPE%^ + -DCMAKE_C_COMPILER=cl^ + -DCMAKE_CXX_COMPILER=cl^ + -DCMAKE_INSTALL_PREFIX:PATH=%install_directory%^ + -DLLVM_DIR:PATH=%build_root%\llvm\lib\cmake\llvm^ + -DClang_DIR:PATH=%build_root%\llvm\lib\cmake\clang^ + -DSwift_DIR:PATH=%build_root%\swift\lib\cmake\swift^ + -DLLVM_ENABLE_ASSERTIONS:BOOL=YES^ + -DLLDB_USE_STATIC_BINDINGS:BOOL=YES^ + -DPYTHON_HOME:PATH=%PYTHON_HOME%^ + -DCMAKE_CXX_FLAGS:STRING="/GS- /Oy"^ + -DCMAKE_EXE_LINKER_FLAGS:STRING=/INCREMENTAL:NO^ + -DCMAKE_SHARED_LINKER_FLAGS:STRING=/INCREMENTAL:NO^ + -DLLDB_DISABLE_PYTHON=YES^ + -DLLDB_INCLUDE_TESTS:BOOL=NO^ + -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON^ + -S "%source_root%\lldb" %exitOnError% + +cmake --build "%build_root%\lldb" %exitOnError% +cmake --build "%build_root%\lldb" --target install %exitOnError% + +goto :eof +endlocal + + +:build_libdispatch +:: Configures, builds, and installs Dispatch +setlocal enableextensions enabledelayedexpansion + +cmake^ + -B "%build_root%\swift-corelibs-libdispatch"^ + -G Ninja^ + -DCMAKE_BUILD_TYPE=%CMAKE_BUILD_TYPE%^ + -DCMAKE_C_COMPILER=clang-cl^ + -DCMAKE_CXX_COMPILER=clang-cl^ + -DCMAKE_Swift_COMPILER=swiftc^ + -DSwift_DIR:PATH=%build_root%\swift\lib\cmake\swift^ + -DCMAKE_INSTALL_PREFIX:PATH=%install_directory%^ + -DCMAKE_C_COMPILER_TARGET=x86_64-unknown-windows-msvc^ + -DCMAKE_CXX_COMPILER_TARGET=x86_64-unknown-windows-msvc^ + -DENABLE_SWIFT:BOOL=YES^ + -DENABLE_TESTING:BOOL=YES^ + -DCMAKE_C_FLAGS:STRING="${CMAKE_C_FLAGS} --target=x86_64-unknown-windows-msvc /GS- /Oy /Gw /Gy"^ + -DCMAKE_CXX_FLAGS:STRING="${CMAKE_CXX_FLAGS} --target=x86_64-unknown-windows-msvc /GS- /Oy /Gw /Gy"^ + -DCMAKE_EXE_LINKER_FLAGS:STRING="/INCREMENTAL:NO"^ + -DCMAKE_SHARED_LINKER_FLAGS:STRING="/INCREMENTAL:NO"^ + -DCMAKE_Swift_COMPILER_TARGET:STRING=x86_64-unknown-windows-msvc^ + -DCMAKE_Swift_FLAGS:STRING="-resource-dir \"%install_directory%\lib\swift\""^ + -DCMAKE_Swift_LINK_FLAGS:STRING="-resource-dir \"%install_directory%\lib\swift\""^ + -S "%source_root%\swift-corelibs-libdispatch" %exitOnError% + +cmake --build "%build_root%\swift-corelibs-libdispatch" %exitOnError% +cmake --build "%build_root%\swift-corelibs-libdispatch" --target install %exitOnError% + +goto :eof +endlocal + + +:test_libdispatch +:: Tests libdispatch C interface +setlocal enableextensions enabledelayedexpansion + +cmake --build "%build_root%\swift-corelibs-libdispatch" --target ExperimentalTest %exitOnError% + +goto :eof +endlocal + + +:end diff --git a/utils/build_swift/build_swift/driver_arguments.py b/utils/build_swift/build_swift/driver_arguments.py index ae6403e0eaf0c..52426d85824d2 100644 --- a/utils/build_swift/build_swift/driver_arguments.py +++ b/utils/build_swift/build_swift/driver_arguments.py @@ -564,16 +564,16 @@ def create_argument_parser(): # ------------------------------------------------------------------------- in_group('Options to select projects') - option('--infer', store_true('infer_dependencies'), + option('--infer', toggle_true('infer_dependencies'), help='Infer any downstream dependencies from enabled projects') - option(['-l', '--lldb'], store_true('build_lldb'), + option(['-l', '--lldb'], toggle_true('build_lldb'), help='build LLDB') - option(['-b', '--llbuild'], store_true('build_llbuild'), + option(['-b', '--llbuild'], toggle_true('build_llbuild'), help='build llbuild') - option(['--libcxx'], store_true('build_libcxx'), + option(['--libcxx'], toggle_true('build_libcxx'), help='build libcxx') option(['-p', '--swiftpm'], toggle_true('build_swiftpm'), @@ -582,16 +582,16 @@ def create_argument_parser(): option(['--install-swiftpm'], toggle_true('install_swiftpm'), help='install swiftpm') - option(['--swiftsyntax'], store_true('build_swiftsyntax'), + option(['--swiftsyntax'], toggle_true('build_swiftsyntax'), help='build swiftSyntax') - option(['--skstresstester'], store_true('build_skstresstester'), + option(['--skstresstester'], toggle_true('build_skstresstester'), help='build the SourceKit stress tester') - option(['--swiftformat'], store_true('build_swiftformat'), + option(['--swiftformat'], toggle_true('build_swiftformat'), help='build swift-format') - option(['--swiftevolve'], store_true('build_swiftevolve'), + option(['--swiftevolve'], toggle_true('build_swiftevolve'), help='build the swift-evolve tool') option(['--swift-driver'], toggle_true('build_swift_driver'), @@ -645,13 +645,13 @@ def create_argument_parser(): option('--playgroundsupport', toggle_true('build_playgroundsupport'), help='build PlaygroundSupport') option('--install-playgroundsupport', - store_true('install_playgroundsupport'), + toggle_true('install_playgroundsupport'), help='install playground support') option('--build-ninja', toggle_true, help='build the Ninja tool') - option(['--build-libparser-only'], store_true('build_libparser_only'), + option(['--build-libparser-only'], toggle_true('build_libparser_only'), help='build only libParser for SwiftSyntax') option('--skip-build-clang-tools-extra', @@ -695,6 +695,11 @@ def create_argument_parser(): help='build the Release variant of everything (default is ' '%(default)s)') + option(['--min-size-release'], store('build_variant'), + const='MinSizeRel', + help='build the MinSizeRel variant of everything (default is ' + '%(default)s)') + # ------------------------------------------------------------------------- in_group('Override build variant for a specific project') @@ -1021,6 +1026,11 @@ def create_argument_parser(): help='skip testing Android device targets on the host machine (the ' 'phone itself)') + option('--skip-clean-swiftpm', toggle_false('clean_swiftpm'), + help='skip cleaning up swiftpm') + option('--skip-clean-swift-driver', toggle_false('clean_swift_driver'), + help='skip cleaning up Swift driver') + option('--skip-test-wasm', toggle_false('test_wasm'), help='skip testing all WebAssembly targets.') diff --git a/utils/build_swift/tests/expected_options.py b/utils/build_swift/tests/expected_options.py index bbcd8577d94b3..e0381cb842fc2 100644 --- a/utils/build_swift/tests/expected_options.py +++ b/utils/build_swift/tests/expected_options.py @@ -205,6 +205,8 @@ defaults.SWIFT_MAX_PARALLEL_LTO_LINK_JOBS, 'swift_user_visible_version': defaults.SWIFT_USER_VISIBLE_VERSION, 'symbols_package': None, + 'clean_swiftpm': True, + 'clean_swift_driver': True, 'test': None, 'test_android': False, 'test_android_host': False, @@ -412,6 +414,8 @@ class BuildScriptImplOption(_BaseOption): SetOption('--release', dest='build_variant', value='Release'), SetOption('--release-debuginfo', dest='build_variant', value='RelWithDebInfo'), + SetOption('--min-size-release', + dest='build_variant', value='MinSizeRel'), SetOption('--xcode', dest='cmake_generator', value='Xcode'), SetOption('-R', dest='build_variant', value='Release'), SetOption('-d', dest='build_variant', value='Debug'), @@ -565,6 +569,8 @@ class BuildScriptImplOption(_BaseOption): dest='build_watchos_device'), DisableOption('--skip-build-watchos-simulator', dest='build_watchos_simulator'), + DisableOption('--skip-clean-swiftpm', dest='clean_swiftpm'), + DisableOption('--skip-clean-swift-driver', dest='clean_swift_driver'), DisableOption('--skip-test-android', dest='test_android'), DisableOption('--skip-test-android-host', dest='test_android_host'), DisableOption('--skip-test-cygwin', dest='test_cygwin'), diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py index 8b442d8c307a1..59801e8e98244 100644 --- a/utils/gyb_syntax_support/ExprNodes.py +++ b/utils/gyb_syntax_support/ExprNodes.py @@ -49,7 +49,9 @@ # await foo() Node('AwaitExpr', kind='Expr', children=[ - Child('AwaitKeyword', kind='AwaitToken'), + Child('AwaitKeyword', kind='IdentifierToken', + classification='Keyword', + text_choices=['await']), Child('Expression', kind='Expr'), ]), @@ -390,6 +392,9 @@ Child('SimpleInput', kind='ClosureParamList'), Child('Input', kind='ParameterClause'), ]), + Child('AsyncKeyword', kind='IdentifierToken', + classification='Keyword', + text_choices=['async'], is_optional=True), Child('ThrowsTok', kind='ThrowsToken', is_optional=True), Child('Output', kind='ReturnClause', is_optional=True), Child('InTok', kind='InToken'), diff --git a/utils/gyb_syntax_support/Token.py b/utils/gyb_syntax_support/Token.py index 5abe6794e61d7..6a2eb85ac5318 100644 --- a/utils/gyb_syntax_support/Token.py +++ b/utils/gyb_syntax_support/Token.py @@ -196,7 +196,6 @@ def macro_name(self): ExprKeyword('True', 'true', serialization_code=51), ExprKeyword('Try', 'try', serialization_code=52), ExprKeyword('Throws', 'throws', serialization_code=53), - ExprKeyword('Await', '__await', serialization_code=123), Keyword('__FILE__', '__FILE__', serialization_code=54), Keyword('__LINE__', '__LINE__', serialization_code=55), diff --git a/utils/parser-lib/darwin-extract-symbols b/utils/parser-lib/darwin-extract-symbols index a4ee1e4c61e96..1e10f61c7c11b 100755 --- a/utils/parser-lib/darwin-extract-symbols +++ b/utils/parser-lib/darwin-extract-symbols @@ -46,11 +46,12 @@ function xcrun_find_tool() { # Run dsymutil on executables and shared libraries. # # Exclude shell scripts. +# Run sequentially -- dsymutil is multithreaded and can be memory intensive (cd "${INSTALL_SYMROOT}" && find ./"${INSTALL_PREFIX}" -perm -0111 -type f -print | \ grep -v crashlog.py | \ grep -v symbolication.py | \ - xargs -n 1 -P ${BUILD_JOBS} $(xcrun_find_tool dsymutil)) + xargs -n 1 -P 1 $(xcrun_find_tool dsymutil)) # Strip executables, shared libraries and static libraries in INSTALL_DIR. find "${INSTALL_DIR}${INSTALL_PREFIX}/" \ diff --git a/utils/recursive-lipo b/utils/recursive-lipo index 056b5f3576ef6..df3d302e651fd 100755 --- a/utils/recursive-lipo +++ b/utils/recursive-lipo @@ -63,6 +63,9 @@ def merge_lipo_files(src_root_dirs, file_list, copy_verbatim_subpaths, if all([os.path.islink(item) for item in file_paths]): # It's a symlink in all found instances, copy the link. print("-- Creating symlink %s" % dest_path) + # Remove symlink if it already exists + if os.path.islink(dest_path): + os.remove(dest_path) os.symlink(os.readlink(file_paths[0]), dest_path) elif all([os.path.isdir(item) for item in file_paths]): # It's a subdir in all found instances. diff --git a/utils/sil-mode.el b/utils/sil-mode.el index fe29c99d9b58b..59cc44ba0c4c7 100644 --- a/utils/sil-mode.el +++ b/utils/sil-mode.el @@ -259,6 +259,7 @@ ;; *NOTE* viewcfg must be in the $PATH and .dot files should be associated with ;; the graphviz app. (defvar sil-mode-viewcfg-program-name "viewcfg") +(defvar sil-mode-viewcfg-renderer "dot") (defvar sil-mode-viewcfg-buffer-name "*viewcfg*") (defcustom sil-mode-viewcfg-command-default "viewcfg" @@ -281,7 +282,8 @@ (process-connection-type nil)) (let ((p (start-process sil-mode-viewcfg-program-name sil-mode-viewcfg-buffer-name - sil-mode-viewcfg-command))) + sil-mode-viewcfg-command + (concat "--renderer=" sil-mode-viewcfg-renderer)))) (process-send-region p brace-start brace-end) (process-send-eof p))))) diff --git a/utils/swift-api-dump.py b/utils/swift-api-dump.py index 9022e9c89d5b2..d44b33ae19839 100755 --- a/utils/swift-api-dump.py +++ b/utils/swift-api-dump.py @@ -102,6 +102,8 @@ def create_parser(): parser.add_argument('--enable-infer-import-as-member', action='store_true', help='Infer when a global could be imported as a ' + 'member.') + parser.add_argument('--enable-experimental-concurrency', action='store_true', + help='Enable experimental concurrency model.') parser.add_argument('-swift-version', metavar='N', help='the Swift version to use') parser.add_argument('-show-overlay', action='store_true', @@ -328,6 +330,8 @@ def main(): extra_args = ['-skip-imports'] if args.enable_infer_import_as_member: extra_args = extra_args + ['-enable-infer-import-as-member'] + if args.enable_experimental_concurrency: + extra_args = extra_args + ['-enable-experimental-concurrency'] if args.swift_version: extra_args = extra_args + ['-swift-version', '%s' % args.swift_version] diff --git a/utils/swift_build_support/swift_build_support/cmake.py b/utils/swift_build_support/swift_build_support/cmake.py index 85a97dfa747e2..5ef74e0cf5ee4 100644 --- a/utils/swift_build_support/swift_build_support/cmake.py +++ b/utils/swift_build_support/swift_build_support/cmake.py @@ -18,7 +18,6 @@ from __future__ import absolute_import, unicode_literals import os -import platform import re from numbers import Number @@ -256,9 +255,6 @@ def build_cmake(self, source_root, build_root): # the source and build the source if necessary. Returns the path to the # cmake binary. def check_cmake_version(self, source_root, build_root): - if platform.system() != 'Linux': - return - cmake_source_dir = os.path.join(source_root, 'cmake') # If the source is not checked out then don't attempt to build cmake. if not os.path.isdir(cmake_source_dir): diff --git a/utils/swift_build_support/swift_build_support/products/ninja.py b/utils/swift_build_support/swift_build_support/products/ninja.py index 53ebb15c6e32e..d133c22fa9ded 100644 --- a/utils/swift_build_support/swift_build_support/products/ninja.py +++ b/utils/swift_build_support/swift_build_support/products/ninja.py @@ -63,8 +63,8 @@ def build(self): "-isysroot {sysroot} -mmacosx-version-min={osx_version}" ).format(sysroot=sysroot, osx_version=osx_version_min), "LDFLAGS": ( - "-mmacosx-version-min={osx_version}" - ).format(osx_version=osx_version_min), + "-isysroot {sysroot} -mmacosx-version-min={osx_version}" + ).format(sysroot=sysroot, osx_version=osx_version_min), } elif self.toolchain.cxx: env = { diff --git a/utils/swift_build_support/swift_build_support/products/product.py b/utils/swift_build_support/swift_build_support/products/product.py index ed4c944bc008e..5ccfa48283e88 100644 --- a/utils/swift_build_support/swift_build_support/products/product.py +++ b/utils/swift_build_support/swift_build_support/products/product.py @@ -78,6 +78,20 @@ def get_dependencies(cls): """Return a list of products that this product depends upon""" raise NotImplementedError + def should_clean(self, host_target): + """should_clean() -> Bool + + Whether or not this product should be cleaned before being built + """ + return False + + def clean(self, host_target): + """clean() -> void + + Perform the clean, for a non-build-script-impl product. + """ + raise NotImplementedError + def should_build(self, host_target): """should_build() -> Bool diff --git a/utils/swift_build_support/swift_build_support/products/swiftdriver.py b/utils/swift_build_support/swift_build_support/products/swiftdriver.py index 52ca78d4c00a9..5eca23c888086 100644 --- a/utils/swift_build_support/swift_build_support/products/swiftdriver.py +++ b/utils/swift_build_support/swift_build_support/products/swiftdriver.py @@ -47,6 +47,13 @@ def get_dependencies(cls): xctest.XCTest, llbuild.LLBuild] + def should_clean(self, host_target): + return self.args.clean_swift_driver + + def clean(self, host_target): + indexstoredb.run_build_script_helper( + 'clean', host_target, self, self.args) + def build(self, host_target): indexstoredb.run_build_script_helper( 'build', host_target, self, self.args) diff --git a/utils/swift_build_support/swift_build_support/products/swiftpm.py b/utils/swift_build_support/swift_build_support/products/swiftpm.py index 48c18256629b5..412dc52814f5c 100644 --- a/utils/swift_build_support/swift_build_support/products/swiftpm.py +++ b/utils/swift_build_support/swift_build_support/products/swiftpm.py @@ -51,6 +51,11 @@ def run_bootstrap_script(self, action, host_target, additional_params=[]): helper_cmd = [script_path, action] + if action == 'clean': + helper_cmd += ["--build-dir", self.build_dir] + shell.call(helper_cmd) + return + if self.is_release(): helper_cmd.append("--release") @@ -94,6 +99,12 @@ def should_test(self, host_target): def test(self, host_target): self.run_bootstrap_script('test', host_target) + def should_clean(self, host_target): + return self.args.clean_swiftpm + + def clean(self, host_target): + self.run_bootstrap_script('clean', host_target) + def should_install(self, host_target): return self.args.install_swiftpm diff --git a/utils/swift_build_support/swift_build_support/targets.py b/utils/swift_build_support/swift_build_support/targets.py index 64ed0485edabb..4438b83157389 100644 --- a/utils/swift_build_support/swift_build_support/targets.py +++ b/utils/swift_build_support/swift_build_support/targets.py @@ -179,6 +179,12 @@ class StdlibDeploymentTarget(object): sdk_name="WATCHOS_SIMULATOR", is_simulator=True) + # A platform that's not tied to any particular OS, and it meant to be used + # to build the stdlib as standalone and/or statically linked. + Freestanding = Platform("freestanding", + archs=["i386", "x86_64", "armv7", "armv7s", "armv7k", + "arm64", "arm64e"]) + Linux = Platform("linux", archs=[ "x86_64", "i686", @@ -209,6 +215,7 @@ class StdlibDeploymentTarget(object): iOS, iOSSimulator, AppleTV, AppleTVSimulator, AppleWatch, AppleWatchSimulator, + Freestanding, Linux, FreeBSD, OpenBSD, diff --git a/utils/swift_build_support/tests/products/test_ninja.py b/utils/swift_build_support/tests/products/test_ninja.py index 5a3c919732d11..3eb26c4a838a0 100644 --- a/utils/swift_build_support/tests/products/test_ninja.py +++ b/utils/swift_build_support/tests/products/test_ninja.py @@ -101,7 +101,7 @@ def test_build(self): "env " "'CFLAGS=-isysroot {sysroot} -mmacosx-version-min=10.9' " "CXX={cxx} " - "LDFLAGS=-mmacosx-version-min=10.9 " + "'LDFLAGS=-isysroot {sysroot} -mmacosx-version-min=10.9' " ).format( cxx=self.toolchain.cxx, sysroot=xcrun.sdk_path('macosx') diff --git a/utils/update_checkout/update-checkout-config.json b/utils/update_checkout/update-checkout-config.json index 58f6c32b881c9..b3ddc61e64916 100644 --- a/utils/update_checkout/update-checkout-config.json +++ b/utils/update_checkout/update-checkout-config.json @@ -62,7 +62,7 @@ "llbuild": "master", "swift-tools-support-core": "master", "swiftpm": "swiftwasm", - "swift-argument-parser": "0.0.6", + "swift-argument-parser": "0.3.0", "swift-driver": "master", "swift-syntax": "master", "swift-stress-tester": "master", @@ -113,7 +113,7 @@ "llbuild": "master", "swift-tools-support-core": "master", "swiftpm": "master", - "swift-argument-parser": "0.0.6", + "swift-argument-parser": "0.3.0", "swift-driver": "master", "swift-syntax": "master", "swift-stress-tester": "master", @@ -143,7 +143,7 @@ "llbuild": "master", "swift-tools-support-core": "master", "swiftpm": "master", - "swift-argument-parser": "0.0.6", + "swift-argument-parser": "0.3.0", "swift-driver": "master", "swift-syntax": "master", "swift-stress-tester": "master", @@ -366,6 +366,8 @@ "llbuild": "master", "swift-tools-support-core": "master", "swiftpm": "master", + "swift-argument-parser": "0.3.0", + "swift-driver": "master", "swift-syntax": "master", "swift-stress-tester": "master", "swift-corelibs-xctest": "master", @@ -375,6 +377,7 @@ "swift-xcode-playground-support": "master", "ninja": "release", "icu": "release-65-1", + "yams": "3.0.1", "cmake": "v3.16.5", "indexstore-db": "master", "sourcekit-lsp": "master", diff --git a/utils/webassembly/build-foundation.sh b/utils/webassembly/build-foundation.sh index 6d15e0ba5b216..eeb18fcc9920d 100755 --- a/utils/webassembly/build-foundation.sh +++ b/utils/webassembly/build-foundation.sh @@ -28,6 +28,10 @@ ninja -v install # On Linux though there's no system CoreFoundation, its headers have to be shipped # in the installable archive and serve for both host and target. if [[ "$(uname)" == "Darwin" ]]; then - mv $DESTINATION_TOOLCHAIN/usr/lib/swift/CoreFoundation \ + mv $DESTINATION_TOOLCHAIN/usr/lib/swift_static/CoreFoundation \ $DESTINATION_TOOLCHAIN/usr/lib/swift/wasi/wasm32/CoreFoundation -fi \ No newline at end of file +fi + +# .swiftdoc and .swiftmodule files should live in `swift`, not in `swift_static` +mv $DESTINATION_TOOLCHAIN/usr/lib/swift_static/wasi/wasm32/Foundation.swift* \ + $DESTINATION_TOOLCHAIN/usr/lib/swift/wasi/wasm32 \ No newline at end of file diff --git a/validation-test/Casting/BoxingCasts.swift.gyb b/validation-test/Casting/BoxingCasts.swift.gyb new file mode 100644 index 0000000000000..7ee19e67a85fb --- /dev/null +++ b/validation-test/Casting/BoxingCasts.swift.gyb @@ -0,0 +1,264 @@ +// BoxingCasts.swift - Tests for boxing/unboxing casts +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 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 +// +// ----------------------------------------------------------------------------- +/// +/// Contains tests for existential, optional, and other casts that box/unbox values. +/// +// ----------------------------------------------------------------------------- +// RUN: %empty-directory(%t) +// +// RUN: %gyb %s -o %t/BoxingCasts.swift +// RUN: %line-directive %t/BoxingCasts.swift -- %target-build-swift -g -module-name a -swift-version 5 -Onone %t/BoxingCasts.swift -o %t/a.swift5.Onone.out +// RUN: %target-codesign %t/a.swift5.Onone.out +// RUN: %line-directive %t/BoxingCasts.swift -- %target-run %t/a.swift5.Onone.out +// +// Note: The RUN directives above override the default test optimizations. +// This test is deliberately run non-optimized in order to verify the +// behavior of runtime methods that may not be called for optimized casts. +// +// XXX FIXME XXX TODO XXX _Also_ build this with optimizations in order to +// verify compiler behaviors. +// +// REQUIRES: executable_test + +import StdlibUnittest +#if _runtime(_ObjC) +import Foundation +#endif + +fileprivate func runtimeCast (_ x: From, to: To.Type) -> To? { + return x as? To +} + +fileprivate func optional(_ x: T) -> Optional { + return runtimeCast(x, to: Optional.self)! +} + +fileprivate protocol FilePrivateProtocol {} +internal protocol InternalProtocol {} +public protocol PublicProtocol {} +protocol UnimplementedProtocol {} + +fileprivate enum EmptyEnum: FilePrivateProtocol, InternalProtocol, PublicProtocol { } + +fileprivate enum SingleCaseEnum: FilePrivateProtocol, InternalProtocol, PublicProtocol { +case case0 + init() {self = .case0} +} + +fileprivate enum TrivialPayloadEnum: FilePrivateProtocol, InternalProtocol, PublicProtocol { +case payloadCase(Int) + init() {self = .payloadCase(42)} +} + +extension TrivialPayloadEnum: Hashable {} + +fileprivate enum MultiPayloadEnum: FilePrivateProtocol, InternalProtocol, PublicProtocol { +case case0(String) +case case1(Int) + init() {self = .case1(42)} +} + +extension MultiPayloadEnum: Hashable {} + +fileprivate class ClassInt: FilePrivateProtocol, InternalProtocol, PublicProtocol { + public var value: Int + private var tracker = LifetimeTracked(77) + init(_ v: Int = 42) {value = v} +} + +extension ClassInt: Equatable, Hashable { + static func ==(left: ClassInt, right: ClassInt) -> Bool {left.value == right.value} + func hash(into hasher: inout Hasher) { value.hash(into: &hasher) } +} + +fileprivate struct StructInt: FilePrivateProtocol, InternalProtocol, PublicProtocol { + public var value: Int + private var tracker = LifetimeTracked(77) + init(_ v: Int = 42) { value = v} +} + +extension StructInt: Hashable, Equatable { } + +#if _runtime(_ObjC) +fileprivate class OCClassInt: NSObject, FilePrivateProtocol, InternalProtocol, PublicProtocol { + public var value: Int + private var tracker = LifetimeTracked(77) + init(_ v: Int = 42) { value = v} +} +#endif + +let BoxingCasts = TestSuite("BoxingCasts") + +%{ +import random +# The test body goes into a named function and the test case just invokes that +# function by name. This makes debugging easier, since it's easier to set break +# points on named functions than on arbitrary closures. +# The function names are included in the test name +# for ease of reference. +testNumber = 0 +def testFunctionName(): + return "test{number}".format(number=testNumber) +def nextTestNumber(): + global testNumber + testNumber += 1 + +# Type used for intermediate casts. The base object gets +# cast to one or more of these before the final test. +class Box: + def __init__(self, name, typeName=None, cast=None): + self.name = name + self.typeName = typeName or name + self.cast_template = cast or "runtimeCast({expr}, to: {typeName}.self)!" + def cast_oper(self, expr): + return self.cast_template.format(expr=expr, typeName=self.typeName) + +anyHashableBox = Box(name="AnyHashable") +all_boxes = [ + Box(name="Any", typeName="Any"), + Box(name="AnyStatic", cast="({expr} as Any)"), + Box(name="AnyObject"), + Box(name="SwiftValueBox", cast="_bridgeAnythingToObjectiveC({expr})"), + Box(name="Optional", cast="optional({expr})") +] +protocol_boxes = [ + Box(name="PublicProtocol"), +# Box(name="FilePrivateProtocol"), # Blocked by SR-2620 aka rdar://28281488 + Box(name="InternalProtocol"), +] + +# Describes a base object that will be subject to a variety of casts +default_protocols = [ + "PublicProtocol", + "InternalProtocol", + # "FilePrivateProtocol" # Blocked by SR-2620 aka rdar://28281488 +] + +class Contents: + def __init__(self, name, constructor=None, extra_targets=[], hashable=True, roundtrips=True, protocols=default_protocols, objc_only=False): + self.name = name + self.constructor = constructor or "{name}()".format(name=name) + self.objc_only = objc_only + + self.targets = ["Any"] + self.targets.extend(protocols) + self.targets.extend(extra_targets) + if roundtrips: + self.targets.append(self.name) + + self.boxes = [] + self.boxes.extend(all_boxes) + self.boxes.extend([Box(name=n) for n in protocols]) + if hashable: + self.boxes.append(anyHashableBox) + +contents = [ + Contents(name="StructInt", + # extra_targets=["StructInt?"], + ), + Contents(name="StructInt?", + constructor="Optional.some(StructInt())", + extra_targets=["StructInt"], + roundtrips=False, # Compiler bug rejects roundtrip cast T? => Any => T? + ), + Contents(name="ClassInt"), + Contents(name="OCClassInt", objc_only=True), + Contents(name="SingleCaseEnum"), + Contents(name="TrivialPayloadEnum"), + Contents(name="TrivialPayloadEnum"), + Contents(name="MultiPayloadEnum"), + Contents(name="StructInt.Type", + constructor="StructInt.self", + hashable=False, + protocols=[], + ), + Contents(name="StructInt.Type?", + constructor="Optional.some(StructInt.self)", + hashable=False, + protocols=[], + extra_targets=["StructInt.Type"], + roundtrips=False, # Compiler bug rejects roundtrip cast T? => Any => T? + ), + Contents(name="PublicProtocol.Protocol", + constructor="PublicProtocol.self", + hashable=False, + protocols=[], + ), +] + +# Code below generates a separate test case for each combination of content, +# target type, and one or more box/intermediate types. +}% + +% for content in contents: +% if content.objc_only: +#if _runtime(_ObjC) +% end +% for target in content.targets: +% for box in content.boxes: +% nextTestNumber() +BoxingCasts.test("${testFunctionName()}(): Casting ${box.name}(${content.name}) to ${target}") { + // TODO: Selectively enable/disable cases that work with earlier stdlib + if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) { + ${testFunctionName()}() + } +} +func ${testFunctionName()}() { + let a = ${content.constructor} + let b = ${box.cast_oper("a")} +% # // Skip trivial cast from T? to T +% if not (content.name == target and box.name == "Optional"): +% # // Skip trivial cast from protocol box to protocol +% if box.name != target: +% # // Skip trivial cast from T? => P +% if not (target.endswith("Protocol") and box.name == "Optional"): + let c = /* ${box.name}(${content.name})) */ b as? ${target} + expectNotNil(c) +% end +% end +% end + let d = runtimeCast(/* ${box.name}(${content.name}) */ b, to: ${target}.self) + expectNotNil(d) +} + +% for innerBox in [random.choice(content.boxes)]: +% nextTestNumber() +BoxingCasts.test("${testFunctionName()}(): Casting ${box.name}(${innerBox.name}(${content.name})) to ${target}") { + // TODO: Selectively enable/disable cases that work with earlier stdlib + if #available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) { + ${testFunctionName()}() + } +} +func ${testFunctionName()}() { + let a = ${content.constructor} + let b = ${innerBox.cast_oper("a")} + let c = ${box.cast_oper("b")} +% # // Skip trivial cast from T? to T +% if not (innerBox.name == target and box.name == "Optional"): +% # // Skip trivial cast from protocol box to protocol +% if box.name != target: + let d = /* ${box.name}(${innerBox.name}(${content.name})) */ c as? ${target} + expectNotNil(d) +% end +% end + let e = runtimeCast(/* ${box.name}(${innerBox.name}(${content.name})) */ c, to: ${target}.self) + expectNotNil(e) +} +% end +% end +% end +% if content.objc_only: +#endif +% end +% end + +runAllTests() diff --git a/validation-test/IDE/crashers_2_fixed/rdar67102611.swift b/validation-test/IDE/crashers_2_fixed/rdar67102611.swift new file mode 100644 index 0000000000000..c5069e7550cbb --- /dev/null +++ b/validation-test/IDE/crashers_2_fixed/rdar67102611.swift @@ -0,0 +1,6 @@ +// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s > /dev/null + +for x in "foo" { + if x.#^A^# { + } +} diff --git a/validation-test/ParseableInterface/verify_all_overlays.py b/validation-test/ParseableInterface/verify_all_overlays.py index 631ddd0666a92..e1ce62e248f54 100755 --- a/validation-test/ParseableInterface/verify_all_overlays.py +++ b/validation-test/ParseableInterface/verify_all_overlays.py @@ -12,7 +12,7 @@ # RUN: test ! -e %t/failures.txt || \ # RUN: diff %t/filter.txt %t/failures.txt -# REQUIRES: nonexecutable_test +# REQUIRES: nonexecutable_test, no_asan # Expected failures by platform # ----------------------------- diff --git a/validation-test/Runtime/weak-reference-racetests.swift b/validation-test/Runtime/weak-reference-racetests.swift index 1d759c12c60ff..23fc108b6f9f0 100644 --- a/validation-test/Runtime/weak-reference-racetests.swift +++ b/validation-test/Runtime/weak-reference-racetests.swift @@ -1,7 +1,7 @@ // RUN: %target-run-simple-swift // REQUIRES: executable_test // REQUIRES: stress_test -// UNSUPPORTED: nonatomic_rc +// UNSUPPORTED: single_threaded_runtime import StdlibUnittest diff --git a/validation-test/SILOptimizer/large_string_array.swift.gyb b/validation-test/SILOptimizer/large_string_array.swift.gyb index 91280bd424040..6b6093f78552b 100644 --- a/validation-test/SILOptimizer/large_string_array.swift.gyb +++ b/validation-test/SILOptimizer/large_string_array.swift.gyb @@ -12,12 +12,10 @@ // REQUIRES: long_test // REQUIRES: CPU=arm64 || CPU=x86_64 -// REQUIRES: rdar66807959 - // Check if the optimizer can optimize the whole array into a statically // initialized global -// CHECK: sil_global private @globalinit_{{.*}} : $_ContiguousArrayStorage = { +// CHECK: sil_global private @{{.*9str_array.*}}WZTv_ : $_ContiguousArrayStorage = { // CHECK: %initval = object $_ContiguousArrayStorage public let str_array: [String] = [ diff --git a/validation-test/SILOptimizer/string_switch.swift b/validation-test/SILOptimizer/string_switch.swift index b30c80b7cc48e..555c1d972847c 100644 --- a/validation-test/SILOptimizer/string_switch.swift +++ b/validation-test/SILOptimizer/string_switch.swift @@ -4,7 +4,7 @@ // REQUIRES: swift_stdlib_no_asserts,optimized_stdlib // REQUIRES: stress_test // REQUIRES: executable_test -// UNSUPPORTED: nonatomic_rc +// UNSUPPORTED: single_threaded_runtime import StdlibUnittest diff --git a/validation-test/StdlibUnittest/AtomicInt.swift b/validation-test/StdlibUnittest/AtomicInt.swift index 00bf5d1c0f8c2..9bc3e8b3f1f8a 100644 --- a/validation-test/StdlibUnittest/AtomicInt.swift +++ b/validation-test/StdlibUnittest/AtomicInt.swift @@ -4,7 +4,7 @@ // RUN: %target-run %t.out // REQUIRES: executable_test // REQUIRES: stress_test -// UNSUPPORTED: nonatomic_rc +// UNSUPPORTED: single_threaded_runtime import SwiftPrivate import StdlibUnittest diff --git a/validation-test/StdlibUnittest/RaceTest.swift b/validation-test/StdlibUnittest/RaceTest.swift index b3c296036f371..d0f1efc0ef750 100644 --- a/validation-test/StdlibUnittest/RaceTest.swift +++ b/validation-test/StdlibUnittest/RaceTest.swift @@ -2,7 +2,7 @@ // RUN: %target-build-swift -Xfrontend -disable-access-control -module-name a %s -o %t.out // RUN: %target-run %t.out | %FileCheck %s // REQUIRES: stress_test -// UNSUPPORTED: nonatomic_rc +// UNSUPPORTED: single_threaded_runtime import SwiftPrivate import StdlibUnittest diff --git a/validation-test/compiler_crashers_2_fixed/rdar62268062.swift b/validation-test/compiler_crashers_2_fixed/rdar62268062.swift new file mode 100644 index 0000000000000..21b59a843ff98 --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/rdar62268062.swift @@ -0,0 +1,41 @@ +// RUN: %target-swift-frontend -emit-ir %s + +public protocol HorseSaddle {} +public enum EnglishSaddle : HorseSaddle {} + +public enum WesternSaddle : HorseSaddle {} + +public protocol Horse { + associatedtype Body : Horse + + associatedtype Saddle: HorseSaddle + + var body: Body { get } +} + +extension Horse { + typealias Saddle = Body.Saddle +} + +public struct DraftHorse : Pony { + public typealias Saddle = EnglishSaddle + public typealias Body = Never + var contents: T +} + +// MARK: - Implementation detail + +extension Never : Horse { + public typealias Saddle = EnglishSaddle + public typealias Body = Never + + public var body: Never { + switch self {} + } +} + +protocol Pony : Horse where Body == Never {} +extension Pony { + public var body: Never { fatalError() } +} + diff --git a/validation-test/compiler_crashers_2_fixed/rdar65272763.swift b/validation-test/compiler_crashers_2_fixed/rdar65272763.swift new file mode 100644 index 0000000000000..f3233a7afd131 --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/rdar65272763.swift @@ -0,0 +1,21 @@ +// RUN: %target-swift-frontend -emit-ir %s + +public struct S1 {} +public extension S1 where T1 == Int { + public struct S2 { + let value: T2 + + public init(value: T2) { + self.value = value + } + } + + public init(s: [S2]) { + self.init() + + s.forEach { _ in + + } + } +} + diff --git a/validation-test/compiler_crashers_2_fixed/rdar67239650.swift b/validation-test/compiler_crashers_2_fixed/rdar67239650.swift new file mode 100644 index 0000000000000..5ec036b8b61cf --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/rdar67239650.swift @@ -0,0 +1,24 @@ +// RUN: %target-swift-frontend -typecheck %s + +@_functionBuilder +struct SillyBuilder { + static func buildBlock() -> () {} +} + +struct SillyStruct { + init(@SillyBuilder _: () -> ()) {} +} + +struct UsesSillyStruct { + var x: Int = 0 + + func foo() { + SillyStruct { + let fn = { + if true { + _ = x + } + } + } + } +} diff --git a/validation-test/compiler_crashers_2_fixed/rdar67259506.swift b/validation-test/compiler_crashers_2_fixed/rdar67259506.swift new file mode 100644 index 0000000000000..4f3360980adc4 --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/rdar67259506.swift @@ -0,0 +1,29 @@ +// RUN: %target-swift-frontend -emit-ir %s + +public func foo(_: T, _: S.A) {} + +public protocol P { + associatedtype A + + func foo() -> A +} + +public protocol Q { + associatedtype A + + func bar() -> A +} + +public struct S {} + +extension S : P where T : P { + public func foo() -> Int { + return 0 + } +} + +extension S : Q where T : Q { + public func bar() -> Int { + return 0 + } +} diff --git a/validation-test/compiler_crashers_2_fixed/sr12327.swift b/validation-test/compiler_crashers_2_fixed/sr12327.swift new file mode 100644 index 0000000000000..33a5140a92d27 --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/sr12327.swift @@ -0,0 +1,42 @@ +// RUN: %target-swift-frontend -emit-ir -O %s + +protocol A { + associatedtype Foo // Does not crash if renamed +} + +protocol B { + associatedtype Foo // Does not crash if renamed + var aFoo: Foo { get } +} + +public struct Wrapper { + let wrapped: T +} + +// Removing this extension or combining it with the next one prevents the crash +extension Wrapper: A where T: A { + typealias Foo = Wrapper +} + +extension Wrapper: B where T: B { + var aFoo: Wrapper { + return .init(wrapped: wrapped.aFoo) + } +} + +public struct Model: B { + public struct Foo {} + + public var aFoo: Foo { + return Foo() + } +} + +// Attempting to specialize this method for Wrapper crashes the compiler +func fooString(body: Body) -> String { + return "\(body.aFoo)" +} + +public func foo(_ command: Wrapper) -> String { + return fooString(body: command) +} diff --git a/validation-test/compiler_crashers_2_fixed/sr12691.swift b/validation-test/compiler_crashers_2_fixed/sr12691.swift new file mode 100644 index 0000000000000..33c98979944fd --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/sr12691.swift @@ -0,0 +1,23 @@ +// RUN: not %target-swift-frontend -typecheck %s + +struct CountSteps1 : Collection { + init(count: Int) { self.count = count } + var count: Int + + var startIndex: Int { 0 } + var endIndex: Int { count } + func index(after i: Int) -> Int { + totalSteps += 1 + return i + 1 + } + subscript(i: Int) -> Int { return i } +} + +extension CountSteps1 + : RandomAccessCollection, BidirectionalCollection + where T : Equatable +{ + func index(_ i: Index, offsetBy d: Int) -> Index { + return i + d + } +} diff --git a/validation-test/compiler_crashers_2_fixed/sr13141.swift b/validation-test/compiler_crashers_2_fixed/sr13141.swift new file mode 100644 index 0000000000000..fe403d1ce6c1c --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/sr13141.swift @@ -0,0 +1,12 @@ +// RUN: %target-swift-frontend -emit-ir %s + +public protocol Book { + associatedtype Name +} +public protocol BookDecorator: Book where Name == DecoratedBook.Name { + associatedtype DecoratedBook: Book + associatedtype Name = DecoratedBook.Name +} +public class ConcreteBookDecorator: BookDecorator { + public typealias DecoratedBook = T +} diff --git a/validation-test/compiler_crashers_2_fixed/sr13461.swift b/validation-test/compiler_crashers_2_fixed/sr13461.swift new file mode 100644 index 0000000000000..b6bda64bdce53 --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/sr13461.swift @@ -0,0 +1,17 @@ +// RUN: %target-swift-frontend -disable-availability-checking -emit-ir -o /dev/null %s +// REQUIRES: asserts + +final class Klass { + static var current: Klass { + fatalError() + } +} +private struct Build { + let val: T + unowned let unownedBinding = Klass.current + unowned(unsafe) let unownedUnsafeBinding = Klass.current + weak var weakBinding = Klass.current +} +private func phase(_ val: T) -> Build { + return Build(val: val) +} diff --git a/validation-test/compiler_crashers_2_fixed/sr9199.swift b/validation-test/compiler_crashers_2_fixed/sr9199.swift index 422f46b5579ba..609bb9e4ad46c 100644 --- a/validation-test/compiler_crashers_2_fixed/sr9199.swift +++ b/validation-test/compiler_crashers_2_fixed/sr9199.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -emit-ir -o %t.ll %s +// RUN: not %target-swift-frontend -emit-ir %s // Just make sure we don't crash. @@ -54,4 +54,4 @@ extension Controller: WithReturnType { let controller = Controller() -controller.returnTheThing() \ No newline at end of file +controller.returnTheThing() diff --git a/validation-test/lit.site.cfg.in b/validation-test/lit.site.cfg.in index 12aaec7150e00..649281bef0df2 100644 --- a/validation-test/lit.site.cfg.in +++ b/validation-test/lit.site.cfg.in @@ -87,8 +87,8 @@ if "@SWIFT_OPTIMIZED@" == "TRUE": if "@SWIFT_ENABLE_SOURCEKIT_TESTS@" == "TRUE": config.available_features.add('sourcekit') -if "@SWIFT_STDLIB_USE_NONATOMIC_RC@" == "TRUE": - config.available_features.add("nonatomic_rc") +if "@SWIFT_STDLIB_SINGLE_THREADED_RUNTIME@" == "TRUE": + config.available_features.add("single_threaded_runtime") if "@SWIFT_BUILT_STANDALONE@" == "TRUE": config.available_features.add('standalone_build') diff --git a/validation-test/stdlib/ArrayBridging.swift b/validation-test/stdlib/ArrayBridging.swift index 3fd92fa951dda..6c24bfe8dd0cf 100644 --- a/validation-test/stdlib/ArrayBridging.swift +++ b/validation-test/stdlib/ArrayBridging.swift @@ -9,7 +9,7 @@ // REQUIRES: objc_interop // REQUIRES: executable_test // REQUIRES: stress_test -// UNSUPPORTED: nonatomic_rc +// UNSUPPORTED: single_threaded_runtime import StdlibUnittest import Foundation diff --git a/validation-test/stdlib/CommandLine.swift b/validation-test/stdlib/CommandLine.swift index 610ec08eee400..a43defe135d37 100644 --- a/validation-test/stdlib/CommandLine.swift +++ b/validation-test/stdlib/CommandLine.swift @@ -8,7 +8,7 @@ // RUN: %target-run %t/CommandLineStressTest foo bar baz qux quux corge grault garply waldo fred plugh xyzzy and thud // REQUIRES: executable_test // REQUIRES: stress_test -// UNSUPPORTED: nonatomic_rc +// UNSUPPORTED: single_threaded_runtime // This file is an empty stub to call into the command line stress test which // houses `main`. diff --git a/validation-test/stdlib/DictionaryBridging.swift b/validation-test/stdlib/DictionaryBridging.swift index 4a2d203e2ca79..eed83d32a67ec 100644 --- a/validation-test/stdlib/DictionaryBridging.swift +++ b/validation-test/stdlib/DictionaryBridging.swift @@ -8,7 +8,7 @@ // REQUIRES: stress_test // REQUIRES: objc_interop -// UNSUPPORTED: nonatomic_rc +// UNSUPPORTED: single_threaded_runtime import StdlibUnittest import Foundation diff --git a/validation-test/stdlib/ErrorProtocol.swift b/validation-test/stdlib/ErrorProtocol.swift index 5e8a8b7862d38..6b2cf70ef7838 100644 --- a/validation-test/stdlib/ErrorProtocol.swift +++ b/validation-test/stdlib/ErrorProtocol.swift @@ -2,7 +2,7 @@ // REQUIRES: executable_test // REQUIRES: stress_test // REQUIRES: objc_interop -// UNSUPPORTED: nonatomic_rc +// UNSUPPORTED: single_threaded_runtime import SwiftPrivate import StdlibUnittest