From 096f7f38c0841288499f0f800e0c0f093e071e34 Mon Sep 17 00:00:00 2001 From: Vlad Gorloff Date: Tue, 28 May 2019 23:26:13 +0200 Subject: [PATCH 001/112] Android Intel 32/64 bit (i.e. Android Simulator) support. --- cmake/modules/AddSwift.cmake | 4 ++++ cmake/modules/SwiftAndroidSupport.cmake | 4 ++++ cmake/modules/SwiftConfigureSDK.cmake | 20 +++++++++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 7b8ac7a995eba..c70e83ec49d1b 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -465,6 +465,10 @@ function(_add_variant_link_flags) set(android_libcxx_path "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a") elseif("${LFLAGS_ARCH}" MATCHES aarch64) set(android_libcxx_path "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/arm64-v8a") + elseif("${LFLAGS_ARCH}" MATCHES i686) + set(android_libcxx_path "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/x86") + elseif("${LFLAGS_ARCH}" MATCHES x86_64) + set(android_libcxx_path "${SWIFT_ANDROID_NDK_PATH}/sources/cxx-stl/llvm-libc++/libs/x86_64") else() message(SEND_ERROR "unknown architecture (${LFLAGS_ARCH}) for android") endif() diff --git a/cmake/modules/SwiftAndroidSupport.cmake b/cmake/modules/SwiftAndroidSupport.cmake index c6dcc783c6809..f2070c4ebf4dd 100644 --- a/cmake/modules/SwiftAndroidSupport.cmake +++ b/cmake/modules/SwiftAndroidSupport.cmake @@ -23,6 +23,10 @@ function(swift_android_lib_for_arch arch var) list(APPEND paths "${_prebuilt}/${_host}/lib/armv7-a") elseif(arch STREQUAL aarch64) list(APPEND paths "${_prebuilt}/${_host}/lib64") + elseif(arch STREQUAL i686) + list(APPEND paths "${_prebuilt}/${_host}/lib") + elseif(arch STREQUAL x86_64) + list(APPEND paths "${_prebuilt}/${_host}/lib64") else() message(SEND_ERROR "unknown architecture (${arch}) for android") endif() diff --git a/cmake/modules/SwiftConfigureSDK.cmake b/cmake/modules/SwiftConfigureSDK.cmake index f5d77456dd434..339a5d739c318 100644 --- a/cmake/modules/SwiftConfigureSDK.cmake +++ b/cmake/modules/SwiftConfigureSDK.cmake @@ -186,6 +186,16 @@ macro(configure_sdk_unix name architectures) set(SWIFT_SDK_ANDROID_ARCH_${arch}_ALT_SPELLING "aarch64") set(SWIFT_SDK_ANDROID_ARCH_${arch}_PATH "${SWIFT_ANDROID_NDK_PATH}/platforms/android-${SWIFT_ANDROID_API_LEVEL}/arch-arm64") set(SWIFT_SDK_ANDROID_ARCH_${arch}_TRIPLE "aarch64-unknown-linux-android") + elseif("${arch}" STREQUAL "i686") + set(SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_TRIPLE "i686-linux-android") + set(SWIFT_SDK_ANDROID_ARCH_${arch}_ALT_SPELLING "i686") + set(SWIFT_SDK_ANDROID_ARCH_${arch}_PATH "${SWIFT_ANDROID_NDK_PATH}/platforms/android-${SWIFT_ANDROID_API_LEVEL}/arch-x86") + set(SWIFT_SDK_ANDROID_ARCH_${arch}_TRIPLE "i686-unknown-linux-android") + elseif("${arch}" STREQUAL "x86_64") + set(SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_TRIPLE "x86_64-linux-android") + set(SWIFT_SDK_ANDROID_ARCH_${arch}_ALT_SPELLING "x86_64") + set(SWIFT_SDK_ANDROID_ARCH_${arch}_PATH "${SWIFT_ANDROID_NDK_PATH}/platforms/android-${SWIFT_ANDROID_API_LEVEL}/arch-x86_64") + set(SWIFT_SDK_ANDROID_ARCH_${arch}_TRIPLE "x86_64-unknown-linux-android") else() message(FATAL_ERROR "unknown arch for android SDK: ${arch}") endif() @@ -196,8 +206,16 @@ macro(configure_sdk_unix name architectures) elseif("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux") set(_swift_android_prebuilt_build "linux-x86_64") endif() - set(SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_PREBUILT_PATH + if("${arch}" STREQUAL "i686") + set(SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_PREBUILT_PATH + "${SWIFT_ANDROID_NDK_PATH}/toolchains/x86-${SWIFT_ANDROID_NDK_GCC_VERSION}/prebuilt/${_swift_android_prebuilt_build}") + elseif("${arch}" STREQUAL "x86_64") + set(SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_PREBUILT_PATH + "${SWIFT_ANDROID_NDK_PATH}/toolchains/x86_64-${SWIFT_ANDROID_NDK_GCC_VERSION}/prebuilt/${_swift_android_prebuilt_build}") + else() + set(SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_PREBUILT_PATH "${SWIFT_ANDROID_NDK_PATH}/toolchains/${SWIFT_SDK_ANDROID_ARCH_${arch}_NDK_TRIPLE}-${SWIFT_ANDROID_NDK_GCC_VERSION}/prebuilt/${_swift_android_prebuilt_build}") + endif() else() if(NOT SWIFT_SDK_${prefix}_ARCH_${arch}_PATH) set(SWIFT_SDK_${prefix}_ARCH_${arch}_PATH "/") From 8e1c00cb46910edb5a1d0aa632c6bed483623383 Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Sun, 26 May 2019 21:04:58 -0700 Subject: [PATCH 002/112] [Diagnostics] Clarify diagnostic for failed type conversion in subscript assignment Addresses SR-6340 --- include/swift/AST/DiagnosticsSema.def | 10 ++++++++++ lib/Sema/CSDiag.cpp | 13 ++++++++++--- lib/Sema/CSDiagnostics.cpp | 8 +++++++- lib/Sema/TypeChecker.h | 2 ++ test/Constraints/assignment.swift | 15 ++++++++++++++- 5 files changed, 43 insertions(+), 5 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index ab57e404b8f9a..7c1b6ff51c833 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -447,6 +447,16 @@ ERROR(cannot_convert_assign_protocol,none, ERROR(cannot_convert_assign_nil,none, "'nil' cannot be assigned to type %0", (Type)) +// Subscript Assign Expr +ERROR(cannot_convert_subscript_assign,none, + "cannot assign value of type %0 to subscript of type %1", + (Type,Type)) +ERROR(cannot_convert_subscript_assign_protocol,none, + "value of type %0 does not conform to %1 in subscript assignment", + (Type, Type)) +ERROR(cannot_convert_subscript_assign_nil,none, + "'nil' cannot be assigned to subscript of type %0", (Type)) + // for ... in expression ERROR(cannot_convert_sequence_element_value,none, "cannot convert sequence element type %0 to expected type %1", diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index 71361f1c9fe3d..35f74f4be8f68 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -2201,6 +2201,10 @@ bool FailureDiagnosis::diagnoseContextualConversionError( diagID = diag::cannot_convert_assign; nilDiag = diag::cannot_convert_assign_nil; break; + case CTP_SubscriptAssignSource: + diagID = diag::cannot_convert_subscript_assign; + nilDiag = diag::cannot_convert_subscript_assign_nil; + break; } // If we're diagnostic an issue with 'nil', produce a specific diagnostic, @@ -2356,6 +2360,7 @@ bool FailureDiagnosis::diagnoseContextualConversionError( case CTP_DictionaryKey: case CTP_DictionaryValue: case CTP_AssignSource: + case CTP_SubscriptAssignSource: case CTP_Initialization: case CTP_ReturnStmt: tryRawRepresentableFixIts(diag, CS, exprType, contextualType, @@ -5383,7 +5388,9 @@ bool FailureDiagnosis::visitAssignExpr(AssignExpr *assignExpr) { auto *srcExpr = assignExpr->getSrc(); auto contextualType = destType->getRValueType(); - + auto contextualTypePurpose = isa(destExpr) + ? CTP_SubscriptAssignSource + : CTP_AssignSource; // Let's try to type-check assignment source expression without using // destination as a contextual type, that allows us to diagnose // contextual problems related to source much easier. @@ -5399,11 +5406,11 @@ bool FailureDiagnosis::visitAssignExpr(AssignExpr *assignExpr) { if (type && !type->isEqual(contextualType)) return diagnoseContextualConversionError( - assignExpr->getSrc(), contextualType, CTP_AssignSource); + assignExpr->getSrc(), contextualType, contextualTypePurpose); } srcExpr = typeCheckChildIndependently(assignExpr->getSrc(), contextualType, - CTP_AssignSource); + contextualTypePurpose); if (!srcExpr) return true; diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index c3427a54c3773..cf7801b51caf8 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -2804,7 +2804,11 @@ bool MissingContextualConformanceFailure::diagnoseAsError() { Optional> diagnostic; if (path.empty()) { assert(isa(anchor)); - diagnostic = getDiagnosticFor(CTP_AssignSource); + if (isa(cast(anchor)->getDest())) { + diagnostic = getDiagnosticFor(CTP_SubscriptAssignSource); + } else { + diagnostic = getDiagnosticFor(CTP_AssignSource); + } } else { const auto &last = path.back(); switch (last.getKind()) { @@ -2871,6 +2875,8 @@ MissingContextualConformanceFailure::getDiagnosticFor( return diag::cannot_convert_coerce_protocol; case CTP_AssignSource: return diag::cannot_convert_assign_protocol; + case CTP_SubscriptAssignSource: + return diag::cannot_convert_subscript_assign_protocol; case CTP_ThrowStmt: case CTP_Unused: diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 621617956c1b0..1512add4e78e4 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -217,6 +217,8 @@ enum ContextualTypePurpose { CTP_DictionaryValue, ///< DictionaryExpr values should have a specific type. CTP_CoerceOperand, ///< CoerceExpr operand coerced to specific type. CTP_AssignSource, ///< AssignExpr source operand coerced to result type. + CTP_SubscriptAssignSource, ///< AssignExpr source operand coerced to subscript + ///< result type. CTP_CannotFail, ///< Conversion can never fail. abort() if it does. }; diff --git a/test/Constraints/assignment.swift b/test/Constraints/assignment.swift index cbf828d6bb582..4bc885b0fbd57 100644 --- a/test/Constraints/assignment.swift +++ b/test/Constraints/assignment.swift @@ -2,6 +2,7 @@ struct X { } struct Y { } +protocol Z { } struct WithOverloadedSubscript { subscript(i: Int) -> X { @@ -14,6 +15,13 @@ struct WithOverloadedSubscript { } } +struct WithProtocolSubscript { + subscript(i: Int) -> Z { + get {} + set {} + } +} + func test_assign() { var a = WithOverloadedSubscript() a[0] = X() @@ -26,6 +34,7 @@ var f: Y func getXY() -> (X, Y) {} var ift : (X, Y) var ovl = WithOverloadedSubscript() +var ps = WithProtocolSubscript() var slice: [X] @@ -40,7 +49,11 @@ i = j _ = (i, f) slice[7] = i -slice[7] = f // expected-error{{cannot assign value of type 'Y' to type 'X'}} +slice[7] = f // expected-error{{cannot assign value of type 'Y' to subscript of type 'X'}} + +slice[7] = nil // expected-error{{'nil' cannot be assigned to subscript of type 'X'}} + +ps[7] = i // expected-error{{value of type 'X' does not conform to 'Z' in subscript assignment}} slice[7] = _ // expected-error{{'_' can only appear in a pattern or on the left side of an assignment}} From f90cdf563d33323693c35734c14614d47aaa52fe Mon Sep 17 00:00:00 2001 From: Ross Bayer Date: Wed, 29 May 2019 13:11:55 -0700 Subject: [PATCH 003/112] [Build System: CMake] Add new SWIFT_DARWIN_SUPPORTED_ARCHS CMake cache variable to allow users to specify a subset of architectures they wish to build. --- CMakeLists.txt | 8 ++++++++ cmake/modules/StandaloneOverlay.cmake | 7 +++++++ cmake/modules/SwiftConfigureSDK.cmake | 11 ++++++++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 459ace1f9f042..16ecd1d0fe08a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -223,6 +223,14 @@ option(SWIFT_STDLIB_ENABLE_SIB_TARGETS "Should we generate sib targets for the stdlib or not?" FALSE) + +set(SWIFT_DARWIN_SUPPORTED_ARCHS "" CACHE STRING + "Space-separated list of architectures to configure on Darwin platforms. \ +If left empty all default architectures are configured.") + +separate_arguments(SWIFT_DARWIN_SUPPORTED_ARCHS) + + # # User-configurable Android specific options. # diff --git a/cmake/modules/StandaloneOverlay.cmake b/cmake/modules/StandaloneOverlay.cmake index dd43f26189fca..8105f94a60205 100644 --- a/cmake/modules/StandaloneOverlay.cmake +++ b/cmake/modules/StandaloneOverlay.cmake @@ -65,6 +65,13 @@ option(SWIFT_ENABLE_PARSEABLE_MODULE_INTERFACES set(SWIFT_STDLIB_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING "Build type for the Swift standard library and SDK overlays.") +set(SWIFT_DARWIN_SUPPORTED_ARCHS "" CACHE STRING + "Space-separated list of architectures to configure on Darwin platforms. \ +If left empty all default architectures are configured.") + +separate_arguments(SWIFT_DARWIN_SUPPORTED_ARCHS) + + # ----------------------------------------------------------------------------- # Constants diff --git a/cmake/modules/SwiftConfigureSDK.cmake b/cmake/modules/SwiftConfigureSDK.cmake index f5d77456dd434..deed67cfbc47d 100644 --- a/cmake/modules/SwiftConfigureSDK.cmake +++ b/cmake/modules/SwiftConfigureSDK.cmake @@ -141,9 +141,18 @@ macro(configure_sdk_darwin set(SWIFT_SDK_${prefix}_LIB_SUBDIR "${xcrun_name}") set(SWIFT_SDK_${prefix}_VERSION_MIN_NAME "${version_min_name}") set(SWIFT_SDK_${prefix}_TRIPLE_NAME "${triple_name}") - set(SWIFT_SDK_${prefix}_ARCHITECTURES "${architectures}") set(SWIFT_SDK_${prefix}_OBJECT_FORMAT "MACHO") + set(SWIFT_SDK_${prefix}_ARCHITECTURES ${architectures}) + if(SWIFT_DARWIN_SUPPORTED_ARCHS) + list_intersect( + "${architectures}" # lhs + "${SWIFT_DARWIN_SUPPORTED_ARCHS}" # rhs + SWIFT_SDK_${prefix}_ARCHITECTURES) # result + endif() + + # Configure variables for _all_ architectures even if we aren't "building" + # them because they aren't supported. foreach(arch ${architectures}) # On Darwin, all archs share the same SDK path. set(SWIFT_SDK_${prefix}_ARCH_${arch}_PATH "${SWIFT_SDK_${prefix}_PATH}") From 1bc306653cd863f3d62e7a6ba9d6df19f03feaa5 Mon Sep 17 00:00:00 2001 From: Ross Bayer Date: Wed, 29 May 2019 13:17:11 -0700 Subject: [PATCH 004/112] [Build System: CMake] Fix the arch-specific target exporting in add_swift_target_library to export targets for all the defined archs rather than _just_ the last one processed in the foreach loop above. --- cmake/modules/AddSwift.cmake | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 7b8ac7a995eba..6f41c83db73d9 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -2042,12 +2042,22 @@ function(add_swift_target_library name) endforeach() endif() - swift_is_installing_component("${SWIFTLIB_INSTALL_IN_COMPONENT}" is_installing) - if(NOT is_installing) - set_property(GLOBAL APPEND PROPERTY SWIFT_BUILDTREE_EXPORTS ${VARIANT_NAME}) - else() - set_property(GLOBAL APPEND PROPERTY SWIFT_EXPORTS ${VARIANT_NAME}) - endif() + swift_is_installing_component( + "${SWIFTLIB_INSTALL_IN_COMPONENT}" + is_installing) + + # Add the arch-specific library targets to the global exports. + foreach(arch ${SWIFT_SDK_${sdk}_ARCHITECTURES}) + set(_variant_name "${name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}") + + if(is_installing) + set_property(GLOBAL APPEND + PROPERTY SWIFT_EXPORTS ${_variant_name}) + else() + set_property(GLOBAL APPEND + PROPERTY SWIFT_BUILDTREE_EXPORTS ${_variant_name}) + endif() + endforeach() # If we built static variants of the library, create a lipo target for # them. From 4ec60332f9aa824c8ec30333260170fdc1ee84a6 Mon Sep 17 00:00:00 2001 From: Ross Bayer Date: Wed, 29 May 2019 13:19:32 -0700 Subject: [PATCH 005/112] [Build System: CMake] Add new SWIFT_DARWIN_MODULE_ARCHS CMake cache variable which allows users to specify architectures they wish to configure and build _just_ the .swiftmodule content, even if they are not 'supported' via SWIFT_DARWIN_SUPPORTED_ARCHS. --- CMakeLists.txt | 6 +++ cmake/modules/AddSwift.cmake | 58 +++++++++++++++++++++++++-- cmake/modules/StandaloneOverlay.cmake | 6 +++ cmake/modules/SwiftConfigureSDK.cmake | 8 ++++ 4 files changed, 75 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 16ecd1d0fe08a..7b1703c5f57f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -228,7 +228,13 @@ set(SWIFT_DARWIN_SUPPORTED_ARCHS "" CACHE STRING "Space-separated list of architectures to configure on Darwin platforms. \ If left empty all default architectures are configured.") +set(SWIFT_DARWIN_MODULE_ARCHS "" CACHE STRING + "Space-separated list of architectures to configure Swift module-only \ +targets on Darwin platforms. These targets are in addition to the full \ +library targets.") + separate_arguments(SWIFT_DARWIN_SUPPORTED_ARCHS) +separate_arguments(SWIFT_DARWIN_MODULE_ARCHS) # diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 6f41c83db73d9..174d6bba7bac4 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -922,6 +922,17 @@ function(_add_swift_library_single target name) endif() endif() + # Only build the modules for any arch listed in the *_MODULE_ARCHITECTURES. + if(SWIFTLIB_SINGLE_SDK IN_LIST SWIFT_APPLE_PLATFORMS + AND SWIFTLIB_SINGLE_ARCHITECTURE IN_LIST SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_MODULE_ARCHITECTURES) + # Create dummy target to hook up the module target dependency. + add_custom_target("${target}" + DEPENDS + "${swift_module_dependency_target}") + + return() + endif() + set(SWIFTLIB_INCORPORATED_OBJECT_LIBRARIES_EXPRESSIONS) foreach(object_library ${SWIFTLIB_SINGLE_INCORPORATE_OBJECT_LIBRARIES}) list(APPEND SWIFTLIB_INCORPORATED_OBJECT_LIBRARIES_EXPRESSIONS @@ -1826,7 +1837,10 @@ function(add_swift_target_library name) endif() # For each architecture supported by this SDK - foreach(arch ${SWIFT_SDK_${sdk}_ARCHITECTURES}) + set(sdk_supported_archs + ${SWIFT_SDK_${sdk}_ARCHITECTURES} + ${SWIFT_SDK_${sdk}_MODULE_ARCHITECTURES}) + foreach(arch ${sdk_supported_archs}) # Configure variables for this subdirectory. set(VARIANT_SUFFIX "-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}") set(VARIANT_NAME "${name}${VARIANT_SUFFIX}") @@ -1947,11 +1961,38 @@ function(add_swift_target_library name) endforeach() endif() - # Note this thin library. - list(APPEND THIN_INPUT_TARGETS ${VARIANT_NAME}) + if(arch IN_LIST SWIFT_SDK_${sdk}_ARCHITECTURES) + # Note this thin library. + list(APPEND THIN_INPUT_TARGETS ${VARIANT_NAME}) + endif() endif() endforeach() + # Configure module-only targets + if(NOT SWIFT_SDK_${sdk}_ARCHITECTURES + AND SWIFT_SDK_${sdk}_MODULE_ARCHITECTURES) + set(_target "${name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}") + + # Create unified sdk target + add_custom_target("${_target}") + + foreach(_arch ${SWIFT_SDK_${sdk}_MODULE_ARCHITECTURES}) + set(_variant_suffix "-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${_arch}") + set(_module_variant_name "${name}-swiftmodule-${_variant_suffix}") + + add_dependencies("${_target}" ${_module_variant_name}) + + # Add Swift standard library targets as dependencies to the top-level + # convenience target. + if(TARGET "swift-stdlib${_variant_suffix}") + add_dependencies("swift-stdlib${_variant_suffix}" + "${_target}") + endif() + endforeach() + + return() + endif() + if(NOT SWIFTLIB_OBJECT_LIBRARY) # Determine the name of the universal library. if(SWIFTLIB_SHARED) @@ -2059,6 +2100,17 @@ function(add_swift_target_library name) endif() endforeach() + # Add the swiftmodule-only targets to the lipo target depdencies. + foreach(arch ${SWIFT_SDK_${sdk}_MODULE_ARCHITECTURES}) + set(_variant_name + "${name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}") + + if(TARGET "${_variant_name}") + add_dependencies("${lipo_target}" + "${_variant_name}") + endif() + endforeach() + # If we built static variants of the library, create a lipo target for # them. set(lipo_target_static) diff --git a/cmake/modules/StandaloneOverlay.cmake b/cmake/modules/StandaloneOverlay.cmake index 8105f94a60205..1dbee2ba46e9c 100644 --- a/cmake/modules/StandaloneOverlay.cmake +++ b/cmake/modules/StandaloneOverlay.cmake @@ -69,7 +69,13 @@ set(SWIFT_DARWIN_SUPPORTED_ARCHS "" CACHE STRING "Space-separated list of architectures to configure on Darwin platforms. \ If left empty all default architectures are configured.") +set(SWIFT_DARWIN_MODULE_ARCHS "" CACHE STRING + "Space-separated list of architectures to configure Swift module-only \ +targets on Darwin platforms. These targets are in addition to the full \ +library targets.") + separate_arguments(SWIFT_DARWIN_SUPPORTED_ARCHS) +separate_arguments(SWIFT_DARWIN_MODULE_ARCHS) # ----------------------------------------------------------------------------- diff --git a/cmake/modules/SwiftConfigureSDK.cmake b/cmake/modules/SwiftConfigureSDK.cmake index deed67cfbc47d..060b52d919563 100644 --- a/cmake/modules/SwiftConfigureSDK.cmake +++ b/cmake/modules/SwiftConfigureSDK.cmake @@ -51,6 +51,9 @@ function(_report_sdk prefix) message(STATUS " Triple name: ${SWIFT_SDK_${prefix}_TRIPLE_NAME}") endif() message(STATUS " Architectures: ${SWIFT_SDK_${prefix}_ARCHITECTURES}") + if(SWIFT_SDK_${prefix}_MODULE_ARCHITECTURES) + message(STATUS " Module Architectures: ${SWIFT_SDK_${prefix}_MODULE_ARCHITECTURES}") + endif() if(NOT prefix IN_LIST SWIFT_APPLE_PLATFORMS) if(SWIFT_BUILD_STDLIB) foreach(arch ${SWIFT_SDK_${prefix}_ARCHITECTURES}) @@ -151,6 +154,11 @@ macro(configure_sdk_darwin SWIFT_SDK_${prefix}_ARCHITECTURES) # result endif() + list_intersect( + "${SWIFT_DARWIN_MODULE_ARCHS}" # lhs + "${architectures}" # rhs + SWIFT_SDK_${prefix}_MODULE_ARCHITECTURES) # result + # Configure variables for _all_ architectures even if we aren't "building" # them because they aren't supported. foreach(arch ${architectures}) From 03dbada12f5387de79fec30034941d3733624848 Mon Sep 17 00:00:00 2001 From: Ross Bayer Date: Wed, 29 May 2019 14:39:08 -0700 Subject: [PATCH 006/112] [Build System: CMake] Convert SWIFT_DARWIN_SUPPORTED_ARCHS and SWIFT_DARWIN_MODULE_ARCHS into semicolon-separated lists rather than space-separated. --- CMakeLists.txt | 7 ++----- cmake/modules/StandaloneOverlay.cmake | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b1703c5f57f9..0bb1d41ea8b9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,17 +225,14 @@ option(SWIFT_STDLIB_ENABLE_SIB_TARGETS set(SWIFT_DARWIN_SUPPORTED_ARCHS "" CACHE STRING - "Space-separated list of architectures to configure on Darwin platforms. \ + "Semicolon-separated list of architectures to configure on Darwin platforms. \ If left empty all default architectures are configured.") set(SWIFT_DARWIN_MODULE_ARCHS "" CACHE STRING - "Space-separated list of architectures to configure Swift module-only \ + "Semicolon-separated list of architectures to configure Swift module-only \ targets on Darwin platforms. These targets are in addition to the full \ library targets.") -separate_arguments(SWIFT_DARWIN_SUPPORTED_ARCHS) -separate_arguments(SWIFT_DARWIN_MODULE_ARCHS) - # # User-configurable Android specific options. diff --git a/cmake/modules/StandaloneOverlay.cmake b/cmake/modules/StandaloneOverlay.cmake index 1dbee2ba46e9c..830833be0c92d 100644 --- a/cmake/modules/StandaloneOverlay.cmake +++ b/cmake/modules/StandaloneOverlay.cmake @@ -66,17 +66,14 @@ set(SWIFT_STDLIB_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING "Build type for the Swift standard library and SDK overlays.") set(SWIFT_DARWIN_SUPPORTED_ARCHS "" CACHE STRING - "Space-separated list of architectures to configure on Darwin platforms. \ + "Semicolon-separated list of architectures to configure on Darwin platforms. \ If left empty all default architectures are configured.") set(SWIFT_DARWIN_MODULE_ARCHS "" CACHE STRING - "Space-separated list of architectures to configure Swift module-only \ + "Semicolon-separated list of architectures to configure Swift module-only \ targets on Darwin platforms. These targets are in addition to the full \ library targets.") -separate_arguments(SWIFT_DARWIN_SUPPORTED_ARCHS) -separate_arguments(SWIFT_DARWIN_MODULE_ARCHS) - # ----------------------------------------------------------------------------- # Constants From 029c25a1374a57e2985fe143ac5d87ca18d9d509 Mon Sep 17 00:00:00 2001 From: Ross Bayer Date: Wed, 29 May 2019 15:28:53 -0700 Subject: [PATCH 007/112] [Build System: CMake] Ensure the SDK supported architectures and module architectures lists are mutually exclusive. --- cmake/modules/AddSwift.cmake | 4 +++- cmake/modules/SwiftConfigureSDK.cmake | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 174d6bba7bac4..728499c22a526 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -1836,10 +1836,12 @@ function(add_swift_target_library name) list(APPEND swiftlib_link_flags_all "-Wl,-z,defs") endif() - # For each architecture supported by this SDK set(sdk_supported_archs ${SWIFT_SDK_${sdk}_ARCHITECTURES} ${SWIFT_SDK_${sdk}_MODULE_ARCHITECTURES}) + list(REMOVE_DUPLICATES sdk_supported_archs) + + # For each architecture supported by this SDK foreach(arch ${sdk_supported_archs}) # Configure variables for this subdirectory. set(VARIANT_SUFFIX "-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}") diff --git a/cmake/modules/SwiftConfigureSDK.cmake b/cmake/modules/SwiftConfigureSDK.cmake index 060b52d919563..cb9c7e9ace84e 100644 --- a/cmake/modules/SwiftConfigureSDK.cmake +++ b/cmake/modules/SwiftConfigureSDK.cmake @@ -159,6 +159,13 @@ macro(configure_sdk_darwin "${architectures}" # rhs SWIFT_SDK_${prefix}_MODULE_ARCHITECTURES) # result + # Ensure the architectures and module-only architectures lists are mutually + # exclusive. + list_subtract( + "${SWIFT_SDK_${prefix}_MODULE_ARCHITECTURES}" # lhs + "${SWIFT_SDK_${prefix}_ARCHITECTURES}" # rhs + SWIFT_SDK_${prefix}_MODULE_ARCHITECTURES) # result + # Configure variables for _all_ architectures even if we aren't "building" # them because they aren't supported. foreach(arch ${architectures}) From 1da11512e76a1c926cf96a4eb71725fe4992e82f Mon Sep 17 00:00:00 2001 From: Ross Bayer Date: Wed, 29 May 2019 16:37:46 -0700 Subject: [PATCH 008/112] [Build System: build-script] Add new build-script options to specify supported architectures and module-only architectures on Darwin platforms. --- utils/build-script | 25 +++++++++++++++++++ utils/build_swift/driver_arguments.py | 12 +++++++++ utils/build_swift/tests/expected_options.py | 4 +++ .../swift_build_support/targets.py | 4 +++ 4 files changed, 45 insertions(+) diff --git a/utils/build-script b/utils/build-script index 14e22662b7406..313b4240825d8 100755 --- a/utils/build-script +++ b/utils/build-script @@ -420,6 +420,31 @@ class BuildScriptInvocation(object): args.android = True args.build_android = False + # Include the Darwin supported architectures in the CMake options. + if args.swift_darwin_supported_archs: + args.extra_cmake_options.append( + '-DSWIFT_DARWIN_SUPPORTED_ARCHS:STRING={}'.format( + args.swift_darwin_supported_archs)) + + # Remove unsupported Darwin archs from the standard library + # deployment targets. + supported_archs = args.swift_darwin_supported_archs.split(';') + targets = StdlibDeploymentTarget.get_targets_by_name( + args.stdlib_deployment_targets) + + args.stdlib_deployment_targets = [ + target.name + for target in targets + if (target.platform.is_darwin and + target.arch in supported_archs) + ] + + # Include the Darwin module-only architectures in the CMake options. + if args.swift_darwin_module_archs: + args.extra_cmake_options.append( + '-DSWIFT_DARWIN_MODULE_ARCHS:STRING={}'.format( + args.swift_darwin_module_archs)) + # --- def __init__(self, toolchain, args): diff --git a/utils/build_swift/driver_arguments.py b/utils/build_swift/driver_arguments.py index 00cebddf4563c..960b81e4f6806 100644 --- a/utils/build_swift/driver_arguments.py +++ b/utils/build_swift/driver_arguments.py @@ -522,6 +522,18 @@ def create_argument_parser(): help='A space-separated list that filters which of the configured ' 'targets to build the Swift standard library for, or "all".') + option('--swift-darwin-supported-archs', store, + metavar='ARCHS', + help='Semicolon-separated list of architectures to configure on ' + 'Darwin platforms. If left empty all default architectures ' + 'are configured.') + + option('--swift-darwin-module-archs', store, + metavar='ARCHS', + help='Semicolon-separated list of architectures to configure Swift ' + 'module-only targets on Darwin platforms. These targets are ' + 'in addition to the full library targets.') + # ------------------------------------------------------------------------- in_group('Options to select projects') diff --git a/utils/build_swift/tests/expected_options.py b/utils/build_swift/tests/expected_options.py index b7ddf46a543ea..e64f9c88207e7 100644 --- a/utils/build_swift/tests/expected_options.py +++ b/utils/build_swift/tests/expected_options.py @@ -171,6 +171,8 @@ 'swift_assertions': True, 'swift_build_variant': 'Debug', 'swift_compiler_version': None, + 'swift_darwin_module_archs': None, + 'swift_darwin_supported_archs': None, 'swift_stdlib_assertions': True, 'swift_stdlib_build_variant': 'Debug', 'swift_tools_max_parallel_lto_link_jobs': @@ -532,6 +534,8 @@ class IgnoreOption(_BaseOption): StrOption('--host-target'), StrOption('--lit-args'), StrOption('--llvm-targets-to-build'), + StrOption('--swift-darwin-module-archs'), + StrOption('--swift-darwin-supported-archs'), PathOption('--android-deploy-device-path'), PathOption('--android-icu-i18n'), diff --git a/utils/swift_build_support/swift_build_support/targets.py b/utils/swift_build_support/swift_build_support/targets.py index e5877fa375919..5ec02dfcc7fec 100644 --- a/utils/swift_build_support/swift_build_support/targets.py +++ b/utils/swift_build_support/swift_build_support/targets.py @@ -258,6 +258,10 @@ def default_stdlib_deployment_targets(): def get_target_for_name(cls, name): return cls._targets_by_name.get(name) + @classmethod + def get_targets_by_name(cls, names): + return [cls.get_target_for_name(name) for name in names] + def install_prefix(): """ From 84815c88466482467f449360a071f36f70d7e5fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodr=C3=ADguez=20Troiti=C3=B1o?= Date: Wed, 29 May 2019 18:33:11 -0700 Subject: [PATCH 009/112] [windows] Update ICU version to 64.2. Improve a little the build script to not have to change the version in two places of the URL. --- utils/build-windows.bat | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/utils/build-windows.bat b/utils/build-windows.bat index 71f0fe73ae6f3..4eaa6b6b1954d 100644 --- a/utils/build-windows.bat +++ b/utils/build-windows.bat @@ -25,7 +25,10 @@ setlocal enableextensions enabledelayedexpansion -set icu_version=63_1 +set icu_version_major=64 +set icu_version_minor=2 +set icu_version=%icu_version_major%_%icu_version_minor% +set icu_version_dotted=%icu_version_major%.%icu_version_minor% set "exitOnError=|| (exit /b)" set current_directory=%~dp0 @@ -87,7 +90,7 @@ endlocal setlocal enableextensions enabledelayedexpansion set file_name=icu4c-%icu_version%-Win64-MSVC2017.zip -curl -L -O -z %file_name% "http://download.icu-project.org/files/icu4c/63.1/%file_name%" %exitOnError% +curl -L -O -z %file_name% "http://download.icu-project.org/files/icu4c/%icu_version_dotted%/%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. unzip -o %file_name% -d "%source_root%\icu-%icu_version%" From d9409957e0a67aea38dae2ef742c28efe3bb8027 Mon Sep 17 00:00:00 2001 From: Ross Bayer Date: Sat, 1 Jun 2019 17:48:47 -0700 Subject: [PATCH 010/112] [Build System: CMake] Check that targets exist before adding them to the global exports. --- cmake/modules/AddSwift.cmake | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 728499c22a526..3becd3017fe25 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -2092,6 +2092,9 @@ function(add_swift_target_library name) # Add the arch-specific library targets to the global exports. foreach(arch ${SWIFT_SDK_${sdk}_ARCHITECTURES}) set(_variant_name "${name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}") + if(NOT TARGET "${_variant_name}") + continue() + endif() if(is_installing) set_property(GLOBAL APPEND @@ -2104,13 +2107,12 @@ function(add_swift_target_library name) # Add the swiftmodule-only targets to the lipo target depdencies. foreach(arch ${SWIFT_SDK_${sdk}_MODULE_ARCHITECTURES}) - set(_variant_name - "${name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}") - - if(TARGET "${_variant_name}") - add_dependencies("${lipo_target}" - "${_variant_name}") + set(_variant_name "${name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}") + if(NOT TARGET "${_variant_name}") + continue() endif() + + add_dependencies("${lipo_target}" "${_variant_name}") endforeach() # If we built static variants of the library, create a lipo target for From 12b27a1332b852480a529bf6bb5b00d3353df504 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Fri, 31 May 2019 13:41:23 -0700 Subject: [PATCH 011/112] IRGen: getSingletonAggregateFieldType must not return field if its access level does not match rdar://50554717 --- lib/IRGen/GenType.cpp | 22 ++++++++++++++++++---- test/IRGen/Inputs/metadata2.swift | 26 ++++++++++++++++++++++++++ test/IRGen/metadata.swift | 14 ++++++++++++++ 3 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 test/IRGen/Inputs/metadata2.swift create mode 100644 test/IRGen/metadata.swift diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp index 390bce6006206..1b18edf910de3 100644 --- a/lib/IRGen/GenType.cpp +++ b/lib/IRGen/GenType.cpp @@ -2289,8 +2289,15 @@ SILType irgen::getSingletonAggregateFieldType(IRGenModule &IGM, SILType t, auto allFields = structDecl->getStoredProperties(); auto field = allFields.begin(); - if (!allFields.empty() && std::next(field) == allFields.end()) - return t.getFieldType(*field, IGM.getSILModule()); + if (!allFields.empty() && std::next(field) == allFields.end()) { + auto fieldTy = t.getFieldType(*field, IGM.getSILModule()); + if (auto fieldDecl = fieldTy.getNominalOrBoundGenericNominal()) { + // The field's access level must be higher or equal to the enclosing + // struct's. + if (fieldDecl->getEffectiveAccess() >= structDecl->getEffectiveAccess()) + return fieldTy; + } + } return SILType(); } @@ -2305,8 +2312,15 @@ SILType irgen::getSingletonAggregateFieldType(IRGenModule &IGM, SILType t, auto theCase = allCases.begin(); if (!allCases.empty() && std::next(theCase) == allCases.end() - && (*theCase)->hasAssociatedValues()) - return t.getEnumElementType(*theCase, IGM.getSILModule()); + && (*theCase)->hasAssociatedValues()) { + auto enumEltTy = t.getEnumElementType(*theCase, IGM.getSILModule()); + if (auto eltDecl = enumEltTy.getNominalOrBoundGenericNominal()) { + // The enum element's access level must be higher or equal to the + // enclosing struct's. + if (eltDecl->getEffectiveAccess() >= enumDecl->getEffectiveAccess()) + return enumEltTy; + } + } return SILType(); } diff --git a/test/IRGen/Inputs/metadata2.swift b/test/IRGen/Inputs/metadata2.swift new file mode 100644 index 0000000000000..3d3ea8334bfca --- /dev/null +++ b/test/IRGen/Inputs/metadata2.swift @@ -0,0 +1,26 @@ +import resilient_struct + +struct Item { + var d: ResilientInt? = nil +} + +struct InternalContainer { + + fileprivate enum SomeEnumType { + case none + case single(Item) + + init(item: [Item]) { + if item.count >= 1 { + self = .single(item.first!) + } else { + self = .none + } + } + } + private var type: SomeEnumType + + init(item: [Item]) { + self.type = SomeEnumType(item: item) + } +} diff --git a/test/IRGen/metadata.swift b/test/IRGen/metadata.swift new file mode 100644 index 0000000000000..5afefb1abe9d5 --- /dev/null +++ b/test/IRGen/metadata.swift @@ -0,0 +1,14 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift +// RUN: %target-swift-frontend -module-name A -I %t %S/Inputs/metadata2.swift -primary-file %s -emit-ir | %FileCheck %s + +// CHECK-LABEL: define {{.*}}swiftcc %swift.metadata_response @"$s1A12MyControllerCMr"(%swift.type*, i8*, i8**) +// CHECK-NOT: ret +// CHECK: call swiftcc %swift.metadata_response @"$s1A17InternalContainerVMa"( +// CHECK: ret +class MyController { + var c = InternalContainer(item: []) + func update(_ n: InternalContainer) { + c = n + } +} From bec3898418e97743e0f8d97128db7d86c7f2e7d3 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Mon, 3 Jun 2019 08:29:01 -0700 Subject: [PATCH 012/112] Only apply access level constraint if we have a nominal type --- lib/IRGen/GenType.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp index 1b18edf910de3..32415136c143b 100644 --- a/lib/IRGen/GenType.cpp +++ b/lib/IRGen/GenType.cpp @@ -2296,6 +2296,8 @@ SILType irgen::getSingletonAggregateFieldType(IRGenModule &IGM, SILType t, // struct's. if (fieldDecl->getEffectiveAccess() >= structDecl->getEffectiveAccess()) return fieldTy; + } else { + return fieldTy; } } @@ -2319,6 +2321,8 @@ SILType irgen::getSingletonAggregateFieldType(IRGenModule &IGM, SILType t, // enclosing struct's. if (eltDecl->getEffectiveAccess() >= enumDecl->getEffectiveAccess()) return enumEltTy; + } else { + return enumEltTy; } } From 1c41c0887c5078905b195b8147f4d9a81ebb021b Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Sun, 2 Jun 2019 22:06:43 -0700 Subject: [PATCH 013/112] validation-test: adjust stdlib tests for Windows The embedded shell script in the RUN command for lit is problematic for non-sh shell environments (i.e. Windows). This adjusts the tests to uniformly build the code for the ObjC runtime. However, the Objective-C code is only built under the same circumstances that it is currently enabled - the availability of the needed frameworks. The empty object on other runtimes will have no material impact. The swift side of it checks whether the runtime is built with ObjC interop. This allows us to largely use the same command line for all the targets. The last missing piece is that the `-fobjc-runtime` requires that we run a modern ObjC runtime. We enable this unconditionally in lit for the non-Apple targets. This improves the validation test coverage for the standard library on Windows. --- test/lit.cfg | 7 ++++--- test/stdlib/Inputs/DictionaryKeyValueTypesObjC.swift | 6 ++++++ test/stdlib/Inputs/NSSlowString/NSSlowString.m | 6 ++++++ .../Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m | 3 +++ validation-test/stdlib/ArrayNew.swift.gyb | 8 ++------ validation-test/stdlib/Arrays.swift.gyb | 8 ++------ validation-test/stdlib/Dictionary.swift | 8 ++------ validation-test/stdlib/Set.swift | 8 ++------ validation-test/stdlib/String.swift | 9 ++------- validation-test/stdlib/StringNormalization.swift | 10 +++------- validation-test/stdlib/StringUTF8.swift | 9 ++------- 11 files changed, 34 insertions(+), 48 deletions(-) diff --git a/test/lit.cfg b/test/lit.cfg index 41166948e2181..6c52aaf00fc3e 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -910,7 +910,7 @@ elif run_os in ['windows-msvc']: config.target_add_rpath = r'' config.target_clang = \ - ('clang++ -target %s %s' % (config.variant_triple, clang_mcp_opt)) + ('clang++ -target %s %s -fobjc-runtime=ios-5.0' % (config.variant_triple, clang_mcp_opt)) config.target_ld = \ ('%r -libpath:%s' % (config.link, os.path.join(test_resource_dir, \ config.target_sdk_name))) @@ -996,7 +996,7 @@ elif run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'windows-cygnus', 'wi '%s -modulewrap -target %s' % (config.swiftc, config.variant_triple)) config.target_clang = ( - "clang++ -target %s %s" % + "clang++ -target %s %s -fobjc-runtime=ios-5.0" % (config.variant_triple, clang_mcp_opt)) config.target_ld = "ld -L%r" % (make_path(test_resource_dir, config.target_sdk_name)) elif run_os == 'linux-androideabi' or run_os == 'linux-android': @@ -1120,7 +1120,8 @@ elif run_os == 'linux-androideabi' or run_os == 'linux-android': config.target_clang = ' '.join([ 'clang++', '-target', config.variant_triple, - clang_mcp_opt, android_include_system_paths_opt]) + clang_mcp_opt, android_include_system_paths_opt, + '-fobjc-runtime=ios-5.0']) config.target_ld = ' '.join([ tools_directory, '-L%s' % make_path(test_resource_dir, config.target_sdk_name)]) diff --git a/test/stdlib/Inputs/DictionaryKeyValueTypesObjC.swift b/test/stdlib/Inputs/DictionaryKeyValueTypesObjC.swift index d367e899e231c..c42383fe44b1f 100644 --- a/test/stdlib/Inputs/DictionaryKeyValueTypesObjC.swift +++ b/test/stdlib/Inputs/DictionaryKeyValueTypesObjC.swift @@ -1,3 +1,6 @@ + +#if _runtime(_ObjC) + import Swift import SwiftPrivate import Darwin @@ -1002,3 +1005,6 @@ func getBridgedNSArrayOfValueTypeCustomBridged( return bridged } + +#endif + diff --git a/test/stdlib/Inputs/NSSlowString/NSSlowString.m b/test/stdlib/Inputs/NSSlowString/NSSlowString.m index f1374165233c2..ae14618c8791f 100644 --- a/test/stdlib/Inputs/NSSlowString/NSSlowString.m +++ b/test/stdlib/Inputs/NSSlowString/NSSlowString.m @@ -1,3 +1,6 @@ + +#if __has_include() + #import "NSSlowString.h" @@ -41,3 +44,6 @@ - (void *) _fastCharacterContents { } @end + +#endif + diff --git a/test/stdlib/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m b/test/stdlib/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m index cc41888b4f2d1..7b3ba99ad67ee 100644 --- a/test/stdlib/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m +++ b/test/stdlib/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m @@ -1,3 +1,5 @@ + +#if __has_include() #include void slurpFastEnumerationOfArrayFromObjCImpl(id Array, id FE, @@ -16,4 +18,5 @@ void slurpFastEnumerationOfDictionaryFromObjCImpl( [KeyValuePairs addObject: NSD[Key]]; } } +#endif diff --git a/validation-test/stdlib/ArrayNew.swift.gyb b/validation-test/stdlib/ArrayNew.swift.gyb index 4bf3caee3d67e..de64492ea4e7f 100644 --- a/validation-test/stdlib/ArrayNew.swift.gyb +++ b/validation-test/stdlib/ArrayNew.swift.gyb @@ -1,12 +1,8 @@ // RUN: %empty-directory(%t) // // RUN: %gyb %s -o %t/main.swift -// RUN: if [ %target-runtime == "objc" ]; then \ -// RUN: %target-clang -fobjc-arc %S/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m -c -o %t/SlurpFastEnumeration.o; \ -// RUN: %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %S/Inputs/DictionaryKeyValueTypesObjC.swift %t/main.swift -I %S/Inputs/SlurpFastEnumeration/ -Xlinker %t/SlurpFastEnumeration.o -o %t/Array -Xfrontend -disable-access-control -swift-version 4.2; \ -// RUN: else \ -// RUN: %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %t/main.swift -o %t/Array -Xfrontend -disable-access-control -swift-version 4.2; \ -// RUN: fi +// RUN: %target-clang -fobjc-arc %S/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m -c -o %t/SlurpFastEnumeration.o +// RUN: %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %S/Inputs/DictionaryKeyValueTypesObjC.swift %t/main.swift -I %S/Inputs/SlurpFastEnumeration/ -Xlinker %t/SlurpFastEnumeration.o -o %t/Array -Xfrontend -disable-access-control -swift-version 4.2 // RUN: %target-codesign %t/Array && %line-directive %t/main.swift -- %target-run %t/Array // REQUIRES: executable_test diff --git a/validation-test/stdlib/Arrays.swift.gyb b/validation-test/stdlib/Arrays.swift.gyb index e71709dd474ad..ef2ba5ff21365 100644 --- a/validation-test/stdlib/Arrays.swift.gyb +++ b/validation-test/stdlib/Arrays.swift.gyb @@ -1,12 +1,8 @@ // RUN: %empty-directory(%t) // // RUN: %gyb %s -o %t/main.swift -// RUN: if [ %target-runtime == "objc" ]; then \ -// RUN: %target-clang -fobjc-arc %S/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m -c -o %t/SlurpFastEnumeration.o; \ -// RUN: %line-directive %t/main.swift -- %target-build-swift %t/main.swift %S/Inputs/ArrayTypesAndHelpers.swift -I %S/Inputs/SlurpFastEnumeration/ -Xlinker %t/SlurpFastEnumeration.o -o %t/Arrays -Xfrontend -disable-access-control; \ -// RUN: else \ -// RUN: %line-directive %t/main.swift -- %target-build-swift %S/Inputs/ArrayTypesAndHelpers.swift %t/main.swift -o %t/Arrays -Xfrontend -disable-access-control; \ -// RUN: fi +// RUN: %target-clang -fobjc-arc %S/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m -c -o %t/SlurpFastEnumeration.o +// RUN: %line-directive %t/main.swift -- %target-build-swift %t/main.swift %S/Inputs/ArrayTypesAndHelpers.swift -I %S/Inputs/SlurpFastEnumeration/ -Xlinker %t/SlurpFastEnumeration.o -o %t/Arrays -Xfrontend -disable-access-control // // RUN: %target-codesign %t/Arrays && %line-directive %t/main.swift -- %target-run %t/Arrays // REQUIRES: executable_test diff --git a/validation-test/stdlib/Dictionary.swift b/validation-test/stdlib/Dictionary.swift index d19dd3d4d6888..ad233d82cbebb 100644 --- a/validation-test/stdlib/Dictionary.swift +++ b/validation-test/stdlib/Dictionary.swift @@ -1,12 +1,8 @@ // RUN: %empty-directory(%t) // // RUN: %gyb %s -o %t/main.swift -// RUN: if [ %target-runtime == "objc" ]; then \ -// RUN: %target-clang -fobjc-arc %S/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m -c -o %t/SlurpFastEnumeration.o; \ -// RUN: %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %S/Inputs/DictionaryKeyValueTypesObjC.swift %t/main.swift -I %S/Inputs/SlurpFastEnumeration/ -Xlinker %t/SlurpFastEnumeration.o -o %t/Dictionary -Xfrontend -disable-access-control; \ -// RUN: else \ -// RUN: %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %t/main.swift -o %t/Dictionary -Xfrontend -disable-access-control; \ -// RUN: fi +// RUN: %target-clang -fobjc-arc %S/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m -c -o %t/SlurpFastEnumeration.o +// RUN: %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %S/Inputs/DictionaryKeyValueTypesObjC.swift %t/main.swift -I %S/Inputs/SlurpFastEnumeration/ -Xlinker %t/SlurpFastEnumeration.o -o %t/Dictionary -Xfrontend -disable-access-control // // RUN: %target-codesign %t/Dictionary && %line-directive %t/main.swift -- %target-run %t/Dictionary // REQUIRES: executable_test diff --git a/validation-test/stdlib/Set.swift b/validation-test/stdlib/Set.swift index 87b95584cd20f..e67011d64f6bc 100644 --- a/validation-test/stdlib/Set.swift +++ b/validation-test/stdlib/Set.swift @@ -1,12 +1,8 @@ // RUN: %empty-directory(%t) // // RUN: %gyb %s -o %t/main.swift -// RUN: if [ %target-runtime == "objc" ]; then \ -// RUN: %target-clang -fobjc-arc %S/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m -c -o %t/SlurpFastEnumeration.o; \ -// RUN: %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %S/Inputs/DictionaryKeyValueTypesObjC.swift %t/main.swift -I %S/Inputs/SlurpFastEnumeration/ -Xlinker %t/SlurpFastEnumeration.o -o %t/Set -Xfrontend -disable-access-control -swift-version 4.2; \ -// RUN: else \ -// RUN: %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %t/main.swift -o %t/Set -Xfrontend -disable-access-control -swift-version 4.2; \ -// RUN: fi +// RUN: %target-clang -fobjc-arc %S/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m -c -o %t/SlurpFastEnumeration.o +// RUN: %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %S/Inputs/DictionaryKeyValueTypesObjC.swift %t/main.swift -I %S/Inputs/SlurpFastEnumeration/ -Xlinker %t/SlurpFastEnumeration.o -o %t/Set -Xfrontend -disable-access-control -swift-version 4.2 // // RUN: %target-codesign %t/Set && %line-directive %t/main.swift -- %target-run %t/Set // REQUIRES: executable_test diff --git a/validation-test/stdlib/String.swift b/validation-test/stdlib/String.swift index 02577109ccfbc..b9ed6ba8ccc33 100644 --- a/validation-test/stdlib/String.swift +++ b/validation-test/stdlib/String.swift @@ -1,11 +1,6 @@ // RUN: %empty-directory(%t) -// RUN: if [ %target-runtime == "objc" ]; \ -// RUN: then \ -// RUN: %target-clang -fobjc-arc %S/Inputs/NSSlowString/NSSlowString.m -c -o %t/NSSlowString.o && \ -// RUN: %target-build-swift -I %S/Inputs/NSSlowString/ %t/NSSlowString.o %s -Xfrontend -disable-access-control -o %t/String; \ -// RUN: else \ -// RUN: %target-build-swift %s -Xfrontend -disable-access-control -o %t/String; \ -// RUN: fi +// RUN: %target-clang -fobjc-arc %S/Inputs/NSSlowString/NSSlowString.m -c -o %t/NSSlowString.o +// RUN: %target-build-swift -I %S/Inputs/NSSlowString/ %t/NSSlowString.o %s -Xfrontend -disable-access-control -o %t/String // RUN: %target-codesign %t/String // RUN: %target-run %t/String diff --git a/validation-test/stdlib/StringNormalization.swift b/validation-test/stdlib/StringNormalization.swift index c6c249c1a2b84..2de63c018b43b 100644 --- a/validation-test/stdlib/StringNormalization.swift +++ b/validation-test/stdlib/StringNormalization.swift @@ -9,14 +9,10 @@ // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// + // RUN: %empty-directory(%t) -// RUN: if [ %target-runtime == "objc" ]; \ -// RUN: then \ -// RUN: %target-clang -fobjc-arc %S/Inputs/NSSlowString/NSSlowString.m -c -o %t/NSSlowString.o && \ -// RUN: %target-build-swift -I %S/Inputs/NSSlowString/ %t/NSSlowString.o %s -o %t/a.out; \ -// RUN: else \ -// RUN: %target-build-swift %s -o %t/a.out; \ -// RUN: fi +// RUN: %target-clang -fobjc-arc %S/Inputs/NSSlowString/NSSlowString.m -c -o %t/NSSlowString.o +// RUN: %target-build-swift -I %S/Inputs/NSSlowString/ %t/NSSlowString.o %s -o %t/a.out // RUN: %target-codesign %t/a.out // RUN: %target-run %t/a.out %S/Inputs/NormalizationTest.txt diff --git a/validation-test/stdlib/StringUTF8.swift b/validation-test/stdlib/StringUTF8.swift index 057f5081ab479..83bff4e5daa76 100644 --- a/validation-test/stdlib/StringUTF8.swift +++ b/validation-test/stdlib/StringUTF8.swift @@ -1,11 +1,6 @@ // RUN: %empty-directory(%t) -// RUN: if [ %target-runtime == "objc" ]; \ -// RUN: then \ -// RUN: %target-clang -fobjc-arc %S/Inputs/NSSlowString/NSSlowString.m -c -o %t/NSSlowString.o && \ -// RUN: %target-build-swift -I %S/Inputs/NSSlowString/ %t/NSSlowString.o %s -o %t/String; \ -// RUN: else \ -// RUN: %target-build-swift %s -o %t/String; \ -// RUN: fi +// RUN: %target-clang -fobjc-arc %S/Inputs/NSSlowString/NSSlowString.m -c -o %t/NSSlowString.o +// RUN: %target-build-swift -I %S/Inputs/NSSlowString/ %t/NSSlowString.o %s -o %t/String // RUN: %target-codesign %t/String // RUN: %target-run %t/String From 48976e56844c9046c6f6c1c39d88d1c996714f68 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 3 Jun 2019 11:18:48 -0700 Subject: [PATCH 014/112] test: add a workaround for `rth` invocation The `rth` tool is a python script and relied on the execution via the shebang. However, not all targets support the shebang to invoke the interpreter. Explicitly launch the resilience test helper with the interpreter (python). Ideally, we would use the `%rth` substitution, but that does not seem to function for the nested case here. --- test/lit.cfg | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/lit.cfg b/test/lit.cfg index 7dbb90dfde51b..2f899e146eef9 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -1338,12 +1338,13 @@ rth_flags = '' if swift_execution_tests_extra_flags: rth_flags = swift_execution_tests_extra_flags + ' -wmo' +# FIXME: why can we not use %rth and have that be expanded out? config.target_resilience_test = ( - '%s --target-build-swift "%s" --target-run "%s" --t %%t --S %%S --s %%s ' - '--lib-prefix "%s" --lib-suffix "%s" --target-codesign "%s" ' + '%r %s --target-build-swift "%s" --target-run "%s" --t %%t --S %%S ' + '--s %%s --lib-prefix "%s" --lib-suffix "%s" --target-codesign "%s" ' '--additional-compile-flags "%s" --triple "%s"' - % (config.rth, config.target_build_swift, config.target_run, - config.target_shared_library_prefix, + % (sys.executable, config.rth, config.target_build_swift, + config.target_run, config.target_shared_library_prefix, config.target_shared_library_suffix, config.target_codesign, rth_flags, config.variant_triple)) From bb2eee12b06d4f3775b6991fac81f791699dbe79 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 3 Jun 2019 16:46:27 -0700 Subject: [PATCH 015/112] syntax: silence MSVC warning about unreachable (NFC) Add a llvm_unreachable to indicate to MSVC that the switch is covered. --- include/swift/Syntax/Trivia.h.gyb | 1 + 1 file changed, 1 insertion(+) diff --git a/include/swift/Syntax/Trivia.h.gyb b/include/swift/Syntax/Trivia.h.gyb index 0f8994cc9c715..edceb2a83918e 100644 --- a/include/swift/Syntax/Trivia.h.gyb +++ b/include/swift/Syntax/Trivia.h.gyb @@ -516,6 +516,7 @@ struct MappingTraits { } % end } + llvm_unreachable("covered switch"); } }; From 299548deb7e5e7bac61200b3e426e33a3ca82a73 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 3 Jun 2019 19:06:05 -0700 Subject: [PATCH 016/112] validation-test: avoid shell in HashingRandomization Split up the commands into multiple RUN lines. Use a temporary to actually capture the output of multiple invocations to compose them into a single stream. Replace the `export` usage with `env` which the lit interpreter is able to process even on Windows. This makes HashingRandomization pass on Windows. --- validation-test/stdlib/HashingRandomization.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/validation-test/stdlib/HashingRandomization.swift b/validation-test/stdlib/HashingRandomization.swift index 39c1d70b01c5e..c1b04d6d0a016 100644 --- a/validation-test/stdlib/HashingRandomization.swift +++ b/validation-test/stdlib/HashingRandomization.swift @@ -1,8 +1,12 @@ // RUN: %empty-directory(%t) // RUN: %target-build-swift -Xfrontend -disable-access-control -module-name main %s -o %t/hash // RUN: %target-codesign %t/hash -// RUN: (export -n %env-SWIFT_DETERMINISTIC_HASHING; %target-run %t/hash && %target-run %t/hash) | %FileCheck --check-prefixes=RANDOM %s -// RUN: (export %env-SWIFT_DETERMINISTIC_HASHING=1; %target-run %t/hash && %target-run %t/hash) | %FileCheck --check-prefixes=STABLE %s +// RUN: env -u %env-SWIFT_DETERMINISTIC_HASHING %target-run %t/hash > %t/nondeterministic.log +// RUN: env -u %env-SWIFT_DETERMINISTIC_HASHING %target-run %t/hash >> %t/nondeterministic.log +// RUN: %FileCheck --check-prefixes=RANDOM %s < %t/nondeterministic.log +// RUN: env %env-SWIFT_DETERMINISTIC_HASHING=1 %target-run %t/hash > %t/deterministic.log +// RUN: env %env-SWIFT_DETERMINISTIC_HASHING=1 %target-run %t/hash >> %t/deterministic.log +// RUN: %FileCheck --check-prefixes=STABLE %s < %t/deterministic.log // REQUIRES: executable_test From 4ed8de10f951fc8b71bd9e33383a205683f8b62c Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Mon, 3 Jun 2019 20:10:51 -0700 Subject: [PATCH 017/112] Revert "Revert "Use autolinking to pull in compatibility libraries."" --- cmake/modules/AddSwift.cmake | 45 ++++++++++++++---- cmake/modules/SwiftSource.cmake | 10 ++-- include/swift/AST/IRGenOptions.h | 4 ++ include/swift/Basic/Platform.h | 7 +++ include/swift/Option/Options.td | 5 ++ lib/Basic/Platform.cpp | 35 ++++++++++++++ lib/Driver/DarwinToolChains.cpp | 46 +++---------------- lib/Driver/ToolChains.cpp | 11 +++++ lib/Frontend/CompilerInvocation.cpp | 24 ++++++++++ lib/IRGen/GenDecl.cpp | 20 ++++++++ stdlib/public/Compatibility50/CMakeLists.txt | 6 ++- stdlib/public/Compatibility50/Overrides.cpp | 5 ++ .../autolink-runtime-compatibility.swift | 25 ++++++++++ test/IRGen/unused.sil | 2 +- test/Serialization/autolinking.swift | 12 ++--- 15 files changed, 196 insertions(+), 61 deletions(-) create mode 100644 test/IRGen/autolink-runtime-compatibility.swift diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 7b8ac7a995eba..6f590663b20af 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -730,7 +730,8 @@ function(_add_swift_library_single target name) OBJECT_LIBRARY SHARED STATIC - TARGET_LIBRARY) + TARGET_LIBRARY + INSTALL_WITH_SHARED) set(SWIFTLIB_SINGLE_single_parameter_options ARCHITECTURE DEPLOYMENT_VERSION_IOS @@ -1085,18 +1086,24 @@ function(_add_swift_library_single target name) BINARY_DIR ${SWIFT_RUNTIME_OUTPUT_INTDIR} LIBRARY_DIR ${SWIFT_LIBRARY_OUTPUT_INTDIR}) + if(SWIFTLIB_INSTALL_WITH_SHARED) + set(swift_lib_dir ${SWIFTLIB_DIR}) + else() + set(swift_lib_dir ${SWIFTSTATICLIB_DIR}) + endif() + foreach(config ${CMAKE_CONFIGURATION_TYPES}) string(TOUPPER ${config} config_upper) escape_path_for_xcode( - "${config}" "${SWIFTSTATICLIB_DIR}" config_lib_dir) + "${config}" "${swift_lib_dir}" config_lib_dir) set_target_properties(${target_static} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${config_upper} ${config_lib_dir}/${SWIFTLIB_SINGLE_SUBDIR} ARCHIVE_OUTPUT_DIRECTORY_${config_upper} ${config_lib_dir}/${SWIFTLIB_SINGLE_SUBDIR}) endforeach() set_target_properties(${target_static} PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${SWIFTSTATICLIB_DIR}/${SWIFTLIB_SINGLE_SUBDIR} - ARCHIVE_OUTPUT_DIRECTORY ${SWIFTSTATICLIB_DIR}/${SWIFTLIB_SINGLE_SUBDIR}) + LIBRARY_OUTPUT_DIRECTORY ${swift_lib_dir}/${SWIFTLIB_SINGLE_SUBDIR} + ARCHIVE_OUTPUT_DIRECTORY ${swift_lib_dir}/${SWIFTLIB_SINGLE_SUBDIR}) endif() set_target_properties(${target} @@ -1347,8 +1354,14 @@ function(_add_swift_library_single target name) set_property(TARGET "${target_static}" APPEND_STRING PROPERTY COMPILE_FLAGS " ${c_compile_flags}") # FIXME: The fallback paths here are going to be dynamic libraries. + + if(SWIFTLIB_INSTALL_WITH_SHARED) + set(search_base_dir ${SWIFTLIB_DIR}) + else() + set(search_base_dir ${SWIFTSTATICLIB_DIR}) + endif() set(library_search_directories - "${SWIFTSTATICLIB_DIR}/${SWIFTLIB_SINGLE_SUBDIR}" + "${search_base_dir}/${SWIFTLIB_SINGLE_SUBDIR}" "${SWIFT_NATIVE_SWIFT_TOOLS_PATH}/../lib/swift/${SWIFTLIB_SINGLE_SUBDIR}" "${SWIFT_NATIVE_SWIFT_TOOLS_PATH}/../lib/swift/${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_LIB_SUBDIR}") swift_target_link_search_directories("${target_static}" "${library_search_directories}") @@ -1477,6 +1490,7 @@ endfunction() # [IS_STDLIB] # [IS_STDLIB_CORE] # [TARGET_LIBRARY] +# [INSTALL_WITH_SHARED] # INSTALL_IN_COMPONENT comp # DEPLOYMENT_VERSION_OSX version # DEPLOYMENT_VERSION_IOS version @@ -1583,6 +1597,9 @@ endfunction() # DEPLOYMENT_VERSION_WATCHOS # The minimum deployment version to build for if this is an WATCHOS library. # +# INSTALL_WITH_SHARED +# Install a static library target alongside shared libraries +# # source1 ... # Sources to add into this library. function(add_swift_target_library name) @@ -1597,7 +1614,8 @@ function(add_swift_target_library name) OBJECT_LIBRARY SHARED STATIC - TARGET_LIBRARY) + TARGET_LIBRARY + INSTALL_WITH_SHARED) set(SWIFTLIB_single_parameter_options DEPLOYMENT_VERSION_IOS DEPLOYMENT_VERSION_OSX @@ -1882,6 +1900,7 @@ function(add_swift_target_library name) ${SWIFTLIB_SHARED_keyword} ${SWIFTLIB_STATIC_keyword} ${SWIFTLIB_OBJECT_LIBRARY_keyword} + ${SWIFTLIB_INSTALL_WITH_SHARED_keyword} ${SWIFTLIB_SOURCES} MODULE_TARGET ${MODULE_VARIANT_NAME} SDK ${sdk} @@ -1996,7 +2015,7 @@ function(add_swift_target_library name) set(resource_dir_sdk_subdir "${SWIFT_SDK_${sdk}_LIB_SUBDIR}") precondition(resource_dir_sdk_subdir) - if(SWIFTLIB_SHARED) + if(SWIFTLIB_SHARED OR SWIFTLIB_INSTALL_WITH_SHARED) set(resource_dir "swift") set(file_permissions OWNER_READ OWNER_WRITE OWNER_EXECUTE @@ -2058,10 +2077,18 @@ function(add_swift_target_library name) list(APPEND THIN_INPUT_TARGETS_STATIC "${TARGET}-static") endforeach() + if(SWIFTLIB_INSTALL_WITH_SHARED) + set(install_subdir "swift") + set(universal_subdir ${SWIFTLIB_DIR}) + else() + set(install_subdir "swift_static") + set(universal_subdir ${SWIFTSTATICLIB_DIR}) + endif() + set(lipo_target_static "${name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}-static") set(UNIVERSAL_LIBRARY_NAME - "${SWIFTSTATICLIB_DIR}/${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${name}${CMAKE_STATIC_LIBRARY_SUFFIX}") + "${universal_subdir}/${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${name}${CMAKE_STATIC_LIBRARY_SUFFIX}") _add_swift_lipo_target(SDK ${sdk} TARGET @@ -2070,7 +2097,7 @@ function(add_swift_target_library name) "${UNIVERSAL_LIBRARY_NAME}" ${THIN_INPUT_TARGETS_STATIC}) swift_install_in_component(FILES "${UNIVERSAL_LIBRARY_NAME}" - DESTINATION "lib${LLVM_LIBDIR_SUFFIX}/swift_static/${resource_dir_sdk_subdir}" + DESTINATION "lib${LLVM_LIBDIR_SUFFIX}/${install_subdir}/${resource_dir_sdk_subdir}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ diff --git a/cmake/modules/SwiftSource.cmake b/cmake/modules/SwiftSource.cmake index 2ddc724f1649d..9eeef768b586f 100644 --- a/cmake/modules/SwiftSource.cmake +++ b/cmake/modules/SwiftSource.cmake @@ -253,12 +253,10 @@ function(_compile_swift_files list(APPEND swift_flags "-module-name" "${SWIFTFILE_MODULE_NAME}") endif() - # Force swift 5 mode for Standard Library. + # Force swift 5 mode for Standard Library and overlays. if (SWIFTFILE_IS_STDLIB) list(APPEND swift_flags "-swift-version" "5") endif() - - # Force swift 4 compatibility mode for overlays. if (SWIFTFILE_IS_SDK_OVERLAY) list(APPEND swift_flags "-swift-version" "5") endif() @@ -267,6 +265,12 @@ function(_compile_swift_files list(APPEND swift_flags "-autolink-force-load") endif() + # Don't need to link runtime compatibility libraries for older runtimes + # into the new runtime. + if (SWIFTFILE_IS_STDLIB OR SWIFTFILE_IS_SDK_OVERLAY) + list(APPEND swift_flags "-runtime-compatibility-version" "none") + endif() + if (SWIFTFILE_IS_STDLIB_CORE OR SWIFTFILE_IS_SDK_OVERLAY) list(APPEND swift_flags "-warn-swift3-objc-inference-complete") endif() diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h index bfb330e767756..fe9f08e0e4695 100644 --- a/include/swift/AST/IRGenOptions.h +++ b/include/swift/AST/IRGenOptions.h @@ -26,6 +26,7 @@ // FIXME: This include is just for llvm::SanitizerCoverageOptions. We should // split the header upstream so we don't include so much. #include "llvm/Transforms/Instrumentation.h" +#include "llvm/Support/VersionTuple.h" #include #include @@ -224,6 +225,9 @@ class IRGenOptions { }; TypeInfoDumpFilter TypeInfoFilter; + + /// Pull in runtime compatibility shim libraries by autolinking. + Optional AutolinkRuntimeCompatibilityLibraryVersion; IRGenOptions() : DWARFVersion(2), OutputKind(IRGenOutputKind::LLVMAssembly), diff --git a/include/swift/Basic/Platform.h b/include/swift/Basic/Platform.h index d59ef72e4297d..134b7a2cd43c6 100644 --- a/include/swift/Basic/Platform.h +++ b/include/swift/Basic/Platform.h @@ -19,6 +19,7 @@ namespace llvm { class Triple; + class VersionTuple; } namespace swift { @@ -85,6 +86,12 @@ namespace swift { /// The input triple should already be "normalized" in the sense that /// llvm::Triple::normalize() would not affect it. llvm::Triple getTargetSpecificModuleTriple(const llvm::Triple &triple); + + + /// Get the Swift runtime version to deploy back to, given a deployment target expressed as an + /// LLVM target triple. + Optional + getSwiftRuntimeCompatibilityVersionForTarget(const llvm::Triple &Triple); } // end namespace swift #endif // SWIFT_BASIC_PLATFORM_H diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 53f8d3401a84d..c6f32a0d6bb32 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -892,4 +892,9 @@ def vfsoverlay_EQ : Joined<["-"], "vfsoverlay=">, def runtime_compatibility_version : Separate<["-"], "runtime-compatibility-version">, Flags<[FrontendOption]>, HelpText<"Link compatibility library for Swift runtime version, or 'none'">; + +def disable_autolinking_runtime_compatibility : Flag<["-"], "disable-autolinking-runtime-compatibility">, + Flags<[FrontendOption]>, + HelpText<"Do not use autolinking for runtime compatibility libraries">; + include "FrontendOptions.td" diff --git a/lib/Basic/Platform.cpp b/lib/Basic/Platform.cpp index c385d666028c9..90bc7d52cc203 100644 --- a/lib/Basic/Platform.cpp +++ b/lib/Basic/Platform.cpp @@ -14,6 +14,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" +#include "llvm/Support/VersionTuple.h" using namespace swift; @@ -313,3 +314,37 @@ llvm::Triple swift::getTargetSpecificModuleTriple(const llvm::Triple &triple) { return triple; } +Optional +swift::getSwiftRuntimeCompatibilityVersionForTarget(const llvm::Triple &Triple){ + unsigned Major, Minor, Micro; + + if (Triple.isMacOSX()) { + Triple.getMacOSXVersion(Major, Minor, Micro); + if (Major == 10) { + if (Minor <= 14) { + return llvm::VersionTuple(5, 0); + } else { + return None; + } + } else { + return None; + } + } else if (Triple.isiOS()) { // includes tvOS + Triple.getiOSVersion(Major, Minor, Micro); + if (Major <= 12) { + return llvm::VersionTuple(5, 0); + } else { + return None; + } + } else if (Triple.isWatchOS()) { + Triple.getWatchOSVersion(Major, Minor, Micro); + if (Major <= 5) { + return llvm::VersionTuple(5, 0); + } else { + return None; + } + } else { + return None; + } +} + diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index 738089e27c954..2c10be0348c52 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -33,6 +33,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" +#include "llvm/Support/VersionTuple.h" using namespace swift; using namespace swift::driver; @@ -221,42 +222,6 @@ static bool wantsObjCRuntime(const llvm::Triple &triple) { llvm_unreachable("unknown Darwin OS"); } -/// Return the earliest backward deployment compatibility version we need to -/// link in for the given target triple, if any. -static Optional> -getSwiftRuntimeCompatibilityVersionForTarget(const llvm::Triple &Triple) { - unsigned Major, Minor, Micro; - - if (Triple.isMacOSX()) { - Triple.getMacOSXVersion(Major, Minor, Micro); - if (Major == 10) { - if (Minor <= 14) { - return std::make_pair(5u, 0u); - } else { - return None; - } - } else { - return None; - } - } else if (Triple.isiOS()) { // includes tvOS - Triple.getiOSVersion(Major, Minor, Micro); - if (Major <= 12) { - return std::make_pair(5u, 0u); - } else { - return None; - } - } else if (Triple.isWatchOS()) { - Triple.getWatchOSVersion(Major, Minor, Micro); - if (Major <= 5) { - return std::make_pair(5u, 0u); - } else { - return None; - } - } else { - return None; - } -} - ToolChain::InvocationInfo toolchains::Darwin::constructInvocation(const LinkJobAction &job, const JobContext &context) const @@ -431,12 +396,13 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job, // Link compatibility libraries, if we're deploying back to OSes that // have an older Swift runtime. - Optional> runtimeCompatibilityVersion; + Optional runtimeCompatibilityVersion; if (context.Args.hasArg(options::OPT_runtime_compatibility_version)) { - auto value = context.Args.getLastArgValue(options::OPT_runtime_compatibility_version); + auto value = context.Args.getLastArgValue( + options::OPT_runtime_compatibility_version); if (value.equals("5.0")) { - runtimeCompatibilityVersion = std::make_pair(5u, 0u); + runtimeCompatibilityVersion = llvm::VersionTuple(5, 0); } else if (value.equals("none")) { runtimeCompatibilityVersion = None; } else { @@ -448,7 +414,7 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job, } if (runtimeCompatibilityVersion) { - if (*runtimeCompatibilityVersion <= std::make_pair(5u, 0u)) { + if (*runtimeCompatibilityVersion <= llvm::VersionTuple(5, 0)) { // Swift 5.0 compatibility library SmallString<128> BackDeployLib; BackDeployLib.append(RuntimeLibPath); diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index ad75b4b454f50..9c377c066bbe6 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -433,6 +433,17 @@ ToolChain::constructInvocation(const CompileJobAction &job, Arguments.push_back("-debug-info-store-invocation"); } + if (context.Args.hasArg( + options::OPT_disable_autolinking_runtime_compatibility)) { + Arguments.push_back("-disable-autolinking-runtime-compatibility"); + } + + if (auto arg = context.Args.getLastArg( + options::OPT_runtime_compatibility_version)) { + Arguments.push_back("-runtime-compatibility-version"); + Arguments.push_back(arg->getValue()); + } + return II; } diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 3a8724aef592c..2819d5ef4398a 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1155,6 +1155,30 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, A->getAsString(Args), A->getValue()); } } + + // Autolink runtime compatibility libraries, if asked to. + if (!Args.hasArg(options::OPT_disable_autolinking_runtime_compatibility)) { + Optional runtimeCompatibilityVersion; + + if (auto versionArg = Args.getLastArg( + options::OPT_runtime_compatibility_version)) { + auto version = StringRef(versionArg->getValue()); + if (version.equals("none")) { + runtimeCompatibilityVersion = None; + } else if (version.equals("5.0")) { + runtimeCompatibilityVersion = llvm::VersionTuple(5, 0); + } else { + Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value, + versionArg->getAsString(Args), version); + } + } else { + runtimeCompatibilityVersion = + getSwiftRuntimeCompatibilityVersionForTarget(Triple); + } + + Opts.AutolinkRuntimeCompatibilityLibraryVersion = + runtimeCompatibilityVersion; + } return false; } diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 733d876e03551..98b36a32621da 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -449,6 +449,26 @@ void IRGenModule::emitSourceFile(SourceFile &SF) { if (ObjCInterop) this->addLinkLibrary(LinkLibrary("objc", LibraryKind::Library)); + + // FIXME: It'd be better to have the driver invocation or build system that + // executes the linker introduce these compatibility libraries, since at + // that point we know whether we're building an executable, which is the only + // place where the compatibility libraries take effect. For the benefit of + // build systems that build Swift code, but don't use Swift to drive + // the linker, we can also use autolinking to pull in the compatibility + // libraries. This may however cause the library to get pulled in in + // situations where it isn't useful, such as for dylibs, though this is + // harmless aside from code size. + if (!IRGen.Opts.UseJIT) { + if (auto compatibilityVersion + = IRGen.Opts.AutolinkRuntimeCompatibilityLibraryVersion) { + if (*compatibilityVersion <= llvm::VersionTuple(5, 0)) { + this->addLinkLibrary(LinkLibrary("swiftCompatibility50", + LibraryKind::Library, + /*forceLoad*/ true)); + } + } + } } /// Collect elements of an already-existing global list with the given diff --git a/stdlib/public/Compatibility50/CMakeLists.txt b/stdlib/public/Compatibility50/CMakeLists.txt index 970cae529207a..4773fcdabade2 100644 --- a/stdlib/public/Compatibility50/CMakeLists.txt +++ b/stdlib/public/Compatibility50/CMakeLists.txt @@ -1,10 +1,12 @@ set(swift_runtime_compile_flags ${SWIFT_RUNTIME_CORE_CXX_FLAGS}) set(swift_runtime_linker_flags ${SWIFT_RUNTIME_CORE_LINK_FLAGS}) -add_swift_target_library(swiftCompatibility50 TARGET_LIBRARY STATIC +add_swift_target_library(swiftCompatibility50 TARGET_LIBRARY STATIC INSTALL_WITH_SHARED ProtocolConformance.cpp Overrides.cpp C_COMPILE_FLAGS ${swift_runtime_library_compile_flags} LINK_FLAGS ${swift_runtime_linker_flags} TARGET_SDKS ${SWIFT_APPLE_PLATFORMS} - INSTALL_IN_COMPONENT stdlib) + INSTALL_IN_COMPONENT compiler) + + diff --git a/stdlib/public/Compatibility50/Overrides.cpp b/stdlib/public/Compatibility50/Overrides.cpp index c88ce2bec1cb1..9d7f8eb28e047 100644 --- a/stdlib/public/Compatibility50/Overrides.cpp +++ b/stdlib/public/Compatibility50/Overrides.cpp @@ -31,3 +31,8 @@ __attribute__((used, section("__DATA,__swift_hooks"))) = { .version = 0, .conformsToProtocol = swift50override_conformsToProtocol, }; + +// Allow this library to get force-loaded by autolinking +__attribute__((weak, visibility("hidden"))) +extern "C" +char _swift_FORCE_LOAD_$_swiftCompatibility50 = 0; diff --git a/test/IRGen/autolink-runtime-compatibility.swift b/test/IRGen/autolink-runtime-compatibility.swift new file mode 100644 index 0000000000000..e6d17fb4c6f02 --- /dev/null +++ b/test/IRGen/autolink-runtime-compatibility.swift @@ -0,0 +1,25 @@ +// REQUIRES: OS=macosx + +// Doesn't autolink compatibility library because autolinking is disabled +// RUN: %target-swift-frontend -target x86_64-apple-macosx10.9 -disable-autolinking-runtime-compatibility -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=NO-FORCE-LOAD %s +// RUN: %target-swift-frontend -runtime-compatibility-version 5.0 -disable-autolinking-runtime-compatibility -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=NO-FORCE-LOAD %s + +// Doesn't autolink compatibility library because runtime compatibility library is disabled +// RUN: %target-swift-frontend -runtime-compatibility-version none -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=NO-FORCE-LOAD %s + +// Doesn't autolink compatibility library because target OS doesn't need it +// RUN: %target-swift-frontend -target x86_64-apple-macosx10.24 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=NO-FORCE-LOAD %s + +// Autolinks because compatibility library was explicitly asked for +// RUN: %target-swift-frontend -runtime-compatibility-version 5.0 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=FORCE-LOAD %s +// RUN: %target-swift-frontend -target x86_64-apple-macosx10.24 -runtime-compatibility-version 5.0 -emit-ir -parse-stdlib %s | %FileCheck -check-prefix=FORCE-LOAD %s + +public func foo() {} + +// NO-FORCE-LOAD-NOT: FORCE_LOAD +// NO-FORCE-LOAD-NOT: !{!"-lswiftCompatibility50"} + +// FORCE-LOAD: declare {{.*}} @"_swift_FORCE_LOAD_$_swiftCompatibility50" + +// FORCE-LOAD-DAG: [[AUTOLINK_SWIFT_COMPAT:![0-9]+]] = !{!"-lswiftCompatibility50"} +// FORCE-LOAD-DAG: !llvm.linker.options = !{{{.*}}[[AUTOLINK_SWIFT_COMPAT]]{{[,}]}} diff --git a/test/IRGen/unused.sil b/test/IRGen/unused.sil index fd260566bcacc..f005364ddb4ee 100644 --- a/test/IRGen/unused.sil +++ b/test/IRGen/unused.sil @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck -check-prefix CHECK -check-prefix NEGATIVE -check-prefix CHECK-%target-object-format %s +// RUN: %target-swift-frontend -runtime-compatibility-version none -primary-file %s -emit-ir | %FileCheck -check-prefix CHECK -check-prefix NEGATIVE -check-prefix CHECK-%target-object-format %s // REQUIRES: CPU=x86_64 diff --git a/test/Serialization/autolinking.swift b/test/Serialization/autolinking.swift index 02062d51656ff..5ab7b673f8db2 100644 --- a/test/Serialization/autolinking.swift +++ b/test/Serialization/autolinking.swift @@ -1,23 +1,23 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend -emit-module -parse-stdlib -o %t -module-name someModule -module-link-name module %S/../Inputs/empty.swift -// RUN: %target-swift-frontend -emit-ir -lmagic %s -I %t > %t/out.txt +// RUN: %target-swift-frontend -runtime-compatibility-version none -emit-ir -lmagic %s -I %t > %t/out.txt // RUN: %FileCheck %s < %t/out.txt // RUN: %FileCheck -check-prefix=NO-FORCE-LOAD %s < %t/out.txt // RUN: %empty-directory(%t/someModule.framework/Modules/someModule.swiftmodule) // RUN: mv %t/someModule.swiftmodule %t/someModule.framework/Modules/someModule.swiftmodule/%target-swiftmodule-name -// RUN: %target-swift-frontend -emit-ir -lmagic %s -F %t > %t/framework.txt +// RUN: %target-swift-frontend -runtime-compatibility-version none -emit-ir -lmagic %s -F %t > %t/framework.txt // RUN: %FileCheck -check-prefix=FRAMEWORK %s < %t/framework.txt // RUN: %FileCheck -check-prefix=NO-FORCE-LOAD %s < %t/framework.txt // RUN: %target-swift-frontend -emit-module -parse-stdlib -o %t -module-name someModule -module-link-name module %S/../Inputs/empty.swift -autolink-force-load -// RUN: %target-swift-frontend -emit-ir -lmagic %s -I %t > %t/force-load.txt +// RUN: %target-swift-frontend -runtime-compatibility-version none -emit-ir -lmagic %s -I %t > %t/force-load.txt // RUN: %FileCheck %s < %t/force-load.txt // RUN: %FileCheck -check-prefix FORCE-LOAD-CLIENT -check-prefix FORCE-LOAD-CLIENT-%target-object-format %s < %t/force-load.txt -// RUN: %target-swift-frontend -emit-ir -parse-stdlib -module-name someModule -module-link-name module %S/../Inputs/empty.swift | %FileCheck --check-prefix=NO-FORCE-LOAD %s -// RUN: %target-swift-frontend -emit-ir -parse-stdlib -module-name someModule -module-link-name module %S/../Inputs/empty.swift -autolink-force-load | %FileCheck --check-prefix=FORCE-LOAD %s -// RUN: %target-swift-frontend -emit-ir -parse-stdlib -module-name someModule -module-link-name 0module %S/../Inputs/empty.swift -autolink-force-load | %FileCheck --check-prefix=FORCE-LOAD-HEX %s +// RUN: %target-swift-frontend -runtime-compatibility-version none -emit-ir -parse-stdlib -module-name someModule -module-link-name module %S/../Inputs/empty.swift | %FileCheck --check-prefix=NO-FORCE-LOAD %s +// RUN: %target-swift-frontend -runtime-compatibility-version none -emit-ir -parse-stdlib -module-name someModule -module-link-name module %S/../Inputs/empty.swift -autolink-force-load | %FileCheck --check-prefix=FORCE-LOAD %s +// RUN: %target-swift-frontend -runtime-compatibility-version none -emit-ir -parse-stdlib -module-name someModule -module-link-name 0module %S/../Inputs/empty.swift -autolink-force-load | %FileCheck --check-prefix=FORCE-LOAD-HEX %s // Linux uses a different autolinking mechanism, based on // swift-autolink-extract. This file tests the Darwin mechanism. From 14f9dc6e1567fd30c1b7cff845b8ed8b93fc8a35 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Mon, 3 Jun 2019 20:18:53 -0700 Subject: [PATCH 018/112] Do not try to dsymutil .a files, which is unsupported --- utils/build-script-impl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/build-script-impl b/utils/build-script-impl index 1d22fa1eb55ae..e64d1c78c9395 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -3838,11 +3838,12 @@ for host in "${ALL_HOSTS[@]}"; do # Run dsymutil on executables and shared libraries. # - # Exclude shell scripts. + # Exclude shell scripts and static archives. (cd "${INSTALL_SYMROOT}" && find ./"${CURRENT_PREFIX}" -perm -0111 -type f -print | \ grep -v crashlog.py | \ grep -v symbolication.py | \ + grep -v '.a$' | \ xargs -n 1 -P ${BUILD_JOBS} $(xcrun_find_tool dsymutil)) # Strip executables, shared libraries and static libraries in From 1e38fc30305a953542a0ea0e31609e238c8dba0d Mon Sep 17 00:00:00 2001 From: mishal_shah Date: Mon, 3 Jun 2019 22:50:02 -0700 Subject: [PATCH 019/112] Update master to build with Xcode 11 beta, macOS 10.15, iOS 13, tvOS 13, and watchOS 6 SDKs --- apinotes/Accelerate.apinotes | 61 ----- apinotes/CMakeLists.txt | 2 - apinotes/ScriptingBridge.apinotes | 5 - include/swift/AST/Attr.def | 5 + include/swift/AST/AvailabilitySpec.h | 7 +- include/swift/AST/Decl.h | 4 +- include/swift/AST/DiagnosticsParse.def | 4 +- include/swift/AST/DiagnosticsSema.def | 37 +-- include/swift/Basic/LangOptions.h | 14 +- lib/AST/Availability.cpp | 17 +- lib/Basic/LangOptions.cpp | 17 +- lib/ClangImporter/ImportDecl.cpp | 2 + lib/Frontend/CompilerInvocation.cpp | 3 - lib/Index/Index.cpp | 27 +- lib/Index/IndexSymbol.cpp | 3 +- lib/Parse/ParseExpr.cpp | 2 +- lib/Parse/ParseStmt.cpp | 16 +- lib/PrintAsObjC/PrintAsObjC.cpp | 8 + lib/Sema/TypeCheckAttr.cpp | 206 ++++++++------- lib/Sema/TypeCheckDeclObjC.cpp | 71 +++++- lib/Sema/TypeCheckDeclOverride.cpp | 2 + lib/Sema/TypeCheckObjC.h | 2 + stdlib/public/Darwin/Dispatch/Queue.swift | 26 +- stdlib/public/Darwin/WatchKit/CMakeLists.txt | 4 +- test/FixCode/fixits-apply.swift | 1 + test/FixCode/fixits-apply.swift.result | 1 + test/IDE/complete_cache.swift | 12 +- test/IDE/complete_decl_attribute.swift | 2 + test/IDE/print_ast_tc_decls.swift | 3 + .../class_update_callback_with_stub.swift | 3 +- test/IRGen/objc_methods.swift | 10 +- .../opaque_result_type_availability.swift | 7 +- test/Index/kinds_objc.swift | 5 + .../objc_class_resilience_stubs.swift | 3 +- test/Parse/availability_query.swift | 11 +- test/PrintAsObjC/classes.swift | 2 + .../resilient-ancestry-stable-abi.swift | 2 +- .../CodeFormat/indent-ibaction.swift | 9 +- .../DocumentStructure/Inputs/main.swift | 6 + .../structure.swift.empty.response | 66 ++++- .../structure.swift.foobar.response | 66 ++++- .../structure.swift.response | 66 ++++- test/attr/attr_availability.swift | 18 ++ test/attr/attr_ibaction.swift | 64 +++-- test/attr/attr_ibaction_ios.swift | 88 ++----- test/attr/attr_ibsegueaction.swift | 235 ++++++++++++++++++ test/attr/attr_objc.swift | 18 +- test/attr/attr_objc_resilience.swift | 32 ++- test/attr/attr_objc_resilient_stubs.swift | 7 +- test/lit.cfg | 69 +++-- test/type/opaque_availability.swift | 13 + tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp | 5 +- .../lib/SwiftLang/SwiftLangSupport.cpp | 4 + tools/swift-ide-test/swift-ide-test.cpp | 9 +- validation-test/Runtime/class_stubs.m | 7 +- validation-test/Runtime/class_stubs_weak.m | 5 +- 56 files changed, 1005 insertions(+), 389 deletions(-) delete mode 100644 apinotes/Accelerate.apinotes delete mode 100644 apinotes/ScriptingBridge.apinotes create mode 100644 test/attr/attr_ibsegueaction.swift create mode 100644 test/type/opaque_availability.swift diff --git a/apinotes/Accelerate.apinotes b/apinotes/Accelerate.apinotes deleted file mode 100644 index 12e48ef89e559..0000000000000 --- a/apinotes/Accelerate.apinotes +++ /dev/null @@ -1,61 +0,0 @@ -Name: Accelerate -Enumerators: -- Name: BNNSDataTypeFloatBit - Availability: nonswift -- Name: BNNSDataTypeIntBit - Availability: nonswift -- Name: BNNSDataTypeUIntBit - Availability: nonswift -- Name: BNNSDataTypeIndexedBit - Availability: nonswift -- Name: BNNSDataTypeFloat16 - SwiftPrivate: true -- Name: BNNSDataTypeFloat32 - SwiftPrivate: true -- Name: BNNSDataTypeInt8 - SwiftPrivate: true -- Name: BNNSDataTypeInt16 - SwiftPrivate: true -- Name: BNNSDataTypeInt32 - SwiftPrivate: true -- Name: BNNSDataTypeUInt8 - SwiftPrivate: true -- Name: BNNSDataTypeUInt16 - SwiftPrivate: true -- Name: BNNSDataTypeUInt32 - SwiftPrivate: true -- Name: BNNSDataTypeIndexed8 - SwiftPrivate: true - -- Name: BNNSPoolingFunctionMax - SwiftPrivate: true -- Name: BNNSPoolingFunctionAverage - SwiftPrivate: true - -- Name: BNNSActivationFunctionIdentity - SwiftPrivate: true -- Name: BNNSActivationFunctionRectifiedLinear - SwiftPrivate: true -- Name: BNNSActivationFunctionLeakyRectifiedLinear - SwiftPrivate: true -- Name: BNNSActivationFunctionSigmoid - SwiftPrivate: true -- Name: BNNSActivationFunctionTanh - SwiftPrivate: true -- Name: BNNSActivationFunctionScaledTanh - SwiftPrivate: true -- Name: BNNSActivationFunctionAbs - SwiftPrivate: true -- Name: BNNSActivationFunctionLinear - SwiftPrivate: true -- Name: BNNSActivationFunctionClamp - SwiftPrivate: true -- Name: BNNSActivationFunctionIntegerLinearSaturate - SwiftPrivate: true -- Name: BNNSActivationFunctionIntegerLinearSaturatePerChannel - SwiftPrivate: true -- Name: BNNSActivationFunctionSoftmax - SwiftPrivate: true - -- Name: BNNSFlagsUseClientPtr - SwiftPrivate: true diff --git a/apinotes/CMakeLists.txt b/apinotes/CMakeLists.txt index add121dad40eb..ab1ecd6811d8e 100644 --- a/apinotes/CMakeLists.txt +++ b/apinotes/CMakeLists.txt @@ -1,7 +1,5 @@ set(sources - Accelerate.apinotes Dispatch.apinotes - ScriptingBridge.apinotes os.apinotes ) diff --git a/apinotes/ScriptingBridge.apinotes b/apinotes/ScriptingBridge.apinotes deleted file mode 100644 index a02ce246d2524..0000000000000 --- a/apinotes/ScriptingBridge.apinotes +++ /dev/null @@ -1,5 +0,0 @@ ---- -Name: ScriptingBridge -Classes: -- Name: SBElementArray - SwiftImportAsNonGeneric: true diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def index 2344582806faf..de90e54a3bc66 100644 --- a/include/swift/AST/Attr.def +++ b/include/swift/AST/Attr.def @@ -394,6 +394,7 @@ DECL_ATTR(_private, PrivateImport, SIMPLE_DECL_ATTR(_alwaysEmitIntoClient, AlwaysEmitIntoClient, OnVar | OnSubscript | OnAbstractFunction | UserInaccessible, 83) + SIMPLE_DECL_ATTR(_implementationOnly, ImplementationOnly, OnImport | UserInaccessible, 84) @@ -407,6 +408,10 @@ SIMPLE_DECL_ATTR(_disfavoredOverload, DisfavoredOverload, OnAbstractFunction | OnVar | OnSubscript | UserInaccessible, 87) +SIMPLE_DECL_ATTR(IBSegueAction, IBSegueAction, + OnFunc, + 95) + #undef TYPE_ATTR #undef DECL_ATTR_ALIAS #undef CONTEXTUAL_DECL_ATTR_ALIAS diff --git a/include/swift/AST/AvailabilitySpec.h b/include/swift/AST/AvailabilitySpec.h index 1f02cdf7e8fee..05c0752bffaab 100644 --- a/include/swift/AST/AvailabilitySpec.h +++ b/include/swift/AST/AvailabilitySpec.h @@ -83,7 +83,12 @@ class PlatformVersionConstraintAvailabilitySpec : public AvailabilitySpec { /// The required platform. PlatformKind getPlatform() const { return Platform; } SourceLoc getPlatformLoc() const { return PlatformLoc; } - + + /// Returns true when the constraint is for a platform that was not + /// recognized. This enables better recovery during parsing but should never + /// be true after parsing is completed. + bool isUnrecognizedPlatform() const { return Platform == PlatformKind::none; } + // The platform version to compare against. llvm::VersionTuple getVersion() const { return Version; } SourceRange getVersionSrcRange() const { return VersionSrcRange; } diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 9c01a48579cb4..a05cd74c9a689 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -6069,8 +6069,8 @@ class FuncDecl : public AbstractFunctionDecl { /// True if the function is a defer body. bool isDeferBody() const; - /// Perform basic checking to determine whether the @IBAction attribute can - /// be applied to this function. + /// Perform basic checking to determine whether the @IBAction or + /// @IBSegueAction attribute can be applied to this function. bool isPotentialIBActionTarget() const; }; diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index e1948e35095cf..22658a6b50690 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -1575,8 +1575,8 @@ ERROR(avail_query_expected_version_number,PointsToFirstBadToken, ERROR(avail_query_expected_rparen,PointsToFirstBadToken, "expected ')' in availability query", ()) -ERROR(avail_query_unrecognized_platform_name, - PointsToFirstBadToken, "unrecognized platform name %0", (Identifier)) +WARNING(avail_query_unrecognized_platform_name, + PointsToFirstBadToken, "unrecognized platform name %0", (Identifier)) ERROR(avail_query_disallowed_operator, PointsToFirstBadToken, "'%0' cannot be used in an availability condition", (StringRef)) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index a4c150027d214..0dc310016a11e 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -1169,17 +1169,25 @@ ERROR(invalid_ibdesignable_extension,none, ERROR(invalid_ibinspectable,none, "only instance properties can be declared @%0", (StringRef)) ERROR(invalid_ibaction_decl,none, - "only instance methods can be declared @IBAction", ()) + "only instance methods can be declared @%0", (StringRef)) ERROR(invalid_ibaction_result,none, - "methods declared @IBAction must return 'Void' (not %0)", (Type)) + "methods declared @%0 must %select{|not }1return a value", (StringRef, bool)) ERROR(invalid_ibaction_argument_count,none, - "@IBAction methods %select{must have a single argument" - "|can only have up to 2 arguments}0", (bool)) -ERROR(ibaction_nonobjc_class_argument,none, - "argument to @IBAction method cannot have non-'@objc' class type %0", - (Type)) -ERROR(ibaction_nonobject_argument,none, - "argument to @IBAction method cannot have non-object type %0", (Type)) + "@%0 methods must have %1 to %2 arguments", + (StringRef, int, int)) +ERROR(invalid_ibaction_argument_count_exact,none, + "@%0 methods must have %2 argument%s2", + (StringRef, int, int)) +ERROR(invalid_ibaction_argument_count_max,none, + "@%0 methods must have at most %2 argument%s2", + (StringRef, int, int)) +ERROR(ibsegueaction_objc_method_family,none, + "@%0 method cannot have selector %1 because it has special memory " + "management behavior", (StringRef, ObjCSelector)) +NOTE(fixit_rename_in_swift,none, + "change Swift name to %0", (DeclName)) +NOTE(fixit_rename_in_objc,none, + "change Objective-C selector to %0", (ObjCSelector)) ERROR(no_objc_tagged_pointer_not_class_protocol,none, "@unsafe_no_objc_tagged_pointer can only be applied to class protocols", ()) @@ -3664,8 +3672,8 @@ ERROR(objc_in_generic_extension,none, "extensions of %select{classes from generic context|generic classes}0 " "cannot contain '@objc' members", (bool)) ERROR(objc_in_resilient_extension,none, - "extensions of classes built with library evolution support " - "cannot contain '@objc' members", ()) + "'@objc' %0 in extension of subclass of %1 requires %2 %3", + (DescriptiveDeclKind, Identifier, StringRef, llvm::VersionTuple)) ERROR(objc_operator, none, "operator methods cannot be declared @objc", ()) ERROR(objc_operator_proto, none, @@ -3687,9 +3695,8 @@ ERROR(objc_for_generic_class,none, "generic subclasses of '@objc' classes cannot have an explicit '@objc' " "because they are not directly visible from Objective-C", ()) ERROR(objc_for_resilient_class,none, - "classes built with library evolution support cannot have explicit " - "'@objc' subclasses because they are not directly " - "visible from Objective-C", ()) + "explicit '@objc' on subclass of %0 requires %1 %2", + (Identifier, StringRef, llvm::VersionTuple)) ERROR(objc_getter_for_nonobjc_property,none, "'@objc' getter for non-'@objc' property", ()) ERROR(objc_getter_for_nonobjc_subscript,none, @@ -3730,7 +3737,7 @@ ERROR(objc_extension_not_class,none, "'@objc' can only be applied to an extension of a class", ()) // If you change this, also change enum ObjCReason -#define OBJC_ATTR_SELECT "select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|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)}" +#define OBJC_ATTR_SELECT "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)}" WARNING(attribute_meaningless_when_nonobjc,none, "'@%0' attribute is meaningless on a property that cannot be " diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index 4515a904565ca..d15dfa782198b 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -305,11 +305,6 @@ namespace swift { /// set to true. bool ExperimentalDependenciesIncludeIntrafileOnes = false; - /// Enable experimental support for emitting Objective-C resilient class - /// stubs. This is a language option since it also determines if we admit - /// @objc members in extensions of classes with resilient ancestry. - bool EnableObjCResilientClassStubs = false; - /// Sets the target we are building for and updates platform conditions /// to match. /// @@ -403,6 +398,15 @@ namespace swift { // - watchOS 5.2 bool doesTargetSupportObjCGetClassHook() const; + // The following deployment targets ship an Objective-C runtime supporting + // the objc_loadClassref() entry point: + // + // - macOS 10.15 + // - iOS 13 + // - tvOS 13 + // - watchOS 6 + bool doesTargetSupportObjCClassStubs() const; + /// Returns true if the given platform condition argument represents /// a supported target operating system. /// diff --git a/lib/AST/Availability.cpp b/lib/AST/Availability.cpp index 74507d9c85051..6a1ec00c07b5b 100644 --- a/lib/AST/Availability.cpp +++ b/lib/AST/Availability.cpp @@ -220,13 +220,16 @@ AvailabilityContext AvailabilityInference::inferForType(Type t) { AvailabilityContext ASTContext::getOpaqueTypeAvailability() { auto target = LangOpts.Target; - if (target.isMacOSX() - || target.isiOS() - || target.isWatchOS()) { - // TODO: Update with OS versions that ship with runtime support + if (target.isMacOSX()) { return AvailabilityContext( - VersionRange::allGTE(llvm::VersionTuple(9999,0,0))); + VersionRange::allGTE(llvm::VersionTuple(10,15,0))); + } else if (target.isiOS()) { + return AvailabilityContext( + VersionRange::allGTE(llvm::VersionTuple(13,0,0))); + } else if (target.isWatchOS()) { + return AvailabilityContext( + VersionRange::allGTE(llvm::VersionTuple(6,0,0))); + } else { + return AvailabilityContext::alwaysAvailable(); } - - return AvailabilityContext::alwaysAvailable(); } diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp index a35121f115a78..78b9df9003013 100644 --- a/lib/Basic/LangOptions.cpp +++ b/lib/Basic/LangOptions.cpp @@ -284,11 +284,24 @@ bool LangOptions::doesTargetSupportObjCMetadataUpdateCallback() const { if (Target.isWatchOS()) return !Target.isOSVersionLT(5, 2); - // If we're running on a non-Apple platform, we still want to allow running - // tests that -enable-objc-interop. + // Don't assert if we're running on a non-Apple platform; we still + // want to allow running tests that -enable-objc-interop. return false; } bool LangOptions::doesTargetSupportObjCGetClassHook() const { return doesTargetSupportObjCMetadataUpdateCallback(); } + +bool LangOptions::doesTargetSupportObjCClassStubs() const { + if (Target.isMacOSX()) + return !Target.isMacOSXVersionLT(10, 15); + if (Target.isiOS()) // also returns true on tvOS + return !Target.isOSVersionLT(13); + if (Target.isWatchOS()) + return !Target.isOSVersionLT(6); + + // Don't assert if we're running on a non-Apple platform; we still + // want to allow running tests that -enable-objc-interop. + return false; +} diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 9d872936936fe..af44228b91aaa 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -4169,6 +4169,8 @@ namespace { new (Impl.SwiftContext) IBActionAttr(/*IsImplicit=*/false)); } + // FIXME: Is there an IBSegueAction equivalent? + // Check whether there's some special method to import. if (!forceClassMethod) { if (dc == Impl.importDeclContextOf(decl, decl->getDeclContext()) && diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 3a8724aef592c..1c43b5465d4ff 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -484,9 +484,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.DisableConstraintSolverPerformanceHacks |= Args.hasArg(OPT_disable_constraint_solver_performance_hacks); - Opts.EnableObjCResilientClassStubs = - Args.hasArg(OPT_enable_objc_resilient_class_stubs); - // Must be processed after any other language options that could affect // platform conditions. bool UnsupportedOS, UnsupportedArch; diff --git a/lib/Index/Index.cpp b/lib/Index/Index.cpp index f9f4d84b37a39..d7ad8d47893c1 100644 --- a/lib/Index/Index.cpp +++ b/lib/Index/Index.cpp @@ -1244,17 +1244,24 @@ bool IndexSwiftASTWalker::initFuncDeclIndexSymbol(FuncDecl *D, Info.roles |= (SymbolRoleSet)SymbolRole::Dynamic; } - if (D->getAttrs().hasAttribute()) { - // Relate with type of the first parameter using RelationIBTypeOf. - if (D->hasImplicitSelfDecl()) { - auto paramList = D->getParameters(); - if (!paramList->getArray().empty()) { - auto param = paramList->get(0); - if (auto nominal = param->getType()->getAnyNominal()) { - addRelation(Info, (SymbolRoleSet) SymbolRole::RelationIBTypeOf, nominal); - } - } + if (D->hasImplicitSelfDecl()) { + // If this is an @IBAction or @IBSegueAction method, find the sender + // parameter (if present) and relate the method to its type. + ParamDecl *senderParam = nullptr; + + auto paramList = D->getParameters(); + if (D->getAttrs().hasAttribute()) { + if (paramList->size() > 0) + senderParam = paramList->get(0); + } else if (D->getAttrs().hasAttribute()) { + if (paramList->size() > 1) + senderParam = paramList->get(1); } + + if (senderParam) + if (auto nominal = senderParam->getType()->getAnyNominal()) + addRelation(Info, (SymbolRoleSet) SymbolRole::RelationIBTypeOf, + nominal); } if (auto Group = D->getGroupName()) diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp index 12b55f23a8558..6ca05d2fcb912 100644 --- a/lib/Index/IndexSymbol.cpp +++ b/lib/Index/IndexSymbol.cpp @@ -84,7 +84,8 @@ static bool isUnitTest(const ValueDecl *D) { static void setFuncSymbolInfo(const FuncDecl *FD, SymbolInfo &sym) { sym.Kind = SymbolKind::Function; - if (FD->getAttrs().hasAttribute()) + if (FD->getAttrs().hasAttribute() || + FD->getAttrs().hasAttribute()) sym.Properties |= SymbolProperty::IBAnnotated; if (isUnitTest(FD)) diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 8ac1515c5da10..2577b0943147b 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -3649,7 +3649,7 @@ Parser::parsePlatformVersionConstraintSpec() { if (!Platform.hasValue() || Platform.getValue() == PlatformKind::none) { diagnose(Tok, diag::avail_query_unrecognized_platform_name, PlatformIdentifier); - return nullptr; + Platform = PlatformKind::none; } // Register the platform name as a keyword token. diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index c8a6ef62b409c..decb90dc431e9 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1214,9 +1214,10 @@ static void parseGuardedPattern(Parser &P, GuardedPattern &result, } } -/// Validate availability spec list, emitting diagnostics if necessary. +/// Validate availability spec list, emitting diagnostics if necessary and removing +/// specs for unrecognized platforms. static void validateAvailabilitySpecList(Parser &P, - ArrayRef Specs) { + SmallVectorImpl &Specs) { llvm::SmallSet Platforms; bool HasOtherPlatformSpec = false; @@ -1228,7 +1229,9 @@ static void validateAvailabilitySpecList(Parser &P, return; } + SmallVector RecognizedSpecs; for (auto *Spec : Specs) { + RecognizedSpecs.push_back(Spec); if (isa(Spec)) { HasOtherPlatformSpec = true; continue; @@ -1243,6 +1246,13 @@ static void validateAvailabilitySpecList(Parser &P, } auto *VersionSpec = cast(Spec); + // We keep specs for unrecognized platforms around for error recovery + // during parsing but remove them once parsing is completed. + if (VersionSpec->isUnrecognizedPlatform()) { + RecognizedSpecs.pop_back(); + continue; + } + bool Inserted = Platforms.insert(VersionSpec->getPlatform()).second; if (!Inserted) { // Rule out multiple version specs referring to the same platform. @@ -1260,6 +1270,8 @@ static void validateAvailabilitySpecList(Parser &P, P.diagnose(InsertWildcardLoc, diag::availability_query_wildcard_required) .fixItInsertAfter(InsertWildcardLoc, ", *"); } + + Specs = RecognizedSpecs; } // #available(...) diff --git a/lib/PrintAsObjC/PrintAsObjC.cpp b/lib/PrintAsObjC/PrintAsObjC.cpp index 8466486db4cad..2e61945482306 100644 --- a/lib/PrintAsObjC/PrintAsObjC.cpp +++ b/lib/PrintAsObjC/PrintAsObjC.cpp @@ -594,6 +594,11 @@ class ObjCPrinter : private DeclVisitor, } else if (clangMethod && isNSUInteger(clangMethod->getReturnType())) { os << "NSUInteger"; } else { + // IBSegueAction is placed before whatever return value is chosen. + if (AFD->getAttrs().hasAttribute()) { + os << "IBSegueAction "; + } + OptionalTypeKind kind; Type objTy; std::tie(objTy, kind) = getObjectTypeAndOptionality(AFD, resultTy); @@ -2736,6 +2741,9 @@ class ModuleWriter { "#else\n" "# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg)\n" "#endif\n" + "#if !defined(IBSegueAction)\n" + "# define IBSegueAction\n" + "#endif\n" ; static_assert(SWIFT_MAX_IMPORTED_SIMD_ELEMENTS == 4, "need to add SIMD typedefs here if max elements is increased"); diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 29d4e0cf44326..e8c59e3d4088a 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -32,6 +32,7 @@ #include "swift/Sema/IDETypeChecking.h" #include "clang/Basic/CharInfo.h" #include "llvm/Support/Debug.h" +#include "clang/Basic/CharInfo.h" using namespace swift; @@ -224,6 +225,7 @@ class AttributeEarlyChecker : public AttributeVisitor { } void visitIBActionAttr(IBActionAttr *attr); + void visitIBSegueActionAttr(IBSegueActionAttr *attr); void visitLazyAttr(LazyAttr *attr); void visitIBDesignableAttr(IBDesignableAttr *attr); void visitIBInspectableAttr(IBInspectableAttr *attr); @@ -335,10 +337,19 @@ void AttributeEarlyChecker::visitDynamicAttr(DynamicAttr *attr) { void AttributeEarlyChecker::visitIBActionAttr(IBActionAttr *attr) { - // Only instance methods returning () can be IBActions. + // Only instance methods can be IBActions. const FuncDecl *FD = cast(D); if (!FD->isPotentialIBActionTarget()) - diagnoseAndRemoveAttr(attr, diag::invalid_ibaction_decl); + diagnoseAndRemoveAttr(attr, diag::invalid_ibaction_decl, + attr->getAttrName()); +} + +void AttributeEarlyChecker::visitIBSegueActionAttr(IBSegueActionAttr *attr) { + // Only instance methods can be IBActions. + const FuncDecl *FD = cast(D); + if (!FD->isPotentialIBActionTarget()) + diagnoseAndRemoveAttr(attr, diag::invalid_ibaction_decl, + attr->getAttrName()); } void AttributeEarlyChecker::visitIBDesignableAttr(IBDesignableAttr *attr) { @@ -802,6 +813,7 @@ class AttributeChecker : public AttributeVisitor { void visitFinalAttr(FinalAttr *attr); void visitIBActionAttr(IBActionAttr *attr); + void visitIBSegueActionAttr(IBSegueActionAttr *attr); void visitNSCopyingAttr(NSCopyingAttr *attr); void visitRequiredAttr(RequiredAttr *attr); void visitRethrowsAttr(RethrowsAttr *attr); @@ -846,34 +858,6 @@ class AttributeChecker : public AttributeVisitor { } // end anonymous namespace -static bool checkObjectOrOptionalObjectType(TypeChecker &TC, Decl *D, - ParamDecl *param) { - Type ty = param->getType(); - if (auto unwrapped = ty->getOptionalObjectType()) - ty = unwrapped; - - if (auto classDecl = ty->getClassOrBoundGenericClass()) { - // @objc class types are okay. - if (!classDecl->isObjC()) { - TC.diagnose(D, diag::ibaction_nonobjc_class_argument, - param->getType()) - .highlight(param->getSourceRange()); - return true; - } - } else if (ty->isObjCExistentialType() || ty->isAny()) { - // @objc existential types are okay, as is Any. - // Nothing to do. - } else { - // No other types are permitted. - TC.diagnose(D, diag::ibaction_nonobject_argument, - param->getType()) - .highlight(param->getSourceRange()); - return true; - } - - return false; -} - static bool isiOS(TypeChecker &TC) { return TC.getLangOpts().Target.isiOS(); } @@ -1100,72 +1084,124 @@ visitDynamicMemberLookupAttr(DynamicMemberLookupAttr *attr) { } } +static bool +validateIBActionSignature(TypeChecker &TC, DeclAttribute *attr, FuncDecl *FD, + unsigned minParameters, unsigned maxParameters, + bool hasVoidResult = true) { + bool valid = true; + + auto arity = FD->getParameters()->size(); + auto resultType = FD->getResultInterfaceType(); + + if (arity < minParameters || arity > maxParameters) { + auto diagID = diag::invalid_ibaction_argument_count; + if (minParameters == maxParameters) + diagID = diag::invalid_ibaction_argument_count_exact; + else if (minParameters == 0) + diagID = diag::invalid_ibaction_argument_count_max; + TC.diagnose(FD, diagID, attr->getAttrName(), minParameters, maxParameters); + valid = false; + } + + if (resultType->isVoid() != hasVoidResult) { + TC.diagnose(FD, diag::invalid_ibaction_result, attr->getAttrName(), + hasVoidResult); + valid = false; + } + + // We don't need to check here that parameter or return types are + // ObjC-representable; IsObjCRequest will validate that. + + if (!valid) + attr->setInvalid(); + return valid; +} + void AttributeChecker::visitIBActionAttr(IBActionAttr *attr) { - // IBActions instance methods must have type Class -> (...) -> (). auto *FD = cast(D); - Type CurriedTy = FD->getMethodInterfaceType(); - Type ResultTy = CurriedTy->castTo()->getResult(); - if (!ResultTy->isEqual(TupleType::getEmpty(TC.Context))) { - TC.diagnose(D, diag::invalid_ibaction_result, ResultTy); - attr->setInvalid(); + + if (isRelaxedIBAction(TC)) + // iOS, tvOS, and watchOS allow 0-2 parameters to an @IBAction method. + validateIBActionSignature(TC, attr, FD, /*minParams=*/0, /*maxParams=*/2); + else + // macOS allows 1 parameter to an @IBAction method. + validateIBActionSignature(TC, attr, FD, /*minParams=*/1, /*maxParams=*/1); +} + +void AttributeChecker::visitIBSegueActionAttr(IBSegueActionAttr *attr) { + auto *FD = cast(D); + if (!validateIBActionSignature(TC, attr, FD, + /*minParams=*/1, /*maxParams=*/3, + /*hasVoidResult=*/false)) return; - } - auto paramList = FD->getParameters(); - bool relaxedIBActionUsedOnOSX = false; - bool Valid = true; - switch (paramList->size()) { - case 0: - // (iOS only) No arguments. - if (!isRelaxedIBAction(TC)) { - relaxedIBActionUsedOnOSX = true; - break; - } - break; - case 1: - // One argument. May be a scalar on iOS/watchOS (because of WatchKit). - if (isRelaxedIBAction(TC)) { - // Do a rough check to allow any ObjC-representable struct or enum type - // on iOS. - Type ty = paramList->get(0)->getType(); - if (auto nominal = ty->getAnyNominal()) - if (isa(nominal) || isa(nominal)) - if (!nominal->isOptionalDecl()) - if (ty->isTriviallyRepresentableIn(ForeignLanguage::ObjectiveC, - cast(D))) - break; // Looks ok. - } - if (checkObjectOrOptionalObjectType(TC, D, paramList->get(0))) - Valid = false; + // If the IBSegueAction method's selector belongs to one of the ObjC method + // families (like -newDocumentSegue: or -copyScreen), it would return the + // object at +1, but the caller would expect it to be +0 and would therefore + // leak it. + // + // To prevent that, diagnose if the selector belongs to one of the method + // families and suggest that the user change the Swift name or Obj-C selector. + auto currentSelector = FD->getObjCSelector(); + + SmallString<32> prefix("make"); + + switch (currentSelector.getSelectorFamily()) { + case ObjCSelectorFamily::None: + // No error--exit early. + return; + + case ObjCSelectorFamily::Alloc: + case ObjCSelectorFamily::Init: + case ObjCSelectorFamily::New: + // Fix-it will replace the "alloc"/"init"/"new" in the selector with "make". break; - case 2: - // (iOS/watchOS only) Two arguments, the second of which is a UIEvent. - // We don't currently enforce the UIEvent part. - if (!isRelaxedIBAction(TC)) { - relaxedIBActionUsedOnOSX = true; - break; - } - if (checkObjectOrOptionalObjectType(TC, D, paramList->get(0))) - Valid = false; - if (checkObjectOrOptionalObjectType(TC, D, paramList->get(1))) - Valid = false; + + case ObjCSelectorFamily::Copy: + // Fix-it will replace the "copy" in the selector with "makeCopy". + prefix += "Copy"; break; - default: - // No platform allows an action signature with more than two arguments. - TC.diagnose(D, diag::invalid_ibaction_argument_count, - isRelaxedIBAction(TC)); - Valid = false; + + case ObjCSelectorFamily::MutableCopy: + // Fix-it will replace the "mutable" in the selector with "makeMutable". + prefix += "Mutable"; break; } - if (relaxedIBActionUsedOnOSX) { - TC.diagnose(D, diag::invalid_ibaction_argument_count, - /*relaxedIBAction=*/false); - Valid = false; + // Emit the actual error. + TC.diagnose(FD, diag::ibsegueaction_objc_method_family, + attr->getAttrName(), currentSelector); + + // The rest of this is just fix-it generation. + + /// Replaces the first word of \c oldName with the prefix, where "word" is a + /// sequence of lowercase characters. + auto replacingPrefix = [&](Identifier oldName) -> Identifier { + SmallString<32> scratch = prefix; + scratch += oldName.str().drop_while(clang::isLowercase); + return TC.Context.getIdentifier(scratch); + }; + + // Suggest changing the Swift name of the method, unless there is already an + // explicit selector. + if (!FD->getAttrs().hasAttribute() || + !FD->getAttrs().getAttribute()->hasName()) { + auto newSwiftBaseName = replacingPrefix(FD->getBaseName().getIdentifier()); + auto argumentNames = FD->getFullName().getArgumentNames(); + DeclName newSwiftName(TC.Context, newSwiftBaseName, argumentNames); + + auto diag = TC.diagnose(FD, diag::fixit_rename_in_swift, newSwiftName); + fixDeclarationName(diag, FD, newSwiftName); } - if (!Valid) - attr->setInvalid(); + // Suggest changing just the selector to one with a different first piece. + auto oldPieces = currentSelector.getSelectorPieces(); + SmallVector newPieces(oldPieces.begin(), oldPieces.end()); + newPieces[0] = replacingPrefix(newPieces[0]); + ObjCSelector newSelector(TC.Context, currentSelector.getNumArgs(), newPieces); + + auto diag = TC.diagnose(FD, diag::fixit_rename_in_objc, newSelector); + fixDeclarationObjCName(diag, FD, currentSelector, newSelector); } /// Get the innermost enclosing declaration for a declaration. diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp index 318f36c45291d..dc607f0e60e71 100644 --- a/lib/Sema/TypeCheckDeclObjC.cpp +++ b/lib/Sema/TypeCheckDeclObjC.cpp @@ -35,6 +35,7 @@ bool swift::shouldDiagnoseObjCReason(ObjCReason reason, ASTContext &ctx) { case ObjCReason::ExplicitlyObjC: case ObjCReason::ExplicitlyIBOutlet: case ObjCReason::ExplicitlyIBAction: + case ObjCReason::ExplicitlyIBSegueAction: case ObjCReason::ExplicitlyNSManaged: case ObjCReason::MemberOfObjCProtocol: case ObjCReason::OverridesObjC: @@ -63,6 +64,7 @@ unsigned swift::getObjCDiagnosticAttrKind(ObjCReason reason) { case ObjCReason::ExplicitlyObjC: case ObjCReason::ExplicitlyIBOutlet: case ObjCReason::ExplicitlyIBAction: + case ObjCReason::ExplicitlyIBSegueAction: case ObjCReason::ExplicitlyNSManaged: case ObjCReason::MemberOfObjCProtocol: case ObjCReason::OverridesObjC: @@ -366,6 +368,40 @@ static bool checkObjCInForeignClassContext(const ValueDecl *VD, return true; } +static VersionRange getMinOSVersionForClassStubs(const llvm::Triple &target) { + if (target.isMacOSX()) + return VersionRange::allGTE(llvm::VersionTuple(10, 15, 0)); + if (target.isiOS()) // also returns true on tvOS + return VersionRange::allGTE(llvm::VersionTuple(13, 0, 0)); + if (target.isWatchOS()) + return VersionRange::allGTE(llvm::VersionTuple(6, 0, 0)); + return VersionRange::all(); +} + +static bool checkObjCClassStubAvailability(ASTContext &ctx, const Decl *decl) { + auto minRange = getMinOSVersionForClassStubs(ctx.LangOpts.Target); + + auto targetRange = AvailabilityContext::forDeploymentTarget(ctx); + if (targetRange.getOSVersion().isContainedIn(minRange)) + return true; + + auto declRange = AvailabilityInference::availableRange(decl, ctx); + return declRange.getOSVersion().isContainedIn(minRange); +} + +static const ClassDecl *getResilientAncestor(ModuleDecl *mod, + const ClassDecl *classDecl) { + auto *superclassDecl = classDecl; + + for (;;) { + if (superclassDecl->hasResilientMetadata(mod, + ResilienceExpansion::Maximal)) + return superclassDecl; + + superclassDecl = superclassDecl->getSuperclassDecl(); + } +} + /// Check whether the given declaration occurs within a constrained /// extension, or an extension of a generic class, or an /// extension of an Objective-C runtime visible class, and @@ -386,13 +422,21 @@ static bool checkObjCInExtensionContext(const ValueDecl *value, auto *mod = value->getModuleContext(); auto &ctx = mod->getASTContext(); - if (!ctx.LangOpts.EnableObjCResilientClassStubs) { + if (!checkObjCClassStubAvailability(ctx, value)) { if (classDecl->checkAncestry().contains( AncestryFlags::ResilientOther) || classDecl->hasResilientMetadata(mod, ResilienceExpansion::Maximal)) { if (diagnose) { - value->diagnose(diag::objc_in_resilient_extension); + auto &target = ctx.LangOpts.Target; + auto platform = prettyPlatformString(targetPlatform(ctx.LangOpts)); + auto range = getMinOSVersionForClassStubs(target); + auto *ancestor = getResilientAncestor(mod, classDecl); + value->diagnose(diag::objc_in_resilient_extension, + value->getDescriptiveKind(), + ancestor->getName(), + platform, + range.getLowerEndpoint()); } return true; } @@ -1050,16 +1094,26 @@ static Optional shouldMarkClassAsObjC(const ClassDecl *CD) { } // If the class has resilient ancestry, @objc just controls the runtime - // name unless -enable-resilient-objc-class-stubs is enabled. + // name unless all targets where the class is available support + // class stubs. if (ancestry.contains(AncestryFlags::ResilientOther) && - !ctx.LangOpts.EnableObjCResilientClassStubs) { + !checkObjCClassStubAvailability(ctx, CD)) { if (attr->hasName()) { const_cast(CD)->getAttrs().add( new (ctx) ObjCRuntimeNameAttr(*attr)); return None; } - ctx.Diags.diagnose(attr->getLocation(), diag::objc_for_resilient_class) + + auto &target = ctx.LangOpts.Target; + auto platform = prettyPlatformString(targetPlatform(ctx.LangOpts)); + auto range = getMinOSVersionForClassStubs(target); + auto *ancestor = getResilientAncestor(CD->getParentModule(), CD); + ctx.Diags.diagnose(attr->getLocation(), + diag::objc_for_resilient_class, + ancestor->getName(), + platform, + range.getLowerEndpoint()) .fixItRemove(attr->getRangeWithAt()); } @@ -1085,7 +1139,7 @@ static Optional shouldMarkClassAsObjC(const ClassDecl *CD) { } if (ancestry.contains(AncestryFlags::ResilientOther) && - !ctx.LangOpts.EnableObjCResilientClassStubs) { + !checkObjCClassStubAvailability(ctx, CD)) { return None; } @@ -1173,7 +1227,8 @@ Optional shouldMarkAsObjC(const ValueDecl *VD, bool allowImplicit) { return None; } } - // @IBOutlet, @IBAction, @NSManaged, and @GKInspectable imply @objc. + // @IBOutlet, @IBAction, @IBSegueAction, @NSManaged, and @GKInspectable imply + // @objc. // // @IBInspectable and @GKInspectable imply @objc quietly in Swift 3 // (where they warn on failure) and loudly in Swift 4 (error on failure). @@ -1181,6 +1236,8 @@ Optional shouldMarkAsObjC(const ValueDecl *VD, bool allowImplicit) { return ObjCReason(ObjCReason::ExplicitlyIBOutlet); if (VD->getAttrs().hasAttribute()) return ObjCReason(ObjCReason::ExplicitlyIBAction); + if (VD->getAttrs().hasAttribute()) + return ObjCReason(ObjCReason::ExplicitlyIBSegueAction); if (VD->getAttrs().hasAttribute()) return ObjCReason(ObjCReason::ExplicitlyIBInspectable); if (VD->getAttrs().hasAttribute()) diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index ec8c88ad189fe..9c010bb64cc66 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -1247,6 +1247,7 @@ namespace { #define UNINTERESTING_ATTR(CLASS) \ void visit##CLASS##Attr(CLASS##Attr *) {} + // Please keep these alphabetical. UNINTERESTING_ATTR(AccessControl) UNINTERESTING_ATTR(Alignment) UNINTERESTING_ATTR(AlwaysEmitIntoClient) @@ -1264,6 +1265,7 @@ namespace { UNINTERESTING_ATTR(IBDesignable) UNINTERESTING_ATTR(IBInspectable) UNINTERESTING_ATTR(IBOutlet) + UNINTERESTING_ATTR(IBSegueAction) UNINTERESTING_ATTR(Indirect) UNINTERESTING_ATTR(Inline) UNINTERESTING_ATTR(Optimize) diff --git a/lib/Sema/TypeCheckObjC.h b/lib/Sema/TypeCheckObjC.h index aca888dd777fe..39af513ef8bd5 100644 --- a/lib/Sema/TypeCheckObjC.h +++ b/lib/Sema/TypeCheckObjC.h @@ -49,6 +49,8 @@ class ObjCReason { ExplicitlyIBOutlet, /// Has an explicit '@IBAction' attribute. ExplicitlyIBAction, + /// Has an explicit '@IBSegueAction' attribute. + ExplicitlyIBSegueAction, /// Has an explicit '@NSManaged' attribute. ExplicitlyNSManaged, /// Is a member of an @objc protocol. diff --git a/stdlib/public/Darwin/Dispatch/Queue.swift b/stdlib/public/Darwin/Dispatch/Queue.swift index 6f4c1514a8754..9b38fb92cf258 100644 --- a/stdlib/public/Darwin/Dispatch/Queue.swift +++ b/stdlib/public/Darwin/Dispatch/Queue.swift @@ -94,21 +94,25 @@ extension DispatchQueue { internal func _attr(attr: __OS_dispatch_queue_attr?) -> __OS_dispatch_queue_attr? { if #available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) { - switch self { - case .inherit: - // DISPATCH_AUTORELEASE_FREQUENCY_INHERIT - return __dispatch_queue_attr_make_with_autorelease_frequency(attr, __dispatch_autorelease_frequency_t(0)) - case .workItem: - // DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM - return __dispatch_queue_attr_make_with_autorelease_frequency(attr, __dispatch_autorelease_frequency_t(1)) - case .never: - // DISPATCH_AUTORELEASE_FREQUENCY_NEVER - return __dispatch_queue_attr_make_with_autorelease_frequency(attr, __dispatch_autorelease_frequency_t(2)) - } + return __dispatch_queue_attr_make_with_autorelease_frequency(attr, self._rawValue) } else { return attr } } + + internal var _rawValue: __dispatch_autorelease_frequency_t { + switch self { + case .inherit: + // DISPATCH_AUTORELEASE_FREQUENCY_INHERIT + return (__dispatch_autorelease_frequency_t(rawValue: 0) as Optional)! + case .workItem: + // DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM + return (__dispatch_autorelease_frequency_t(rawValue: 1) as Optional)! + case .never: + // DISPATCH_AUTORELEASE_FREQUENCY_NEVER + return (__dispatch_autorelease_frequency_t(rawValue: 2) as Optional)! + } + } } public class func concurrentPerform(iterations: Int, execute work: (Int) -> Void) { diff --git a/stdlib/public/Darwin/WatchKit/CMakeLists.txt b/stdlib/public/Darwin/WatchKit/CMakeLists.txt index f4368d2b65fa3..f1d945ec8f98e 100644 --- a/stdlib/public/Darwin/WatchKit/CMakeLists.txt +++ b/stdlib/public/Darwin/WatchKit/CMakeLists.txt @@ -8,9 +8,7 @@ add_swift_target_library(swiftWatchKit ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}" - TARGET_SDKS IOS IOS_SIMULATOR WATCHOS WATCHOS_SIMULATOR - SWIFT_MODULE_DEPENDS_IOS Darwin CoreFoundation CoreGraphics CoreImage CoreLocation Dispatch Foundation MapKit ObjectiveC QuartzCore UIKit # auto-updated - os + TARGET_SDKS WATCHOS WATCHOS_SIMULATOR SWIFT_MODULE_DEPENDS_WATCHOS Darwin CoreFoundation CoreGraphics CoreLocation Dispatch Foundation HomeKit MapKit ObjectiveC SceneKit simd UIKit # auto-updated FRAMEWORK_DEPENDS_WEAK WatchKit SWIFT_COMPILE_FLAGS_WATCHOS -Xfrontend -disable-autolink-framework -Xfrontend CoreText diff --git a/test/FixCode/fixits-apply.swift b/test/FixCode/fixits-apply.swift index c2d7148142f6e..eee2c6bddbc4d 100644 --- a/test/FixCode/fixits-apply.swift +++ b/test/FixCode/fixits-apply.swift @@ -246,6 +246,7 @@ protocol NonObjCProtocol {} @IBOutlet private var ibout6: [String: String]! @IBInspectable static private var ibinspect1: IBIssues! @IBAction static func ibact() {} + @IBSegueAction static func ibsegact(_: String, _: IBIssues) -> IBIssues { return self } } @IBDesignable extension SomeProt {} diff --git a/test/FixCode/fixits-apply.swift.result b/test/FixCode/fixits-apply.swift.result index 1e3e4861c0318..5cb79ac3b70b3 100644 --- a/test/FixCode/fixits-apply.swift.result +++ b/test/FixCode/fixits-apply.swift.result @@ -246,6 +246,7 @@ protocol NonObjCProtocol {} @IBOutlet private var ibout6: [String: String]! @IBInspectable static private var ibinspect1: IBIssues! @IBAction static func ibact() {} + @IBSegueAction static func ibsegact(_: String, _: IBIssues) -> IBIssues { return self } } @IBDesignable extension SomeProt {} diff --git a/test/IDE/complete_cache.swift b/test/IDE/complete_cache.swift index 2a21a44f82568..0cf4c25c2bef7 100644 --- a/test/IDE/complete_cache.swift +++ b/test/IDE/complete_cache.swift @@ -1,13 +1,13 @@ -// RUN: rm -rf %t.ccp %t.ccp.bak +// RUN: rm -rf %t.ccp %t.ccp.bak %t.mcp -// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=CLANG_UNQUAL_1 -completion-cache-path=%t.ccp > %t.ccp1.compl.txt +// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=CLANG_UNQUAL_1 -completion-cache-path=%t.ccp -module-cache-path %t.mcp > %t.ccp1.compl.txt // RUN: cp -r %t.ccp %t.ccp.bak // RUN: %FileCheck %s -check-prefix=CLANG_CTYPES < %t.ccp1.compl.txt // RUN: %FileCheck %s -check-prefix=CLANG_MACROS < %t.ccp1.compl.txt // RUN: %FileCheck %s -check-prefix=CLANG_DARWIN < %t.ccp1.compl.txt // RUN: %FileCheck %s -check-prefix=CLANG_DARWIN_NEG < %t.ccp1.compl.txt -// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=CLANG_UNQUAL_1 -completion-cache-path=%t.ccp > %t.ccp2.compl.txt +// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=CLANG_UNQUAL_1 -completion-cache-path=%t.ccp -module-cache-path %t.mcp > %t.ccp2.compl.txt // RUN: %FileCheck %s -check-prefix=CLANG_CTYPES < %t.ccp2.compl.txt // RUN: %FileCheck %s -check-prefix=CLANG_MACROS < %t.ccp2.compl.txt // RUN: %FileCheck %s -check-prefix=CLANG_DARWIN < %t.ccp2.compl.txt @@ -24,7 +24,7 @@ // Qualified. -// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=CLANG_QUAL_MACROS_1 -completion-cache-path=%t.ccp > %t.macros.ccp1.compl.txt +// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=CLANG_QUAL_MACROS_1 -completion-cache-path=%t.ccp -module-cache-path %t.mcp > %t.macros.ccp1.compl.txt // RUN: %FileCheck %s -check-prefix=CLANG_QUAL_MACROS_1 -check-prefix=CLANG_QUAL_MACROS_1-%target-runtime < %t.macros.ccp1.compl.txt // RUN: diff -r -u %t.ccp %t.ccp.bak @@ -33,14 +33,14 @@ // Qualified with dot. -// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=CLANG_QUAL_MACROS_2 -completion-cache-path=%t.ccp > %t.macros2.ccp1.compl.txt +// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=CLANG_QUAL_MACROS_2 -completion-cache-path=%t.ccp -module-cache-path %t.mcp > %t.macros2.ccp1.compl.txt // RUN: %FileCheck %s -check-prefix=CLANG_QUAL_MACROS_2 -check-prefix=CLANG_QUAL_MACROS_2-%target-runtime < %t.macros2.ccp1.compl.txt // Check the individual cache item. // RUN: %target-swift-ide-test -dump-completion-cache %t.ccp/macros-dot-* | %FileCheck %s -check-prefix=CLANG_QUAL_MACROS_2 // Qualified private with dot. -// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=CLANG_QUAL_STRING -completion-cache-path=%t.ccp > %t.string.ccp1.compl.txt +// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=CLANG_QUAL_STRING -completion-cache-path=%t.ccp -module-cache-path %t.mcp > %t.string.ccp1.compl.txt // RUN: %FileCheck %s -check-prefix=CLANG_QUAL_STRING < %t.string.ccp1.compl.txt diff --git a/test/IDE/complete_decl_attribute.swift b/test/IDE/complete_decl_attribute.swift index 5636a674c93ae..28ddce79748f1 100644 --- a/test/IDE/complete_decl_attribute.swift +++ b/test/IDE/complete_decl_attribute.swift @@ -57,6 +57,7 @@ func method(){} // KEYWORD2-NEXT: Keyword/None: warn_unqualified_access[#Func Attribute#]; name=warn_unqualified_access{{$}} // KEYWORD2-NEXT: Keyword/None: usableFromInline[#Func Attribute#]; name=usableFromInline // KEYWORD2-NEXT: Keyword/None: discardableResult[#Func Attribute#]; name=discardableResult +// KEYWORD2-NEXT: Keyword/None: IBSegueAction[#Func Attribute#]; name=IBSegueAction{{$}} // KEYWORD2-NEXT: End completions @#^KEYWORD3^# @@ -222,6 +223,7 @@ struct _S { // KEYWORD_LAST-NEXT: Keyword/None: discardableResult[#Declaration Attribute#]; name=discardableResult // KEYWORD_LAST-NEXT: Keyword/None: GKInspectable[#Declaration Attribute#]; name=GKInspectable{{$}} // KEYWORD_LAST-NEXT: Keyword/None: _propertyWrapper[#Declaration Attribute#]; name=_propertyWrapper +// KEYWORD_LAST-NEXT: Keyword/None: IBSegueAction[#Declaration Attribute#]; name=IBSegueAction{{$}} // KEYWORD_LAST-NOT: Keyword // KEYWORD_LAST: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct // KEYWORD_LAST: End completions diff --git a/test/IDE/print_ast_tc_decls.swift b/test/IDE/print_ast_tc_decls.swift index aa5ef08c4ef5b..31033c0b8b0f5 100644 --- a/test/IDE/print_ast_tc_decls.swift +++ b/test/IDE/print_ast_tc_decls.swift @@ -538,6 +538,9 @@ class d0170_TestAvailability { @IBAction func anAction(_: AnyObject) {} // PASS_COMMON-NEXT: {{^}} @objc @IBAction func anAction(_: AnyObject){{$}} + @IBSegueAction func aSegueAction(_ coder: AnyObject, sender: AnyObject, identifier: AnyObject?) -> Any? { fatalError() } +// PASS_COMMON-NEXT: {{^}} @objc @IBSegueAction func aSegueAction(_ coder: AnyObject, sender: AnyObject, identifier: AnyObject?) -> Any?{{$}} + @IBDesignable class ADesignableClass {} // PASS_COMMON-NEXT: {{^}} @IBDesignable class ADesignableClass {{{$}} diff --git a/test/IRGen/class_update_callback_with_stub.swift b/test/IRGen/class_update_callback_with_stub.swift index 480ce50a1cba9..f22bd47f09369 100644 --- a/test/IRGen/class_update_callback_with_stub.swift +++ b/test/IRGen/class_update_callback_with_stub.swift @@ -3,7 +3,7 @@ // RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_struct.swiftmodule -I %t %S/../Inputs/resilient_struct.swift // RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module-path %t/resilient_class.swiftmodule -enable-library-evolution %S/../Inputs/resilient_class.swift // RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module-path %t/resilient_objc_class.swiftmodule -enable-library-evolution %S/../Inputs/resilient_objc_class.swift -// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -I %t -emit-ir -enable-library-evolution -enable-resilient-objc-class-stubs %s > %t/out +// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -I %t -emit-ir -enable-library-evolution -target %target-next-stable-abi-triple %s > %t/out // RUN: %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-runtime -DINT=i%target-ptrsize < %t/out // RUN: %FileCheck %s --check-prefix=NEGATIVE < %t/out @@ -12,6 +12,7 @@ import resilient_class import resilient_objc_class // REQUIRES: objc_interop +// REQUIRES: swift_stable_abi // -- Nominal type descriptor for ResilientSubclass // the interesting part is the 'extra class flags' field has a value of 1. diff --git a/test/IRGen/objc_methods.swift b/test/IRGen/objc_methods.swift index cef0ce1113765..a6e2d694bc8e7 100644 --- a/test/IRGen/objc_methods.swift +++ b/test/IRGen/objc_methods.swift @@ -23,6 +23,7 @@ class Foo: Fooable { func bar() {} @objc func baz() {} @IBAction func garply(_: AnyObject?) {} + @IBSegueAction func harply(_: AnyObject?, _: AnyObject) -> AnyObject? {fatalError()} @objc func block(_: (Int) -> Int) {} @objc func block2(_: (Int,Int) -> Int) {} @@ -44,14 +45,15 @@ class ObjcDestructible: NSObject { // CHECK: [[NO_ARGS_SIGNATURE:@.*]] = private unnamed_addr constant [8 x i8] c"v16@0:8\00" // CHECK: [[GARPLY_SIGNATURE:@.*]] = private unnamed_addr constant [11 x i8] c"v24@0:8@16\00" +// CHECK: [[HARPLY_SIGNATURE:@.*]] = private unnamed_addr constant [14 x i8] c"@32@0:8@16@24\00" // CHECK: [[BLOCK_SIGNATURE_TRAD:@.*]] = private unnamed_addr constant [12 x i8] c"v24@0:8@?16\00" // CHECK-macosx: [[FAIL_SIGNATURE:@.*]] = private unnamed_addr constant [12 x i8] c"c24@0:8^@16\00" // CHECK-ios: [[FAIL_SIGNATURE:@.*]] = private unnamed_addr constant [12 x i8] c"B24@0:8^@16\00" // CHECK-tvos: [[FAIL_SIGNATURE:@.*]] = private unnamed_addr constant [12 x i8] c"B24@0:8^@16\00" // CHECK: @_INSTANCE_METHODS__TtC12objc_methods3Foo = private constant { {{.*}}] } { // CHECK: i32 24, -// CHECK: i32 9, -// CHECK: [9 x { i8*, i8*, i8* }] [{ +// CHECK: i32 10, +// CHECK: [10 x { i8*, i8*, i8* }] [{ // CHECK: i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01L_selector_data(baz)", i64 0, i64 0), // CHECK: i8* getelementptr inbounds ([8 x i8], [8 x i8]* [[NO_ARGS_SIGNATURE]], i64 0, i64 0), // CHECK: i8* bitcast (void (i8*, i8*)* @"$s12objc_methods3FooC3bazyyFTo" to i8*) @@ -60,6 +62,10 @@ class ObjcDestructible: NSObject { // CHECK: i8* getelementptr inbounds ([11 x i8], [11 x i8]* [[GARPLY_SIGNATURE]], i64 0, i64 0), // CHECK: i8* bitcast (void (i8*, i8*, i8*)* @"$s12objc_methods3FooC6garplyyyyXlSgFTo" to i8*) // CHECK: }, { +// CHECK: i8* getelementptr inbounds ([9 x i8], [9 x i8]* @"\01L_selector_data(harply::)", i64 0, i64 0), +// CHECK: i8* getelementptr inbounds ([14 x i8], [14 x i8]* [[HARPLY_SIGNATURE]], i64 0, i64 0), +// CHECK: i8* bitcast (i8* (i8*, i8*, i8*, i8*)* @"$s12objc_methods3FooC6harplyyyXlSgAE_yXltFTo" to i8*) +// CHECK: }, { // CHECK: i8* getelementptr inbounds ([7 x i8], [7 x i8]* @"\01L_selector_data(block:)", i64 0, i64 0), // CHECK: i8* getelementptr inbounds ([12 x i8], [12 x i8]* [[BLOCK_SIGNATURE_TRAD]], i64 0, i64 0), // CHECK: i8* bitcast (void (i8*, i8*, i64 (i64)*)* @"$s12objc_methods3FooC5blockyyS2iXEFTo" to i8*) diff --git a/test/IRGen/opaque_result_type_availability.swift b/test/IRGen/opaque_result_type_availability.swift index 972bd434699dd..b5fdfb74cfb5e 100644 --- a/test/IRGen/opaque_result_type_availability.swift +++ b/test/IRGen/opaque_result_type_availability.swift @@ -1,12 +1,11 @@ // RUN: %target-swift-frontend -target x86_64-apple-macosx10.9 -Onone -emit-ir %s | %FileCheck --check-prefix=MAYBE-AVAILABLE %s -// TODO: Build with a macos deployment target that unconditionally supports opaque result types -// R/UN: %target-swift-frontend -target x86_64-apple-macosx10.9999 -Onone -emit-ir %s | %FileCheck --check-prefix=ALWAYS-AVAILABLE %s +// RUN: %target-swift-frontend -target x86_64-apple-macosx10.15 -Onone -emit-ir %s | %FileCheck --check-prefix=ALWAYS-AVAILABLE %s // REQUIRES: OS=macosx protocol P {} extension Int: P {} -@available(macOS 9999, *) +@available(macOS 10.15, *) func foo() -> some P { return 1738 } @@ -14,7 +13,7 @@ func foo() -> some P { @_silgen_name("external") func generic(x: T, y: T) -@available(macOS 9999, *) +@available(macOS 10.15, *) public func main() { generic(x: foo(), y: foo()) } diff --git a/test/Index/kinds_objc.swift b/test/Index/kinds_objc.swift index 1abc2a36181ca..a64d6a15b7b27 100644 --- a/test/Index/kinds_objc.swift +++ b/test/Index/kinds_objc.swift @@ -3,12 +3,17 @@ @objc class TargetForIBAction {} // CHECK: [[@LINE-1]]:13 | class/Swift | TargetForIBAction | [[TargetForIBAction_USR:.*]] | Def | +@objc class TargetForIBSegueAction {} +// CHECK: [[@LINE-1]]:13 | class/Swift | TargetForIBSegueAction | [[TargetForIBSegueAction_USR:.*]] | Def | class AttrAnnots { @IBOutlet var iboutletString: AnyObject? // CHECK: [[@LINE-1]]:17 | instance-property(IB)/Swift | iboutletString | @IBAction func someibaction(o: TargetForIBAction) {} // CHECK: [[@LINE-1]]:18 | instance-method(IB)/Swift | someibaction(o:) | {{.*}} | Def,Dyn,RelChild,RelIBType | rel: 2 // CHECK-NEXT: RelIBType | class/Swift | TargetForIBAction | [[TargetForIBAction_USR]] + @IBSegueAction func someibsegue(coder: Any, o: TargetForIBSegueAction) -> Any {} + // CHECK: [[@LINE-1]]:23 | instance-method(IB)/Swift | someibsegue(coder:o:) | {{.*}} | Def,Dyn,RelChild,RelIBType | rel: 2 + // CHECK-NEXT: RelIBType | class/Swift | TargetForIBSegueAction | [[TargetForIBSegueAction_USR]] @GKInspectable var gkString = "gk" // CHECK: [[@LINE-1]]:22 | instance-property(GKI)/Swift | gkString | } diff --git a/test/Interpreter/objc_class_resilience_stubs.swift b/test/Interpreter/objc_class_resilience_stubs.swift index 595551ba7aa50..f84c042523a59 100644 --- a/test/Interpreter/objc_class_resilience_stubs.swift +++ b/test/Interpreter/objc_class_resilience_stubs.swift @@ -6,13 +6,14 @@ // RUN: %target-build-swift-dylib(%t/%target-library-name(resilient_objc_class)) -I %t -L %t -lresilient_struct -enable-library-evolution %S/../Inputs/resilient_objc_class.swift -emit-module -emit-module-path %t/resilient_objc_class.swiftmodule // RUN: %target-codesign %t/%target-library-name(resilient_objc_class) -// RUN: %target-build-swift %s -L %t -I %t -lresilient_struct -lresilient_objc_class -o %t/main %target-rpath(%t) -Xfrontend -enable-resilient-objc-class-stubs +// RUN: %target-build-swift %s -L %t -I %t -lresilient_struct -lresilient_objc_class -o %t/main %target-rpath(%t) -target %target-next-stable-abi-triple // RUN: %target-codesign %t/main // RUN: %target-run %t/main %t/%target-library-name(resilient_struct) %t/%target-library-name(resilient_objc_class) // REQUIRES: executable_test // REQUIRES: objc_interop +// REQUIRES: swift_stable_abi import StdlibUnittest import Foundation diff --git a/test/Parse/availability_query.swift b/test/Parse/availability_query.swift index 96a87cfa7c7ec..eea8399c4ffaa 100644 --- a/test/Parse/availability_query.swift +++ b/test/Parse/availability_query.swift @@ -39,10 +39,11 @@ if #available(OSX) { // expected-error {{expected version number}} if #available(OSX 10.51 { // expected-error {{expected ')'}} expected-note {{to match this opening '('}} expected-error {{must handle potential future platforms with '*'}} {{24-24=, *}} } -if #available(iDishwasherOS 10.51) { // expected-error {{unrecognized platform name 'iDishwasherOS'}} +if #available(iDishwasherOS 10.51) { // expected-warning {{unrecognized platform name 'iDishwasherOS'}} +// expected-error@-1 {{must handle potential future platforms with '*'}} } -if #available(iDishwasherOS 10.51, *) { // expected-error {{unrecognized platform name 'iDishwasherOS'}} +if #available(iDishwasherOS 10.51, *) { // expected-warning {{unrecognized platform name 'iDishwasherOS'}} } if #available(OSX 10.51, OSX 10.52, *) { // expected-error {{version for 'OSX' already specified}} @@ -79,10 +80,12 @@ if #available(OSX 10.51,) { // expected-error {{expected platform name}} if #available(OSX 10.51, iOS { // expected-error {{expected version number}} // expected-error {{expected ')'}} expected-note {{to match this opening '('}} } -if #available(OSX 10.51, iOS 8.0, iDishwasherOS 10.51) { // expected-error {{unrecognized platform name 'iDishwasherOS'}} +if #available(OSX 10.51, iOS 8.0, iDishwasherOS 10.51) { // expected-warning {{unrecognized platform name 'iDishwasherOS'}} +// expected-error@-1 {{must handle potential future platforms with '*'}} } -if #available(iDishwasherOS 10.51, OSX 10.51) { // expected-error {{unrecognized platform name 'iDishwasherOS'}} +if #available(iDishwasherOS 10.51, OSX 10.51) { // expected-warning {{unrecognized platform name 'iDishwasherOS'}} +// expected-error@-1 {{must handle potential future platforms with '*'}} } if #available(OSX 10.51 || iOS 8.0) {// expected-error {{'||' cannot be used in an availability condition}} diff --git a/test/PrintAsObjC/classes.swift b/test/PrintAsObjC/classes.swift index c031d760f53fd..9d46ef4a1ddbb 100644 --- a/test/PrintAsObjC/classes.swift +++ b/test/PrintAsObjC/classes.swift @@ -223,6 +223,7 @@ class NotObjC {} // CHECK-NEXT: - (void)testDictionaryBridging3:(NSDictionary * _Nonnull)a; // CHECK-NEXT: - (void)testSetBridging:(NSSet * _Nonnull)a; // CHECK-NEXT: - (IBAction)actionMethod:(id _Nonnull)_; +// CHECK-NEXT: - (IBSegueAction NSObject * _Nonnull)segueActionMethod:(NSCoder * _Nonnull)coder sender:(id _Nonnull)sender SWIFT_WARN_UNUSED_RESULT; // CHECK-NEXT: - (void)methodWithReservedParameterNames:(id _Nonnull)long_ protected:(id _Nonnull)protected_; // CHECK-NEXT: - (void)honorRenames:(CustomName * _Nonnull)_; // CHECK-NEXT: - (Methods * _Nullable __unsafe_unretained)unmanaged:(id _Nonnull __unsafe_unretained)_ SWIFT_WARN_UNUSED_RESULT; @@ -280,6 +281,7 @@ class NotObjC {} @objc func testSetBridging(_ a: Set) {} @IBAction func actionMethod(_: AnyObject) {} + @IBSegueAction func segueActionMethod(_ coder: NSCoder, sender: Any) -> NSObject { fatalError() } @objc func methodWithReservedParameterNames(_ long: AnyObject, protected: AnyObject) {} diff --git a/test/PrintAsObjC/resilient-ancestry-stable-abi.swift b/test/PrintAsObjC/resilient-ancestry-stable-abi.swift index f572deea7db6f..bfa2a08230a27 100644 --- a/test/PrintAsObjC/resilient-ancestry-stable-abi.swift +++ b/test/PrintAsObjC/resilient-ancestry-stable-abi.swift @@ -4,7 +4,7 @@ // RUN: cp %S/Inputs/custom-modules/module.map %t/module.map -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %S/resilient-ancestry.swift -module-name resilient -emit-objc-header-path %t/resilient.h -I %t -enable-library-evolution -enable-resilient-objc-class-stubs +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %S/resilient-ancestry.swift -module-name resilient -emit-objc-header-path %t/resilient.h -I %t -enable-library-evolution -target %target-next-stable-abi-triple // RUN: %FileCheck %S/resilient-ancestry.swift < %t/resilient.h // RUN: %check-in-clang %t/resilient.h -I %t diff --git a/test/SourceKit/CodeFormat/indent-ibaction.swift b/test/SourceKit/CodeFormat/indent-ibaction.swift index 4c13bea222650..78c47fc6d2570 100644 --- a/test/SourceKit/CodeFormat/indent-ibaction.swift +++ b/test/SourceKit/CodeFormat/indent-ibaction.swift @@ -1,8 +1,13 @@ @IBAction func foo() { var xyz : Int } +@IBSegueAction func bar() { + var xyz : Int +} -// RUN: %sourcekitd-test -req=format -line=2 -length=1 %s >%t.response -// RUN: %FileCheck --strict-whitespace %s <%t.response +// RUN: %sourcekitd-test -req=format -line=2 -length=1 %s >%t.action.response +// RUN: %FileCheck --strict-whitespace %s <%t.action.response +// RUN: %sourcekitd-test -req=format -line=5 -length=1 %s >%t.segueaction.response +// RUN: %FileCheck --strict-whitespace %s <%t.segueaction.response // CHECK: key.sourcetext: " var xyz : Int" diff --git a/test/SourceKit/DocumentStructure/Inputs/main.swift b/test/SourceKit/DocumentStructure/Inputs/main.swift index f5e31b1f98906..1825f3a070c83 100644 --- a/test/SourceKit/DocumentStructure/Inputs/main.swift +++ b/test/SourceKit/DocumentStructure/Inputs/main.swift @@ -129,3 +129,9 @@ enum MySecondEnum { } func someFunc(input :Int?, completion: () throws -> Void) rethrows {} + +class OneMore { + @IBSegueAction func testAction(coder: AnyObject, _ ident: String) -> AnyObject { + fatalError() + } +} diff --git a/test/SourceKit/DocumentStructure/structure.swift.empty.response b/test/SourceKit/DocumentStructure/structure.swift.empty.response index 330079849eb5c..91c8d8f9b440f 100644 --- a/test/SourceKit/DocumentStructure/structure.swift.empty.response +++ b/test/SourceKit/DocumentStructure/structure.swift.empty.response @@ -1,6 +1,6 @@ { key.offset: 0, - key.length: 2136, + key.length: 2259, key.diagnostic_stage: source.diagnostic.stage.swift.parse, key.substructure: [ { @@ -1326,6 +1326,70 @@ key.namelength: 10 } ] + }, + { + key.kind: source.lang.swift.decl.class, + key.accessibility: source.lang.swift.accessibility.internal, + key.name: "OneMore", + key.offset: 2137, + key.length: 121, + key.runtime_name: "_TtC4main7OneMore", + key.nameoffset: 2143, + key.namelength: 7, + key.bodyoffset: 2152, + key.bodylength: 105, + key.substructure: [ + { + key.kind: source.lang.swift.decl.function.method.instance, + key.accessibility: source.lang.swift.accessibility.internal, + key.name: "testAction(coder:_:)", + key.offset: 2170, + key.length: 86, + key.typename: "AnyObject", + key.selector_name: "testActionWithCoder::", + key.nameoffset: 2175, + key.namelength: 45, + key.bodyoffset: 2235, + key.bodylength: 20, + key.attributes: [ + { + key.offset: 2155, + key.length: 14, + key.attribute: source.decl.attribute.ibsegueaction + } + ], + key.substructure: [ + { + key.kind: source.lang.swift.decl.var.parameter, + key.name: "coder", + key.offset: 2186, + key.length: 16, + key.typename: "AnyObject", + key.nameoffset: 2186, + key.namelength: 5 + }, + { + key.kind: source.lang.swift.decl.var.parameter, + key.name: "ident", + key.offset: 2204, + key.length: 15, + key.typename: "String", + key.nameoffset: 0, + key.namelength: 0 + }, + { + key.kind: source.lang.swift.expr.call, + key.name: "fatalError", + key.offset: 2240, + key.length: 12, + key.nameoffset: 2240, + key.namelength: 10, + key.bodyoffset: 2251, + key.bodylength: 0 + } + ] + } + ] } ], key.diagnostics: [ diff --git a/test/SourceKit/DocumentStructure/structure.swift.foobar.response b/test/SourceKit/DocumentStructure/structure.swift.foobar.response index aea96507edfa9..e09c97690fa8d 100644 --- a/test/SourceKit/DocumentStructure/structure.swift.foobar.response +++ b/test/SourceKit/DocumentStructure/structure.swift.foobar.response @@ -1,6 +1,6 @@ { key.offset: 0, - key.length: 2136, + key.length: 2259, key.diagnostic_stage: source.diagnostic.stage.swift.parse, key.substructure: [ { @@ -1326,6 +1326,70 @@ key.namelength: 10 } ] + }, + { + key.kind: source.lang.swift.decl.class, + key.accessibility: source.lang.swift.accessibility.internal, + key.name: "OneMore", + key.offset: 2137, + key.length: 121, + key.runtime_name: "_TtC4main7OneMore", + key.nameoffset: 2143, + key.namelength: 7, + key.bodyoffset: 2152, + key.bodylength: 105, + key.substructure: [ + { + key.kind: source.lang.swift.decl.function.method.instance, + key.accessibility: source.lang.swift.accessibility.internal, + key.name: "testAction(coder:_:)", + key.offset: 2170, + key.length: 86, + key.typename: "AnyObject", + key.selector_name: "testActionWithCoder::", + key.nameoffset: 2175, + key.namelength: 45, + key.bodyoffset: 2235, + key.bodylength: 20, + key.attributes: [ + { + key.offset: 2155, + key.length: 14, + key.attribute: source.decl.attribute.ibsegueaction + } + ], + key.substructure: [ + { + key.kind: source.lang.swift.decl.var.parameter, + key.name: "coder", + key.offset: 2186, + key.length: 16, + key.typename: "AnyObject", + key.nameoffset: 2186, + key.namelength: 5 + }, + { + key.kind: source.lang.swift.decl.var.parameter, + key.name: "ident", + key.offset: 2204, + key.length: 15, + key.typename: "String", + key.nameoffset: 0, + key.namelength: 0 + }, + { + key.kind: source.lang.swift.expr.call, + key.name: "fatalError", + key.offset: 2240, + key.length: 12, + key.nameoffset: 2240, + key.namelength: 10, + key.bodyoffset: 2251, + key.bodylength: 0 + } + ] + } + ] } ], key.diagnostics: [ diff --git a/test/SourceKit/DocumentStructure/structure.swift.response b/test/SourceKit/DocumentStructure/structure.swift.response index 82b8c122b86fa..d4e91a12c9131 100644 --- a/test/SourceKit/DocumentStructure/structure.swift.response +++ b/test/SourceKit/DocumentStructure/structure.swift.response @@ -1,6 +1,6 @@ { key.offset: 0, - key.length: 2136, + key.length: 2259, key.diagnostic_stage: source.diagnostic.stage.swift.parse, key.substructure: [ { @@ -1326,6 +1326,70 @@ key.namelength: 10 } ] + }, + { + key.kind: source.lang.swift.decl.class, + key.accessibility: source.lang.swift.accessibility.internal, + key.name: "OneMore", + key.offset: 2137, + key.length: 121, + key.runtime_name: "_TtC13StructureTest7OneMore", + key.nameoffset: 2143, + key.namelength: 7, + key.bodyoffset: 2152, + key.bodylength: 105, + key.substructure: [ + { + key.kind: source.lang.swift.decl.function.method.instance, + key.accessibility: source.lang.swift.accessibility.internal, + key.name: "testAction(coder:_:)", + key.offset: 2170, + key.length: 86, + key.typename: "AnyObject", + key.selector_name: "testActionWithCoder::", + key.nameoffset: 2175, + key.namelength: 45, + key.bodyoffset: 2235, + key.bodylength: 20, + key.attributes: [ + { + key.offset: 2155, + key.length: 14, + key.attribute: source.decl.attribute.ibsegueaction + } + ], + key.substructure: [ + { + key.kind: source.lang.swift.decl.var.parameter, + key.name: "coder", + key.offset: 2186, + key.length: 16, + key.typename: "AnyObject", + key.nameoffset: 2186, + key.namelength: 5 + }, + { + key.kind: source.lang.swift.decl.var.parameter, + key.name: "ident", + key.offset: 2204, + key.length: 15, + key.typename: "String", + key.nameoffset: 0, + key.namelength: 0 + }, + { + key.kind: source.lang.swift.expr.call, + key.name: "fatalError", + key.offset: 2240, + key.length: 12, + key.nameoffset: 2240, + key.namelength: 10, + key.bodyoffset: 2251, + key.bodylength: 0 + } + ] + } + ] } ], key.diagnostics: [ diff --git a/test/attr/attr_availability.swift b/test/attr/attr_availability.swift index 22c7fbae550da..571fba385ddd9 100644 --- a/test/attr/attr_availability.swift +++ b/test/attr/attr_availability.swift @@ -215,6 +215,24 @@ func shortFormMissingParen() { // expected-error {{expected ')' in 'available' a func shortFormMissingPlatform() { } +@available(iOS 8.0, iDishwasherOS 22.0, *) // expected-warning {{unrecognized platform name 'iDishwasherOS'}} +func shortFormWithUnrecognizedPlatform() { +} + +@available(iOS 8.0, iDishwasherOS 22.0, iRefrigeratorOS 18.0, *) +// expected-warning@-1 {{unrecognized platform name 'iDishwasherOS'}} +// expected-warning@-2 {{unrecognized platform name 'iRefrigeratorOS'}} +func shortFormWithTwoUnrecognizedPlatforms() { +} + +// Make sure that even after the parser hits an unrecognized +// platform it validates the availability. +@available(iOS 8.0, iDishwasherOS 22.0, iOS 9.0, *) +// expected-warning@-1 {{unrecognized platform name 'iDishwasherOS'}} +// expected-error@-2 {{version for 'iOS' already specified}} +func shortFormWithUnrecognizedPlatformContinueValidating() { +} + @available(iOS 8.0, * func shortFormMissingParenAfterWildcard() { // expected-error {{expected ')' in 'available' attribute}} } diff --git a/test/attr/attr_ibaction.swift b/test/attr/attr_ibaction.swift index b0d16514fc330..78409a6215fa2 100644 --- a/test/attr/attr_ibaction.swift +++ b/test/attr/attr_ibaction.swift @@ -30,7 +30,7 @@ class IBActionWrapperTy { var value : Void = () @IBAction - func process(x: AnyObject) -> Int {} // expected-error {{methods declared @IBAction must return 'Void' (not 'Int')}} + func process(x: AnyObject) -> Int {} // expected-error {{methods declared @IBAction must not return a value}} // @IBAction does /not/ semantically imply @objc. @IBAction // expected-note {{attribute already specified here}} @@ -55,6 +55,14 @@ protocol CP2 : class { } @objc protocol OP1 { } @objc protocol OP2 { } +// Teach the compiler that String is @objc-friendly without importing +// Foundation. +extension String: _ObjectiveCBridgeable { + @_semantics("convertToObjectiveC") public func _bridgeToObjectiveC() -> AnyObject { fatalError() } + public static func _forceBridgeFromObjectiveC(_ x: AnyObject, result: inout String?) { fatalError() } + public static func _conditionallyBridgeFromObjectiveC(_ x: AnyObject, result: inout String?) -> Bool { fatalError() } + @_effects(readonly) public static func _unconditionallyBridgeFromObjectiveC(_ source: AnyObject? ) -> String { fatalError() } +} // Check which argument types @IBAction can take. @objc class X { @@ -74,39 +82,47 @@ protocol CP2 : class { } @IBAction func action6a(_: Any!) {} // Protocol types - @IBAction func action7(_: P1) {} // expected-error{{argument to @IBAction method cannot have non-object type 'P1'}} - @IBAction func action8(_: CP1) {} // expected-error{{argument to @IBAction method cannot have non-object type 'CP1'}} + @IBAction func action7(_: P1) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} expected-note{{protocol-constrained type containing protocol 'P1' cannot be represented in Objective-C}} + @IBAction func action8(_: CP1) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} expected-note{{protocol-constrained type containing protocol 'CP1' cannot be represented in Objective-C}} @IBAction func action9(_: OP1) {} - @IBAction func action10(_: P1?) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action11(_: CP1?) {} // expected-error{{argument to @IBAction method cannot have non-object type}} + @IBAction func action10(_: P1?) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} + @IBAction func action11(_: CP1?) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} @IBAction func action12(_: OP1?) {} - @IBAction func action13(_: P1!) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action14(_: CP1!) {} // expected-error{{argument to @IBAction method cannot have non-object type}} + @IBAction func action13(_: P1!) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} + @IBAction func action14(_: CP1!) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} @IBAction func action15(_: OP1!) {} // Class metatype - @IBAction func action15b(_: X.Type) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action16(_: X.Type?) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action17(_: X.Type!) {} // expected-error{{argument to @IBAction method cannot have non-object type}} + @IBAction func action15b(_: X.Type) {} + @IBAction func action16(_: X.Type?) {} + @IBAction func action17(_: X.Type!) {} // AnyClass - @IBAction func action18(_: AnyClass) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action19(_: AnyClass?) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action20(_: AnyClass!) {} // expected-error{{argument to @IBAction method cannot have non-object type}} + @IBAction func action18(_: AnyClass) {} + @IBAction func action19(_: AnyClass?) {} + @IBAction func action20(_: AnyClass!) {} // Protocol types - @IBAction func action21(_: P1.Type) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action22(_: CP1.Type) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action23(_: OP1.Type) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action24(_: P1.Type?) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action25(_: CP1.Type?) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action26(_: OP1.Type?) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action27(_: P1.Type!) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action28(_: CP1.Type!) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action29(_: OP1.Type!) {} // expected-error{{argument to @IBAction method cannot have non-object type}} + @IBAction func action21(_: P1.Type) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} + @IBAction func action22(_: CP1.Type) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} + @IBAction func action23(_: OP1.Type) {} + @IBAction func action24(_: P1.Type?) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} + @IBAction func action25(_: CP1.Type?) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} + @IBAction func action26(_: OP1.Type?) {} + @IBAction func action27(_: P1.Type!) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} + @IBAction func action28(_: CP1.Type!) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} + @IBAction func action29(_: OP1.Type!) {} + + // Structs representable in Objective-C + @IBAction func action32(_: Int) {} + @IBAction func action33(_: Int?) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} + + @IBAction func action34(_: String) {} + @IBAction func action35(_: String?) {} // Other bad cases - @IBAction func action30(_: S) {} // expected-error{{argument to @IBAction method cannot have non-object type}} - @IBAction func action31(_: E) {} // expected-error{{argument to @IBAction method cannot have non-object type}} + @IBAction func action30(_: S) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} expected-note{{Swift structs cannot be represented in Objective-C}} + @IBAction func action31(_: E) {} // expected-error{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} expected-note{{non-'@objc' enums cannot be represented in Objective-C}} + init() { } } diff --git a/test/attr/attr_ibaction_ios.swift b/test/attr/attr_ibaction_ios.swift index 53b44185d2fd6..dea44ffc0c918 100644 --- a/test/attr/attr_ibaction_ios.swift +++ b/test/attr/attr_ibaction_ios.swift @@ -1,78 +1,28 @@ -// RUN: not %target-build-swift -typecheck %s 2>&1 | %FileCheck -check-prefix=CHECK-%target-os -check-prefix=CHECK-BOTH %s +// RUN: not %target-build-swift -typecheck %s 2>&1 | %FileCheck -check-prefix=CHECK-%target-os %s // REQUIRES: executable_test -struct IntWrapper { - let value: Int -} - class IBActionWrapperTy { @IBAction func nullary() {} // CHECK-ios-NOT: attr_ibaction_ios.swift:[[@LINE-1]] - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-2]]:18: error: @IBAction methods must have a single argument - // CHECK-watchos-NOT: attr_ibaction_ios.swift:[[@LINE-3]] - - @IBAction func reqReq(_: AnyObject, _: AnyObject) {} - @IBAction func reqOpt(_: AnyObject, _: AnyObject?) {} - @IBAction func reqImp(_: AnyObject, _: AnyObject!) {} - @IBAction func optReq(_: AnyObject?, _: AnyObject) {} - @IBAction func optOpt(_: AnyObject?, _: AnyObject?) {} - @IBAction func optImp(_: AnyObject?, _: AnyObject!) {} - @IBAction func impReq(_: AnyObject!, _: AnyObject) {} - @IBAction func impOpt(_: AnyObject!, _: AnyObject?) {} - @IBAction func impImp(_: AnyObject!, _: AnyObject!) {} - // CHECK-ios-NOT: attr_ibaction_ios.swift:[[@LINE-9]] - // CHECK-ios-NOT: attr_ibaction_ios.swift:[[@LINE-9]] - // CHECK-ios-NOT: attr_ibaction_ios.swift:[[@LINE-9]] - // CHECK-ios-NOT: attr_ibaction_ios.swift:[[@LINE-9]] - // CHECK-ios-NOT: attr_ibaction_ios.swift:[[@LINE-9]] - // CHECK-ios-NOT: attr_ibaction_ios.swift:[[@LINE-9]] - // CHECK-ios-NOT: attr_ibaction_ios.swift:[[@LINE-9]] - // CHECK-ios-NOT: attr_ibaction_ios.swift:[[@LINE-9]] - // CHECK-ios-NOT: attr_ibaction_ios.swift:[[@LINE-9]] - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-18]]:18: error: @IBAction methods must have a single argument - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-18]]:18: error: @IBAction methods must have a single argument - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-18]]:18: error: @IBAction methods must have a single argument - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-18]]:18: error: @IBAction methods must have a single argument - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-18]]:18: error: @IBAction methods must have a single argument - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-18]]:18: error: @IBAction methods must have a single argument - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-18]]:18: error: @IBAction methods must have a single argument - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-18]]:18: error: @IBAction methods must have a single argument - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-18]]:18: error: @IBAction methods must have a single argument - // CHECK-watchos-NOT: attr_ibaction_ios.swift:[[@LINE-27]] - // CHECK-watchos-NOT: attr_ibaction_ios.swift:[[@LINE-27]] - // CHECK-watchos-NOT: attr_ibaction_ios.swift:[[@LINE-27]] - // CHECK-watchos-NOT: attr_ibaction_ios.swift:[[@LINE-27]] - // CHECK-watchos-NOT: attr_ibaction_ios.swift:[[@LINE-27]] - // CHECK-watchos-NOT: attr_ibaction_ios.swift:[[@LINE-27]] - // CHECK-watchos-NOT: attr_ibaction_ios.swift:[[@LINE-27]] - // CHECK-watchos-NOT: attr_ibaction_ios.swift:[[@LINE-27]] - // CHECK-watchos-NOT: attr_ibaction_ios.swift:[[@LINE-27]] - - @IBAction func reqBad(_: AnyObject, _: IBActionWrapperTy) {} - // CHECK-ios: attr_ibaction_ios.swift:[[@LINE-1]]:18: error: argument to @IBAction method cannot have non-'@objc' class type - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-2]]:18: error: @IBAction methods must have a single argument - // CHECK-watch: attr_ibaction_ios.swift:[[@LINE-3]]:18: error: argument to @IBAction method cannot have non-'@objc' class type - - @IBAction func badReq(_: Int, _: AnyObject) {} - // CHECK-ios: attr_ibaction_ios.swift:[[@LINE-1]]:18: error: argument to @IBAction method cannot have non-object type - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-2]]:18: error: @IBAction methods must have a single argument + // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-2]]:18: error: @IBAction methods must have 1 argument + // CHECK-tvos-NOT: attr_ibaction_ios.swift:[[@LINE-3]] + // CHECK-watchos-NOT: attr_ibaction_ios.swift:[[@LINE-4]] - @IBAction func badBad(_: Int, _: IBActionWrapperTy) {} - // CHECK-ios: attr_ibaction_ios.swift:[[@LINE-1]]:18: error: argument to @IBAction method cannot have non-object type - // CHECK-ios: attr_ibaction_ios.swift:[[@LINE-2]]:18: error: argument to @IBAction method cannot have non-'@objc' class type - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-3]]:18: error: @IBAction methods must have a single argument - - @IBAction func tooManyArgs(_: AnyObject, _: AnyObject, _: AnyObject) {} - // CHECK-ios: attr_ibaction_ios.swift:[[@LINE-1]]:18: error: @IBAction methods can only have up to 2 arguments - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-2]]:18: error: @IBAction methods must have a single argument - - @IBAction func watchKitLike(_: Int) {} + @IBAction func unary(_: AnyObject) {} // CHECK-ios-NOT: attr_ibaction_ios.swift:[[@LINE-1]] - // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-2]]:18: error: argument to @IBAction method cannot have non-object type + // CHECK-macosx-NOT: attr_ibaction_ios.swift:[[@LINE-2]] + // CHECK-tvos-NOT: attr_ibaction_ios.swift:[[@LINE-3]] + // CHECK-watchos-NOT: attr_ibaction_ios.swift:[[@LINE-4]] - @IBAction func watchKitLikeBad(_: IntWrapper) {} - // CHECK-BOTH: attr_ibaction_ios.swift:[[@LINE-1]]:18: error: argument to @IBAction method cannot have non-object type - - @IBAction func watchKitLikeOpt(_: Int?) {} - // CHECK-BOTH: attr_ibaction_ios.swift:[[@LINE-1]]:18: error: argument to @IBAction method cannot have non-object type + @IBAction func binary(_: AnyObject, _: AnyObject) {} + // CHECK-ios-NOT: attr_ibaction_ios.swift:[[@LINE-1]] + // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-2]]:18: error: @IBAction methods must have 1 argument + // CHECK-tvos-NOT: attr_ibaction_ios.swift:[[@LINE-3]] + // CHECK-watchos-NOT: attr_ibaction_ios.swift:[[@LINE-4]] + + @IBAction func ternary(_: AnyObject, _: AnyObject, _: AnyObject) {} + // CHECK-ios: attr_ibaction_ios.swift:[[@LINE-1]]:18: error: @IBAction methods must have at most 2 arguments + // CHECK-macosx: attr_ibaction_ios.swift:[[@LINE-2]]:18: error: @IBAction methods must have 1 argument + // CHECK-tvos: attr_ibaction_ios.swift:[[@LINE-3]]:18: error: @IBAction methods must have at most 2 arguments + // CHECK-watchos: attr_ibaction_ios.swift:[[@LINE-4]]:18: error: @IBAction methods must have at most 2 arguments } diff --git a/test/attr/attr_ibsegueaction.swift b/test/attr/attr_ibsegueaction.swift new file mode 100644 index 0000000000000..8323208f5701c --- /dev/null +++ b/test/attr/attr_ibsegueaction.swift @@ -0,0 +1,235 @@ +// RUN: %target-typecheck-verify-swift + +// REQUIRES: objc_interop + +@IBSegueAction // expected-error {{@IBSegueAction may only be used on 'func' declarations}} {{1-16=}} +var iboutlet_global: Int + +var iboutlet_accessor: Int { + @IBSegueAction // expected-error {{@IBSegueAction may only be used on 'func' declarations}} {{3-18=}} + get { return 42 } +} + +@IBSegueAction // expected-error {{@IBSegueAction may only be used on 'func' declarations}} {{1-16=}} +class IBOutletClassTy {} +@IBSegueAction // expected-error {{@IBSegueAction may only be used on 'func' declarations}} {{1-16=}} +struct IBStructTy {} + +@IBSegueAction // expected-error {{only instance methods can be declared @IBSegueAction}} {{1-16=}} +func IBFunction(_: AnyObject, _: AnyObject, _: AnyObject) -> AnyObject {} + +class IBActionWrapperTy { + @IBSegueAction + func click(_: AnyObject, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // no-warning + + func outer(_: AnyObject, _: AnyObject, _: AnyObject) -> AnyObject { + @IBSegueAction // expected-error {{only instance methods can be declared @IBSegueAction}} {{5-20=}} + func inner(_: AnyObject, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} + fatalError() + } + @IBSegueAction // expected-error {{@IBSegueAction may only be used on 'func' declarations}} {{3-18=}} + var value : AnyObject? = nil + + @IBSegueAction + func process(x: AnyObject, _: AnyObject, _: AnyObject) {} // expected-error {{methods declared @IBSegueAction must return a value}} + + @IBSegueAction + func process(_: AnyObject, _: AnyObject, _: AnyObject) -> Int? {fatalError()} // expected-error {{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} + + // @IBSegueAction does /not/ semantically imply @objc. + @IBSegueAction // expected-note {{attribute already specified here}} + @IBSegueAction // expected-error {{duplicate attribute}} + func doMagic(_: AnyObject, _: AnyObject, _: AnyObject) -> AnyObject {} + + @IBSegueAction @objc + func moreMagic(_: AnyObject, _: AnyObject, _: AnyObject) -> AnyObject {} // no-warning + @objc @IBSegueAction + func evenMoreMagic(_: AnyObject, _: AnyObject, _: AnyObject) -> AnyObject {} // no-warning +} + +struct S { } +enum E { case aCaseToKeepItFromBeingUninhabited } + +protocol P1 { } +protocol P2 { } + +protocol CP1 : class { } +protocol CP2 : class { } + +@objc protocol OP1 { } +@objc protocol OP2 { } + +// Check errors and fix-its for names which would cause memory leaks due to ARC +// semantics. +@objc class Leaky { + @IBSegueAction func newScreen(_: AnyObject) -> AnyObject {fatalError()} + // expected-error@-1{{@IBSegueAction method cannot have selector 'newScreen:' because it has special memory management behavior}} + // expected-note@-2{{change Swift name to 'makeScreen'}} {{23-32=makeScreen}} + // expected-note@-3{{change Objective-C selector to 'makeScreen:'}} {{3-3=@objc(makeScreen:) }} + @IBSegueAction func allocScreen(_: AnyObject) -> AnyObject {fatalError()} + // expected-error@-1{{@IBSegueAction method cannot have selector 'allocScreen:' because it has special memory management behavior}} + // expected-note@-2{{change Swift name to 'makeScreen'}} {{23-34=makeScreen}} + // expected-note@-3{{change Objective-C selector to 'makeScreen:'}} {{3-3=@objc(makeScreen:) }} + @IBSegueAction func initScreen(_: AnyObject) -> AnyObject {fatalError()} + // expected-error@-1{{@IBSegueAction method cannot have selector 'initScreen:' because it has special memory management behavior}} + // expected-note@-2{{change Swift name to 'makeScreen'}} {{23-33=makeScreen}} + // expected-note@-3{{change Objective-C selector to 'makeScreen:'}} {{3-3=@objc(makeScreen:) }} + @IBSegueAction func copyScreen(_: AnyObject) -> AnyObject {fatalError()} + // expected-error@-1{{@IBSegueAction method cannot have selector 'copyScreen:' because it has special memory management behavior}} + // expected-note@-2{{change Swift name to 'makeCopyScreen'}} {{23-33=makeCopyScreen}} + // expected-note@-3{{change Objective-C selector to 'makeCopyScreen:'}} {{3-3=@objc(makeCopyScreen:) }} + @IBSegueAction func mutableCopyScreen(_: AnyObject) -> AnyObject {fatalError()} + // expected-error@-1{{@IBSegueAction method cannot have selector 'mutableCopyScreen:' because it has special memory management behavior}} + // expected-note@-2{{change Swift name to 'makeMutableCopyScreen'}} {{23-40=makeMutableCopyScreen}} + // expected-note@-3{{change Objective-C selector to 'makeMutableCopyScreen:'}} {{3-3=@objc(makeMutableCopyScreen:) }} + @IBSegueAction func newScreen(_: AnyObject, secondArg: AnyObject) -> AnyObject {fatalError()} + // expected-error@-1{{@IBSegueAction method cannot have selector 'newScreen:secondArg:' because it has special memory management behavior}} + // expected-note@-2{{change Swift name to 'makeScreen(_:secondArg:)'}} {{23-32=makeScreen}} + // expected-note@-3{{change Objective-C selector to 'makeScreen:secondArg:'}} {{3-3=@objc(makeScreen:secondArg:) }} + + // If there's an @objc(explicitSelector:) already, we should validate and fix + // that instead of the Swift name. + @objc(actuallyOkayScreen:) + @IBSegueAction func newActuallyOkayScreen(_: AnyObject) -> AnyObject {fatalError()} + + @objc(actuallyOkayScreen:secondArg:) + @IBSegueAction func newActuallyOkayScreen(_: AnyObject, secondArg: AnyObject) -> AnyObject {fatalError()} + + @objc(newProblematicScreen:) + @IBSegueAction func problematicScreen(_: AnyObject) -> AnyObject {fatalError()} + // expected-error@-1{{@IBSegueAction method cannot have selector 'newProblematicScreen:' because it has special memory management behavior}} + // expected-note@-2{{change Objective-C selector to 'makeProblematicScreen:'}} {{9-30=makeProblematicScreen:}} + + @objc(newProblematicScreen:secondArg:) + @IBSegueAction func problematicScreen(_: AnyObject, secondArg: AnyObject) -> AnyObject {fatalError()} + // expected-error@-1{{@IBSegueAction method cannot have selector 'newProblematicScreen:secondArg:' because it has special memory management behavior}} + // expected-note@-2{{change Objective-C selector to 'makeProblematicScreen:secondArg:'}} {{9-40=makeProblematicScreen:secondArg:}} +} + +// Check which argument types @IBSegueAction can take. +@objc class X { + // Class type + @IBSegueAction func action1(_: X, _: X, _: X) -> X {fatalError()} + + @IBSegueAction func action2(_: X?, _: X?, _: X?) -> X? {fatalError()} + + @IBSegueAction func action3(_: X!, _: X!, _: X!) -> X! {fatalError()} + + // AnyObject + @IBSegueAction func action4(_: AnyObject, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} + + @IBSegueAction func action5(_: AnyObject?, _: AnyObject?, _: AnyObject?) -> AnyObject? {fatalError()} + + @IBSegueAction func action6(_: AnyObject!, _: AnyObject!, _: AnyObject!) -> AnyObject! {fatalError()} + + // Any + @IBSegueAction func action4a(_: Any, _: Any, _: Any) -> Any {fatalError()} + + @IBSegueAction func action5a(_: Any?, _: Any?, _: Any?) -> Any? {fatalError()} + + @IBSegueAction func action6a(_: Any!, _: Any!, _: Any!) -> Any! {fatalError()} + + // Protocol types + @IBSegueAction func action7a(_: AnyObject, _: AnyObject, _: AnyObject) -> P1 {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} expected-note{{protocol-constrained type containing protocol 'P1' cannot be represented in Objective-C}} + @IBSegueAction func action7b(_: P1, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 1 cannot be represented in Objective-C}} expected-note{{protocol-constrained type containing protocol 'P1' cannot be represented in Objective-C}} + @IBSegueAction func action7c(_: AnyObject, _: P1, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 2 cannot be represented in Objective-C}} expected-note{{protocol-constrained type containing protocol 'P1' cannot be represented in Objective-C}} + @IBSegueAction func action7d(_: AnyObject, _: AnyObject, _: P1) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 3 cannot be represented in Objective-C}} expected-note{{protocol-constrained type containing protocol 'P1' cannot be represented in Objective-C}} + + @IBSegueAction func action8a(_: AnyObject, _: AnyObject, _: AnyObject) -> CP1 {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} expected-note{{protocol-constrained type containing protocol 'CP1' cannot be represented in Objective-C}} + @IBSegueAction func action7b(_: CP1, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 1 cannot be represented in Objective-C}} expected-note{{protocol-constrained type containing protocol 'CP1' cannot be represented in Objective-C}} + @IBSegueAction func action7c(_: AnyObject, _: CP1, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 2 cannot be represented in Objective-C}} expected-note{{protocol-constrained type containing protocol 'CP1' cannot be represented in Objective-C}} + @IBSegueAction func action7d(_: AnyObject, _: AnyObject, _: CP1) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 3 cannot be represented in Objective-C}} expected-note{{protocol-constrained type containing protocol 'CP1' cannot be represented in Objective-C}} + + @IBSegueAction func action9(_: OP1, _: OP1, _: OP1) -> OP1 {fatalError()} + + @IBSegueAction func action10a(_: AnyObject, _: AnyObject, _: AnyObject) -> P1? {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} + @IBSegueAction func action10b(_: P1?, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 1 cannot be represented in Objective-C}} + @IBSegueAction func action10c(_: AnyObject, _: P1?, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 2 cannot be represented in Objective-C}} + @IBSegueAction func action10d(_: AnyObject, _: AnyObject, _: P1?) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 3 cannot be represented in Objective-C}} + + @IBSegueAction func action11a(_: AnyObject, _: AnyObject, _: AnyObject) -> CP1? {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} + @IBSegueAction func action11b(_: CP1?, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 1 cannot be represented in Objective-C}} + @IBSegueAction func action11c(_: AnyObject, _: CP1?, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 2 cannot be represented in Objective-C}} + @IBSegueAction func action11d(_: AnyObject, _: AnyObject, _: CP1?) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 3 cannot be represented in Objective-C}} + + @IBSegueAction func action12(_: OP1?, _: OP1?, _: OP1?) -> OP1? {fatalError()} + + @IBSegueAction func action13a(_: AnyObject, _: AnyObject, _: AnyObject) -> P1! {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} + @IBSegueAction func action13b(_: P1!, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 1 cannot be represented in Objective-C}} + @IBSegueAction func action13c(_: AnyObject, _: P1!, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 2 cannot be represented in Objective-C}} + @IBSegueAction func action13d(_: AnyObject, _: AnyObject, _: P1!) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 3 cannot be represented in Objective-C}} + + @IBSegueAction func action14a(_: AnyObject, _: AnyObject, _: AnyObject) -> CP1! {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} + @IBSegueAction func action14b(_: CP1!, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 1 cannot be represented in Objective-C}} + @IBSegueAction func action14c(_: AnyObject, _: CP1!, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 2 cannot be represented in Objective-C}} + @IBSegueAction func action14d(_: AnyObject, _: AnyObject, _: CP1!) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 3 cannot be represented in Objective-C}} + + @IBSegueAction func action15(_: OP1!, _: OP1!, _: OP1!) -> OP1! {fatalError()} + + // Class metatype + @IBSegueAction func action16a(_: X.Type, _: X.Type, _: X.Type) -> X.Type {fatalError()} + @IBSegueAction func action16b(_: X.Type?, _: X.Type?, _: X.Type?) -> X.Type? {fatalError()} + @IBSegueAction func action16c(_: X.Type!, _: X.Type!, _: X.Type!) -> X.Type! {fatalError()} + + // AnyClass + @IBSegueAction func action18(_: AnyClass, _: AnyClass, _: AnyClass) -> AnyClass {fatalError()} + @IBSegueAction func action19(_: AnyClass?, _: AnyClass?, _: AnyClass?) -> AnyClass? {fatalError()} + @IBSegueAction func action20(_: AnyClass!, _: AnyClass!, _: AnyClass!) -> AnyClass! {fatalError()} + + // Protocol types + @IBSegueAction func action21a(_: AnyObject, _: AnyObject, _: AnyObject) -> P1.Type {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} + @IBSegueAction func action21b(_: P1.Type, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 1 cannot be represented in Objective-C}} + @IBSegueAction func action21c(_: AnyObject, _: P1.Type, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 2 cannot be represented in Objective-C}} + @IBSegueAction func action21d(_: AnyObject, _: AnyObject, _: P1.Type) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 3 cannot be represented in Objective-C}} + + @IBSegueAction func action22a(_: AnyObject, _: AnyObject, _: AnyObject) -> CP1.Type {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} + @IBSegueAction func action22b(_: CP1.Type, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 1 cannot be represented in Objective-C}} + @IBSegueAction func action22c(_: AnyObject, _: CP1.Type, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 2 cannot be represented in Objective-C}} + @IBSegueAction func action22d(_: AnyObject, _: AnyObject, _: CP1.Type) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 3 cannot be represented in Objective-C}} + + @IBSegueAction func action23(_: OP1.Type, _: OP1.Type, _: OP1.Type) -> OP1.Type {fatalError()} + + @IBSegueAction func action24a(_: AnyObject, _: AnyObject, _: AnyObject) -> P1.Type? {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} + @IBSegueAction func action24b(_: P1.Type?, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 1 cannot be represented in Objective-C}} + @IBSegueAction func action24c(_: AnyObject, _: P1.Type?, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 2 cannot be represented in Objective-C}} + @IBSegueAction func action24d(_: AnyObject, _: AnyObject, _: P1.Type?) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 3 cannot be represented in Objective-C}} + + @IBSegueAction func action25a(_: AnyObject, _: AnyObject, _: AnyObject) -> CP1.Type? {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} + @IBSegueAction func action25b(_: CP1.Type?, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 1 cannot be represented in Objective-C}} + @IBSegueAction func action25c(_: AnyObject, _: CP1.Type?, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 2 cannot be represented in Objective-C}} + @IBSegueAction func action25d(_: AnyObject, _: AnyObject, _: CP1.Type?) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 3 cannot be represented in Objective-C}} + + @IBSegueAction func action26(_: OP1.Type?, _: OP1.Type?, _: OP1.Type?) -> OP1.Type? {fatalError()} + + @IBSegueAction func action27a(_: AnyObject, _: AnyObject, _: AnyObject) -> P1.Type! {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} + @IBSegueAction func action27b(_: P1.Type!, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 1 cannot be represented in Objective-C}} + @IBSegueAction func action27c(_: AnyObject, _: P1.Type!, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 2 cannot be represented in Objective-C}} + @IBSegueAction func action27d(_: AnyObject, _: AnyObject, _: P1.Type!) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 3 cannot be represented in Objective-C}} + + @IBSegueAction func action28a(_: AnyObject, _: AnyObject, _: AnyObject) -> CP1.Type! {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} + @IBSegueAction func action28b(_: CP1.Type!, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 1 cannot be represented in Objective-C}} + @IBSegueAction func action28c(_: AnyObject, _: CP1.Type!, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 2 cannot be represented in Objective-C}} + @IBSegueAction func action28d(_: AnyObject, _: AnyObject, _: CP1.Type!) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 3 cannot be represented in Objective-C}} + + @IBSegueAction func action29(_: OP1.Type!, _: OP1.Type!, _: OP1.Type!) -> OP1.Type! {fatalError()} + + // Other bad cases + @IBSegueAction func action30a(_: AnyObject, _: AnyObject, _: AnyObject) -> S {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} expected-note{{Swift structs cannot be represented in Objective-C}} + @IBSegueAction func action30b(_: S, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 1 cannot be represented in Objective-C}} expected-note{{Swift structs cannot be represented in Objective-C}} + @IBSegueAction func action30c(_: AnyObject, _: S, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 2 cannot be represented in Objective-C}} expected-note{{Swift structs cannot be represented in Objective-C}} + @IBSegueAction func action30d(_: AnyObject, _: AnyObject, _: S) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 3 cannot be represented in Objective-C}} expected-note{{Swift structs cannot be represented in Objective-C}} + + @IBSegueAction func action31a(_: AnyObject, _: AnyObject, _: AnyObject) -> E {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because its result type cannot be represented in Objective-C}} expected-note{{non-'@objc' enums cannot be represented in Objective-C}} + @IBSegueAction func action31b(_: E, _: AnyObject, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 1 cannot be represented in Objective-C}} expected-note{{non-'@objc' enums cannot be represented in Objective-C}} + @IBSegueAction func action31c(_: AnyObject, _: E, _: AnyObject) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 2 cannot be represented in Objective-C}} expected-note{{non-'@objc' enums cannot be represented in Objective-C}} + @IBSegueAction func action31d(_: AnyObject, _: AnyObject, _: E) -> AnyObject {fatalError()} // expected-error{{method cannot be marked @IBSegueAction because the type of the parameter 3 cannot be represented in Objective-C}} expected-note{{non-'@objc' enums cannot be represented in Objective-C}} + + // Supported arities + @IBSegueAction func actionWith0() -> X {fatalError()} // expected-error{{@IBSegueAction methods must have 1 to 3 arguments}} + @IBSegueAction func actionWith1(_: X) -> X {fatalError()} + @IBSegueAction func actionWith2(_: X, _: X) -> X {fatalError()} + @IBSegueAction func actionWith3(_: X, _: X, _: X) -> X {fatalError()} + @IBSegueAction func actionWith4(_: X, _: X, _: X, _: X) -> X {fatalError()} // expected-error{{@IBSegueAction methods must have 1 to 3 arguments}} + + init() { } +} diff --git a/test/attr/attr_objc.swift b/test/attr/attr_objc.swift index 2f4a7ea7823cc..8d5c46e7d85ef 100644 --- a/test/attr/attr_objc.swift +++ b/test/attr/attr_objc.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -disable-objc-attr-requires-foundation-module -typecheck -verify %s -swift-version 4 -enable-source-import -I %S/Inputs -enable-swift3-objc-inference +// RUN: %target-swift-frontend -disable-objc-attr-requires-foundation-module -typecheck -verify -verify-ignore-unknown %s -swift-version 4 -enable-source-import -I %S/Inputs -enable-swift3-objc-inference // RUN: %target-swift-ide-test -skip-deinit=false -print-ast-typechecked -source-filename %s -function-definitions=true -prefer-type-repr=false -print-implicit-attrs=true -explode-pattern-binding-decls=true -disable-objc-attr-requires-foundation-module -swift-version 4 -enable-source-import -I %S/Inputs -enable-swift3-objc-inference | %FileCheck %s // RUN: not %target-swift-frontend -typecheck -dump-ast -disable-objc-attr-requires-foundation-module %s -swift-version 4 -enable-source-import -I %S/Inputs -enable-swift3-objc-inference > %t.ast // RUN: %FileCheck -check-prefix CHECK-DUMP %s < %t.ast @@ -1649,6 +1649,7 @@ class C { // Don't crash. @objc func foo(x: Undeclared) {} // expected-error {{use of undeclared type 'Undeclared'}} @IBAction func myAction(sender: Undeclared) {} // expected-error {{use of undeclared type 'Undeclared'}} + @IBSegueAction func myAction(coder: Undeclared, sender: Undeclared) -> Undeclared {fatalError()} // expected-error {{use of undeclared type 'Undeclared'}} expected-error {{use of undeclared type 'Undeclared'}} expected-error {{use of undeclared type 'Undeclared'}} } //===--- @@ -1681,7 +1682,20 @@ class HasIBAction { // CHECK: {{^}} @objc @IBAction func goodAction(_ sender: AnyObject?) { @IBAction func badAction(_ sender: PlainStruct?) { } - // expected-error@-1{{argument to @IBAction method cannot have non-object type 'PlainStruct?'}} + // expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}} +} + +//===--- +//===--- @IBSegueAction implies @objc +//===--- + +// CHECK-LABEL: {{^}}class HasIBSegueAction { +class HasIBSegueAction { + @IBSegueAction func goodSegueAction(_ coder: AnyObject) -> AnyObject {fatalError()} + // CHECK: {{^}} @objc @IBSegueAction func goodSegueAction(_ coder: AnyObject) -> AnyObject { + + @IBSegueAction func badSegueAction(_ coder: PlainStruct?) -> Int? {fatalError()} + // expected-error@-1{{method cannot be marked @IBSegueAction because the type of the parameter cannot be represented in Objective-C}} } //===--- diff --git a/test/attr/attr_objc_resilience.swift b/test/attr/attr_objc_resilience.swift index 22829b6209415..0afd4cefa6acd 100644 --- a/test/attr/attr_objc_resilience.swift +++ b/test/attr/attr_objc_resilience.swift @@ -9,18 +9,18 @@ import Foundation import resilient_objc_class @objc public class ResilientNSObjectSubclass : ResilientNSObjectOutsideParent {} -// expected-error@-1 {{classes built with library evolution support cannot have explicit '@objc' subclasses because they are not directly visible from Objective-C}} +// expected-error@-1 {{explicit '@objc' on subclass of 'ResilientNSObjectOutsideParent' requires}} public class AnotherResilientNSObjectSubclass : ResilientNSObjectOutsideParent {} extension ResilientNSObjectOutsideParent { @objc public func categoryOneMethod() {} - // expected-error@-1 {{extensions of classes built with library evolution support cannot contain '@objc' members}} + // expected-error@-1 {{'@objc' instance method in extension of subclass of 'ResilientNSObjectOutsideParent' requires}} } extension AnotherResilientNSObjectSubclass { @objc public func categoryTwoMethod() {} - // expected-error@-1 {{extensions of classes built with library evolution support cannot contain '@objc' members}} + // expected-error@-1 {{'@objc' instance method in extension of subclass of 'ResilientNSObjectOutsideParent' requires}} } // Note: @_fixed_layout on a class only applies to the storage layout and @@ -28,17 +28,37 @@ extension AnotherResilientNSObjectSubclass { @_fixed_layout @objc public class FixedLayoutNSObjectSubclass : FixedLayoutNSObjectOutsideParent {} -// expected-error@-1 {{classes built with library evolution support cannot have explicit '@objc' subclasses because they are not directly visible from Objective-C}} +// expected-error@-1 {{explicit '@objc' on subclass of 'FixedLayoutNSObjectOutsideParent' requires}} @_fixed_layout public class AnotherFixedLayoutNSObjectSubclass : FixedLayoutNSObjectOutsideParent {} extension FixedLayoutNSObjectOutsideParent { @objc public func categoryOneMethod() {} - // expected-error@-1 {{extensions of classes built with library evolution support cannot contain '@objc' members}} + // expected-error@-1 {{'@objc' instance method in extension of subclass of 'FixedLayoutNSObjectOutsideParent' requires}} } extension AnotherFixedLayoutNSObjectSubclass { @objc public func categoryTwoMethod() {} - // expected-error@-1 {{extensions of classes built with library evolution support cannot contain '@objc' members}} + // expected-error@-1 {{'@objc' instance method in extension of subclass of 'FixedLayoutNSObjectOutsideParent' requires}} +} + +// If either the class or the extension member has sufficiently narrow +// availability, we're okay. +extension AnotherResilientNSObjectSubclass { + @available(macOS 10.15, iOS 13.0.0, tvOS 13.0.0, watchOS 6.0.0, *) + @objc public func availableCategoryOneMethod() {} +} + +extension AnotherResilientNSObjectSubclass { + @available(macOS 10.15, iOS 13.0.0, tvOS 13.0.0, watchOS 6.0.0, *) + @objc public func availableCategoryTwoMethod() {} +} + +@available(macOS 10.15, iOS 13.0.0, tvOS 13.0.0, watchOS 6.0.0, *) +@objc public class AvailableResilientNSObjectSubclass : ResilientNSObjectOutsideParent {} + +@available(macOS 10.15, iOS 13.0.0, tvOS 13.0.0, watchOS 6.0.0, *) +extension AnotherResilientNSObjectSubclass { + @objc public func categoryThreeMethod() {} } diff --git a/test/attr/attr_objc_resilient_stubs.swift b/test/attr/attr_objc_resilient_stubs.swift index 7831a8e160331..f11267df8804f 100644 --- a/test/attr/attr_objc_resilient_stubs.swift +++ b/test/attr/attr_objc_resilient_stubs.swift @@ -1,14 +1,15 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend -emit-module-path %t/resilient_struct.swiftmodule %S/../Inputs/resilient_struct.swift -enable-library-evolution -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module-path %t/resilient_objc_class.swiftmodule %S/../Inputs/resilient_objc_class.swift -I %t -enable-library-evolution -enable-resilient-objc-class-stubs -// RUN: %target-swift-frontend -typecheck -verify %s -I %t -enable-resilient-objc-class-stubs +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module-path %t/resilient_objc_class.swiftmodule %S/../Inputs/resilient_objc_class.swift -I %t -enable-library-evolution -target %target-next-stable-abi-triple +// RUN: %target-swift-frontend -typecheck -verify %s -I %t -target %target-next-stable-abi-triple // REQUIRES: objc_interop +// REQUIRES: swift_stable_abi import Foundation import resilient_objc_class -// When built with -enable-resilient-objc-class-stubs, all of these cases are +// When built with a sufficiently new deployment target, all of these cases are // allowed. @objc public class ResilientNSObjectSubclass : ResilientNSObjectOutsideParent {} diff --git a/test/lit.cfg b/test/lit.cfg index 7dbb90dfde51b..d7f90569de05b 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -584,45 +584,62 @@ if config.benchmark_o != 'Benchmark_O': config.substitutions.append(('%target-triple', config.variant_triple)) if run_vendor == 'apple': - # iOS 12.2 does not support 32-bit targets, so we cannot run tests that - # want to deploy to an iOS that has Swift in the OS. - if run_os == 'ios' and run_ptrsize == '32': - pre_stable_version = '10' - else: - config.available_features.add('swift_stable_abi') - PRE_STABLE_VERSION = { - 'macosx': '10.14.3', - 'ios': '12.1', - 'tvos': '12.1', - 'watchos': '5.1' + if True: + # iOS 12.2 does not support 32-bit targets, so we cannot run tests that + # want to deploy to an iOS that has Swift in the OS. + if run_os == 'ios' and run_ptrsize == '32': + pre_stable_version = '10' + else: + config.available_features.add('swift_stable_abi') + PRE_STABLE_VERSION = { + 'macosx': '10.14.3', + 'ios': '12.1', + 'tvos': '12.1', + 'watchos': '5.1' + } + pre_stable_version = PRE_STABLE_VERSION.get(run_os, '') + + config.pre_stable_abi_triple = '%s-%s-%s%s' % (run_cpu, run_vendor, run_os, + pre_stable_version) + STABLE_VERSION = { + 'macosx': '10.14.4', + 'ios': '12.2', + 'tvos': '12.2', + 'watchos': '5.2' + } + stable_version = STABLE_VERSION.get(run_os, '') + config.stable_abi_triple = '%s-%s-%s%s' % (run_cpu, run_vendor, run_os, + stable_version) + + NEXT_STABLE_VERSION = { + 'macosx': '10.15', + 'ios': '13', + 'tvos': '13', + 'watchos': '6' } - pre_stable_version = PRE_STABLE_VERSION.get(run_os, '') - - config.pre_stable_abi_triple = '%s-%s-%s%s' % (run_cpu, run_vendor, run_os, - pre_stable_version) - STABLE_VERSION = { - 'macosx': '10.14.4', - 'ios': '12.2', - 'tvos': '12.2', - 'watchos': '5.2' - } - stable_version = STABLE_VERSION.get(run_os, '') - config.stable_abi_triple = '%s-%s-%s%s' % (run_cpu, run_vendor, run_os, - stable_version) + next_stable_version = NEXT_STABLE_VERSION.get(run_os, '') + config.next_stable_abi_triple = '%s-%s-%s%s' % (run_cpu, run_vendor, run_os, + next_stable_version) else: config.pre_stable_abi_triple = config.variant_triple config.stable_abi_triple = config.variant_triple + config.next_stable_abi_triple = config.variant_triple # On Apple platforms, this substitution names the maximum OS version *without* # Swift in the OS. On non-Apple platforms this is equivalent to %target-triple. config.substitutions.append(('%target-pre-stable-abi-triple', config.pre_stable_abi_triple)) -# On Apple platforms, this substitution names the minimum OS version *with* -# Swift in the OS. On non-Apple platforms this is equivalent to %target-triple. +# On Apple platforms, this substitution names the minimum OS version with +# Swift 5.0 in the OS. On non-Apple platforms this is equivalent to %target-triple. config.substitutions.append(('%target-stable-abi-triple', config.stable_abi_triple)) +# On Apple platforms, this substitution names the minimum OS version with +# Swift 5.1 in the OS, and an Objective-C runtime supporting class stubs. +config.substitutions.append(('%target-next-stable-abi-triple', + config.next_stable_abi_triple)) + # Sanitizers are not supported on iOS7, yet all tests are configured to start # testing with the earliest supported platform, which happens to be iOS7 for # Swift. diff --git a/test/type/opaque_availability.swift b/test/type/opaque_availability.swift new file mode 100644 index 0000000000000..360dcbf7887d2 --- /dev/null +++ b/test/type/opaque_availability.swift @@ -0,0 +1,13 @@ +// RUN: %target-swift-frontend -parse-stdlib -target x86_64-apple-macosx10.9 -typecheck -verify %s +// RUN: %target-swift-frontend -parse-stdlib -target x86_64-apple-macosx10.15 -typecheck %s +// REQUIRES: OS=macosx + +protocol P {} +struct X: P {} + +func alwaysOpaque() -> some P { return X() } // expected-error{{'some' return types are only available}} expected-note{{add @available}} + +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +func sometimesOpaque() -> some P { return X() } + + diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp index d12c1ddc96aca..bd8c423d2c1c7 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp @@ -1274,9 +1274,10 @@ class SwiftDocumentStructureWalker: public ide::SyntaxModelWalker { } StringRef getObjCSelectorName(const Decl *D, SmallString<64> &Buf) { - // We only vend the selector name for @IBAction methods. + // We only vend the selector name for @IBAction and @IBSegueAction methods. if (auto FuncD = dyn_cast_or_null(D)) { - if (FuncD->getAttrs().hasAttribute()) + if (FuncD->getAttrs().hasAttribute() || + FuncD->getAttrs().hasAttribute()) return FuncD->getObjCSelector().getString(Buf); } return StringRef(); diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp index 0d146bb130ec0..467089ad40f74 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp @@ -665,6 +665,10 @@ Optional SwiftLangSupport::getUIDForDeclAttribute(const swift::DeclAttri case DAK_IBAction: { return Attr_IBAction; } + case DAK_IBSegueAction: { + static UIdent Attr_IBSegueAction("source.decl.attribute.ibsegueaction"); + return Attr_IBSegueAction; + } case DAK_IBOutlet: { return Attr_IBOutlet; } diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index 16259402b6d4c..38639e0222075 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -264,7 +264,7 @@ static llvm::cl::list SwiftVersion("swift-version", llvm::cl::desc("Swift version"), llvm::cl::cat(Category)); -static llvm::cl::opt +static llvm::cl::list ModuleCachePath("module-cache-path", llvm::cl::desc("Clang module cache path"), llvm::cl::cat(Category)); @@ -3267,8 +3267,11 @@ int main(int argc, char *argv[]) { InitInvok.getLangOptions().EffectiveLanguageVersion = actual.getValue(); } } - InitInvok.getClangImporterOptions().ModuleCachePath = - options::ModuleCachePath; + if (!options::ModuleCachePath.empty()) { + // Honor the *last* -module-cache-path specified. + InitInvok.getClangImporterOptions().ModuleCachePath = + options::ModuleCachePath[options::ModuleCachePath.size()-1]; + } InitInvok.getClangImporterOptions().PrecompiledHeaderOutputDir = options::PCHOutputDir; InitInvok.setImportSearchPaths(options::ImportPaths); diff --git a/validation-test/Runtime/class_stubs.m b/validation-test/Runtime/class_stubs.m index fd40b1da9f059..03af7438fd77c 100644 --- a/validation-test/Runtime/class_stubs.m +++ b/validation-test/Runtime/class_stubs.m @@ -3,14 +3,15 @@ // RUN: %empty-directory(%t) // RUN: %target-build-swift -emit-library -emit-module -o %t/libfirst.dylib -emit-objc-header-path %t/first.h %S/Inputs/class-stubs-from-objc/first.swift -Xlinker -install_name -Xlinker @executable_path/libfirst.dylib -enable-library-evolution -// RUN: %target-build-swift -emit-library -o %t/libsecond.dylib -emit-objc-header-path %t/second.h -I %t %S/Inputs/class-stubs-from-objc/second.swift -Xlinker -install_name -Xlinker @executable_path/libsecond.dylib -lfirst -L %t -Xfrontend -enable-resilient-objc-class-stubs +// RUN: %target-build-swift -emit-library -o %t/libsecond.dylib -emit-objc-header-path %t/second.h -I %t %S/Inputs/class-stubs-from-objc/second.swift -Xlinker -install_name -Xlinker @executable_path/libsecond.dylib -lfirst -L %t -target %target-next-stable-abi-triple // RUN: cp %S/Inputs/class-stubs-from-objc/module.map %t/ -// RUN: xcrun %clang %s -I %t -L %t -fmodules -fobjc-arc -o %t/main -lfirst -lsecond -Wl,-U,_objc_loadClassref +// RUN: xcrun -sdk %sdk %clang %s -I %t -L %t -fmodules -fobjc-arc -o %t/main -lfirst -lsecond -Wl,-U,_objc_loadClassref -target %target-next-stable-abi-triple // RUN: %target-codesign %t/main %t/libfirst.dylib %t/libsecond.dylib // RUN: %target-run %t/main %t/libfirst.dylib %t/libsecond.dylib // REQUIRES: executable_test -// REQUIRES: OS=macosx +// REQUIRES: objc_interop +// REQUIRES: swift_stable_abi #import #import diff --git a/validation-test/Runtime/class_stubs_weak.m b/validation-test/Runtime/class_stubs_weak.m index 0b88706576a72..dd2330bdd7562 100644 --- a/validation-test/Runtime/class_stubs_weak.m +++ b/validation-test/Runtime/class_stubs_weak.m @@ -3,20 +3,21 @@ // RUN: %empty-directory(%t) // RUN: %target-build-swift -emit-library -emit-module -o %t/libfirst.dylib -emit-objc-header-path %t/first.h %S/Inputs/class-stubs-weak/first.swift -Xlinker -install_name -Xlinker @executable_path/libfirst.dylib -enable-library-evolution -// RUN: %target-build-swift -emit-library -o %t/libsecond.dylib -emit-objc-header-path %t/second.h -I %t %S/Inputs/class-stubs-weak/second.swift -Xlinker -install_name -Xlinker @executable_path/libsecond.dylib -lfirst -L %t -Xfrontend -enable-resilient-objc-class-stubs -DBEFORE +// RUN: %target-build-swift -emit-library -o %t/libsecond.dylib -emit-objc-header-path %t/second.h -I %t %S/Inputs/class-stubs-weak/second.swift -Xlinker -install_name -Xlinker @executable_path/libsecond.dylib -lfirst -L %t -target %target-next-stable-abi-triple -DBEFORE // RUN: cp %S/Inputs/class-stubs-weak/module.map %t/ // Note: This is the just-built Clang, not the system Clang. // RUN: xcrun -sdk %sdk %clang %s -I %t -L %t -fmodules -fobjc-arc -o %t/main -lfirst -lsecond -Wl,-U,_objc_loadClassref -target %target-triple // Now rebuild the library, omitting the weak-exported class -// RUN: %target-build-swift -emit-library -o %t/libsecond.dylib -I %t %S/Inputs/class-stubs-weak/second.swift -Xlinker -install_name -Xlinker @executable_path/libsecond.dylib -lfirst -L %t -Xfrontend -enable-resilient-objc-class-stubs +// RUN: %target-build-swift -emit-library -o %t/libsecond.dylib -I %t %S/Inputs/class-stubs-weak/second.swift -Xlinker -install_name -Xlinker @executable_path/libsecond.dylib -lfirst -L %t -target %target-next-stable-abi-triple // RUN: %target-codesign %t/main %t/libfirst.dylib %t/libsecond.dylib // RUN: %target-run %t/main %t/libfirst.dylib %t/libsecond.dylib // REQUIRES: executable_test // REQUIRES: objc_interop +// REQUIRES: swift_stable_abi #import #import From 192bcb2007b89bc941d7ea6f348301f3ecf5ee86 Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Mon, 3 Jun 2019 20:25:03 +0100 Subject: [PATCH 020/112] Basic: Use APInt to implement ClusteredBitVector Simplify the implementation of ClusteredBitVector by using an APInt to represent the raw bits. This simplification will make it easier to incrementally move to a representation of bit vectors that works on both big- and little-endian machines. This commit also removes reserve and reserveExtra from the API since they were only used in one place and no longer have any effect because memory allocation is now handled by the APInt class. --- include/swift/Basic/ClusteredBitVector.h | 543 ++++----------------- lib/Basic/ClusteredBitVector.cpp | 189 +------ lib/IRGen/GenStruct.cpp | 1 - unittests/Basic/ClusteredBitVectorTest.cpp | 16 - 4 files changed, 97 insertions(+), 652 deletions(-) diff --git a/include/swift/Basic/ClusteredBitVector.h b/include/swift/Basic/ClusteredBitVector.h index db24ad38e393e..6ccf17434cb15 100644 --- a/include/swift/Basic/ClusteredBitVector.h +++ b/include/swift/Basic/ClusteredBitVector.h @@ -11,15 +11,7 @@ //===----------------------------------------------------------------------===// // // This file defines the ClusteredBitVector class, a bitset data -// structure appropriate for situations meeting two criteria: -// -// - Many vectors are no larger than a particular constant size, and -// such vectors should be stored as compactly as possible. This -// constant size should be at least as large as any reasonable -// target's pointer size in bits (i.e. at least 64). -// -// - Most vectors have no bits set, and those that do tend to have -// them set in coherent ranges. +// structure. // // For example, this would be reasonable to use to describe the // unoccupied bits in a memory layout. @@ -30,367 +22,101 @@ // // Primary observers: // - testing a specific bit -// - searching for set bits from the start +// - converting to llvm::APInt // //===----------------------------------------------------------------------===// #ifndef SWIFT_BASIC_CLUSTEREDBITVECTOR_H #define SWIFT_BASIC_CLUSTEREDBITVECTOR_H -#include "swift/Basic/LLVM.h" -#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/Optional.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include #include -#include -#include -#include - -namespace llvm { - class APInt; -} namespace swift { -/// A vector of bits. This data structure is optimized to store an -/// empty vector of any size without doing any allocation. +/// A vector of bits. class ClusteredBitVector { - using ChunkType = uint64_t; - static_assert(std::is_unsigned::value, "ChunkType must be unsigned"); - enum { - ChunkSizeInBits = sizeof(ChunkType) * CHAR_BIT - }; - static_assert(sizeof(ChunkType) >= sizeof(ChunkType*), - "ChunkType must be large enough to store a pointer"); - - /// Return the number of chunks required to store a vector of the - /// given number of bits. - static size_t getNumChunksForBits(size_t value) { - return (value + ChunkSizeInBits - 1) / ChunkSizeInBits; - } - - /// Either: - /// - a uint64_t * with at least enough storage for - /// getNumChunksForBits(LengthInBits) or - /// - inline storage for a single chunk - /// as determined by HasOutOfLineData. - /// - /// 1) When using out-of-line storage: - /// - /// Suppose chunk size = 8, length = 13, capacity = 24. - /// - /// 11010101 00011010 101010010 - /// ~~~~~~~~ ^ ~~~~~ ^ - /// data | data | - /// | +---- bits in other chunks - /// high bits in last chunk are uninitialized - /// are guaranteed zero - /// - /// The capacity (in bits) is stored at index -1. - /// - /// 2) When using inline storage: - /// - /// a) LengthInBits >= ChunkSizeInBits. In this case, Data must be 0. - /// All bits are considered to be zero in this case. - /// - /// b) 0 == LengthInBits. In this case, Data must be 0. - /// - /// c) 0 < LengthInBits < ChunkSizeInBits. In this case, Data contains - /// a single chunk, with its unused high bits zeroed like in the - /// out-of-line case. - /// - /// Therefore, an efficient way to test whether all bits are zero: - /// Data != 0. (isInlineAndAllClear()) Not *guaranteed* to find - /// something, but still efficient. - ChunkType Data; - - size_t LengthInBits : sizeof(size_t) * CHAR_BIT - 1; - size_t HasOutOfLineData : 1; - - /// Is this vector using out-of-line storage? - bool hasOutOfLineData() const { return HasOutOfLineData; } - - /// Return true if this vector is not using out-of-line storage and - /// does not have any bits set. This is a special-case representation - /// where the capacity can be smaller than the length. - /// - /// This is a necessary condition for hasSufficientChunkStorage(), - /// and it's quicker to test, so a lot of routines in this class - /// that need to work on chunk data in the general case test this - /// first. - bool isInlineAndAllClear() const { - assert(!hasOutOfLineData() || Data != 0); - return Data == 0; - } - - /// Return true if this vector is not in the special case where the - /// capacity is smaller than the length. If this is true, then - /// it's safe to call routines like getChunks(). - bool hasSufficientChunkStorage() const { - return !(isInlineAndAllClear() && LengthInBits > ChunkSizeInBits); - } - - /// Return the number of chunks required in order to store the full - /// length (not capacity) of this bit vector. This may be greater - /// than the capacity in exactly one case, (2a), i.e. - /// !hasSufficientChunkStorage(). - size_t getLengthInChunks() const { - return getNumChunksForBits(LengthInBits); - } - - /// Return the current capacity of this bit vector, in bits. This - /// is a relatively important operation because it's needed on every - /// append. - size_t getCapacityInBits() const { - return hasOutOfLineData() ? getOutOfLineCapacityInBits() : ChunkSizeInBits; - } - - /// Return the current capacity of this bit vector, in chunks. - size_t getCapacityInChunks() const { - return getCapacityInBits() / ChunkSizeInBits; - } - - /// Return the current capacity of this bit vector, in bits, given - /// that it's using out-of-line storage. - size_t getOutOfLineCapacityInBits() const { - assert(hasOutOfLineData()); - return (size_t) getOutOfLineChunksPtr()[-1]; - } - - /// Return the current capacity of this bit vector, in chunks, given - /// that it's using out-of-line storage. - size_t getOutOfLineCapacityInChunks() const { - return getOutOfLineCapacityInBits() / ChunkSizeInBits; - } - - /// Return a pointer to the data storage of this bit vector. - ChunkType *getChunksPtr() { - assert(hasSufficientChunkStorage()); - return hasOutOfLineData() ? getOutOfLineChunksPtr() : &Data; - } - const ChunkType *getChunksPtr() const { - assert(hasSufficientChunkStorage()); - return hasOutOfLineData() ? getOutOfLineChunksPtr() : &Data; - } + using APInt = llvm::APInt; - MutableArrayRef getChunks() { - assert(hasSufficientChunkStorage()); - return { getChunksPtr(), getLengthInChunks() }; - } - ArrayRef getChunks() const { - assert(hasSufficientChunkStorage()); - return { getChunksPtr(), getLengthInChunks() }; - } - - MutableArrayRef getOutOfLineChunks() { - return { getOutOfLineChunksPtr(), getLengthInChunks() }; - } - ArrayRef getOutOfLineChunks() const { - return { getOutOfLineChunksPtr(), getLengthInChunks() }; - } + /// Represents the bit vector as an integer. + /// The least-significant bit of the integer corresponds to the bit + /// at index 0. If the optional does not have a value then the bit + /// vector has a length of 0 bits. + llvm::Optional Bits; - /// Return a pointer to the data storage of this bit vector, given - /// that it's using out-of-line storage. - ChunkType *getOutOfLineChunksPtr() { - assert(hasOutOfLineData()); - return reinterpret_cast(Data); - } - const ChunkType *getOutOfLineChunksPtr() const { - assert(hasOutOfLineData()); - return reinterpret_cast(Data); - } + /// Copy constructor from APInt. + ClusteredBitVector(const APInt &bits) : Bits(bits) {} + /// Move constructor from APInt. + ClusteredBitVector(APInt &&bits) : Bits(std::move(bits)) {} public: /// Create a new bit vector of zero length. This does not perform /// any allocations. - ClusteredBitVector() : Data(0), LengthInBits(0), HasOutOfLineData(0) {} - - /// Return a constant bit-vector of the given size. - static ClusteredBitVector getConstant(size_t numBits, bool value) { - ClusteredBitVector result; - if (value) { - result.reserve(numBits); - result.appendSetBits(numBits); - } else { - result.appendClearBits(numBits); - } - return result; - } + ClusteredBitVector() = default; ClusteredBitVector(const ClusteredBitVector &other) - : Data(other.Data), - LengthInBits(other.LengthInBits), - HasOutOfLineData(other.HasOutOfLineData) { - if (hasOutOfLineData()) { - makeIndependentCopy(); - } - } + : Bits(other.Bits) {} ClusteredBitVector(ClusteredBitVector &&other) - : Data(other.Data), - LengthInBits(other.LengthInBits), - HasOutOfLineData(other.HasOutOfLineData) { - other.dropData(); - } + : Bits(std::move(other.Bits)) {} ClusteredBitVector &operator=(const ClusteredBitVector &other) { - // Do something with our current out-of-line storage. - if (hasOutOfLineData()) { - // Copy into our current storage if its capacity is adequate. - auto otherLengthInChunks = other.getLengthInChunks(); - if (otherLengthInChunks <= getOutOfLineCapacityInChunks()) { - LengthInBits = other.LengthInBits; - if (other.isInlineAndAllClear()) { - memset(getOutOfLineChunksPtr(), 0, - otherLengthInChunks * sizeof(ChunkType)); - } else { - memcpy(getOutOfLineChunksPtr(), other.getChunksPtr(), - otherLengthInChunks * sizeof(ChunkType)); - } - return *this; - } - - // Otherwise, destroy our current storage. - destroy(); - } - - Data = other.Data; - LengthInBits = other.LengthInBits; - HasOutOfLineData = other.HasOutOfLineData; - if (HasOutOfLineData) { - makeIndependentCopy(); - } - + this->Bits = other.Bits; return *this; } ClusteredBitVector &operator=(ClusteredBitVector &&other) { - // Just drop our current out-of-line storage. - if (hasOutOfLineData()) { - destroy(); - } - - Data = other.Data; - LengthInBits = other.LengthInBits; - HasOutOfLineData = other.HasOutOfLineData; - other.dropData(); + this->Bits = std::move(other.Bits); return *this; } - ~ClusteredBitVector() { - if (hasOutOfLineData()) { - destroy(); - } - } + ~ClusteredBitVector() = default; /// Return true if this vector is zero-length (*not* if it does not /// contain any set bits). bool empty() const { - return LengthInBits == 0; + return !Bits.hasValue(); } /// Return the length of this bit-vector. size_t size() const { - return LengthInBits; - } - - /// Reserve space for an extra N bits. This may unnecessarily force - /// the vector to use an out-of-line representation. - void reserveExtra(size_t numBits) { - auto requiredBits = LengthInBits + numBits; - if (requiredBits > getCapacityInBits()) { - auto requiredChunks = getNumChunksForBits(requiredBits); - auto chunkCount = getCapacityInChunks(); - assert(requiredChunks > chunkCount); - do { - // Growth curve: 1 (inline) -> 3 -> 7 -> 15 -> 31 -> ... - // This is a particularly nice sequence because we store the - // capacity in the chunk at index -1, so the actual allocation - // size is a power of 2. - chunkCount = chunkCount * 2 + 1; - } while (requiredChunks > chunkCount); - - reallocate(chunkCount); - } - // Postcondition: hasSufficientChunkStorage(). - } - - /// Reserve space for a total of N bits. This may unnecessarily - /// force the vector to use an out-of-line representation. - void reserve(size_t requiredSize) { - if (requiredSize > getCapacityInBits()) { - reallocate(getNumChunksForBits(requiredSize)); - } - // Postcondition: hasSufficientChunkStorage(). + return Bits ? Bits.getValue().getBitWidth() : 0; } /// Append the bits from the given vector to this one. void append(const ClusteredBitVector &other) { // Nothing to do if the other vector is empty. - if (other.empty()) return; - - // Special case: don't allocate space for zero bits. - if (isInlineAndAllClear() && other.isInlineAndAllClear()) { - LengthInBits += other.LengthInBits; + if (!other.Bits) { return; } - - // Okay, one or the other of these is using out-of-line storage. - // Assume that bits might be set. - reserveExtra(other.size()); - - if (other.isInlineAndAllClear()) { - appendConstantBitsReserved(other.size(), 0); - } else { - appendReserved(other.size(), other.getChunksPtr()); - } - } - - /// Append the bits from the given vector to this one. - void append(ClusteredBitVector &&other) { - // If this vector is empty, just move the other. - if (empty()) { - *this = std::move(other); + if (!Bits) { + Bits = other.Bits; return; } - - // Otherwise, use copy-append. - append(other); + APInt &v = Bits.getValue(); + unsigned w = v.getBitWidth(); + v = v.zext(w + other.Bits.getValue().getBitWidth()); + v.insertBits(other.Bits.getValue(), w); + return; } /// Add the low N bits from the given value to the vector. void add(size_t numBits, uint64_t value) { - assert(numBits <= 64); - if (numBits == 0) return; - - if (value == 0 && isInlineAndAllClear()) { - LengthInBits += numBits; - return; - } - - reserveExtra(numBits); - static_assert(sizeof(value) <= sizeof(ChunkType), - "chunk too small for this, break 'value' up into " - "multiple parts"); - const ChunkType chunks[] = { value }; - appendReserved(numBits, chunks); + append(fromAPInt(APInt(numBits, value))); } /// Append a number of clear bits to this vector. void appendClearBits(size_t numBits) { - if (numBits == 0) return; - - if (isInlineAndAllClear()) { - LengthInBits += numBits; + if (numBits == 0) { return; } - - reserveExtra(numBits); - appendConstantBitsReserved(numBits, 0); + if (Bits) { + APInt &v = Bits.getValue(); + v = v.zext(v.getBitWidth() + numBits); + return; + } + Bits = APInt::getNullValue(numBits); } /// Extend the vector out to the given length with clear bits. @@ -399,12 +125,20 @@ class ClusteredBitVector { appendClearBits(newSize - size()); } - /// Append a number of set bits to this vector. void appendSetBits(size_t numBits) { - if (numBits == 0) return; - reserveExtra(numBits); - appendConstantBitsReserved(numBits, 1); + if (numBits == 0) { + return; + } + if (Bits) { + APInt &v = Bits.getValue(); + unsigned w = v.getBitWidth(); + v = v.zext(w + numBits); + v.setBitsFrom(w); + return; + } + Bits = APInt::getAllOnesValue(numBits); + return; } /// Extend the vector out to the given length with set bits. @@ -416,31 +150,15 @@ class ClusteredBitVector { /// Test whether a particular bit is set. bool operator[](size_t i) const { assert(i < size()); - if (isInlineAndAllClear()) return false; - return getChunks()[i / ChunkSizeInBits] - & (ChunkType(1) << (i % ChunkSizeInBits)); + return Bits.getValue()[i]; } /// Intersect a bit-vector of the same size into this vector. ClusteredBitVector &operator&=(const ClusteredBitVector &other) { assert(size() == other.size()); - - // If this vector is all-clear, this is a no-op. - if (isInlineAndAllClear()) - return *this; - - // If the other vector is all-clear, we need to wipe this one. - if (other.isInlineAndAllClear()) { - for (auto &chunk : getChunks()) - chunk = 0; - return *this; - } - - // Otherwise, &= the chunks pairwise. - auto chunks = getChunks(); - auto oi = other.getChunksPtr(); - for (auto i = chunks.begin(), e = chunks.end(); i != e; ++i, ++oi) { - *i &= *oi; + if (Bits) { + APInt &v = Bits.getValue(); + v &= other.Bits.getValue(); } return *this; } @@ -448,21 +166,9 @@ class ClusteredBitVector { /// Union a bit-vector of the same size into this vector. ClusteredBitVector &operator|=(const ClusteredBitVector &other) { assert(size() == other.size()); - - // If the other vector is all-clear, this is a no-op. - if (other.isInlineAndAllClear()) - return *this; - - // If this vector is all-clear, we just copy the other. - if (isInlineAndAllClear()) { - return (*this = other); - } - - // Otherwise, |= the chunks pairwise. - auto chunks = getChunks(); - auto oi = other.getChunksPtr(); - for (auto i = chunks.begin(), e = chunks.end(); i != e; ++i, ++oi) { - *i |= *oi; + if (Bits) { + APInt &v = Bits.getValue(); + v |= other.Bits.getValue(); } return *this; } @@ -470,66 +176,41 @@ class ClusteredBitVector { /// Set bit i. void setBit(size_t i) { assert(i < size()); - if (isInlineAndAllClear()) { - reserve(LengthInBits); - } - getChunks()[i / ChunkSizeInBits] |= (ChunkType(1) << (i % ChunkSizeInBits)); + Bits.getValue().setBit(i); } /// Clear bit i. void clearBit(size_t i) { assert(i < size()); - if (isInlineAndAllClear()) return; - getChunksPtr()[i / ChunkSizeInBits] &= ~(ChunkType(1) << (i % ChunkSizeInBits)); + Bits.getValue().clearBit(i); } /// Toggle bit i. void flipBit(size_t i) { assert(i < size()); - if (isInlineAndAllClear()) { - reserve(LengthInBits); - } - getChunksPtr()[i / ChunkSizeInBits] ^= (ChunkType(1) << (i % ChunkSizeInBits)); + Bits.getValue().flipBit(i); } /// Toggle all the bits in this vector. void flipAll() { - if (empty()) return; - if (isInlineAndAllClear()) { - reserve(LengthInBits); - } - for (auto &chunk : getChunks()) { - chunk = ~chunk; - } - if (auto tailBits = size() % ChunkSizeInBits) { - getChunks().back() &= ((ChunkType(1) << tailBits) - 1); + if (Bits) { + Bits.getValue().flipAllBits(); } } - /// Set the length of this vector to zero, but do not release any capacity. + /// Set the length of this vector to zero. void clear() { - LengthInBits = 0; - if (!hasOutOfLineData()) - Data = 0; + Bits.reset(); } /// Count the number of set bits in this vector. size_t count() const { - if (isInlineAndAllClear()) return 0; - size_t count = 0; - for (ChunkType chunk : getChunks()) { - count += llvm::countPopulation(chunk); - } - return count; + return Bits ? Bits.getValue().countPopulation() : 0; } /// Determine if there are any bits set in this vector. bool any() const { - if (isInlineAndAllClear()) return false; - for (ChunkType chunk : getChunks()) { - if (chunk) return true; - } - return false; + return Bits && Bits.getValue() != 0; } /// Determine if there are no bits set in this vector. @@ -541,16 +222,13 @@ class ClusteredBitVector { friend bool operator==(const ClusteredBitVector &lhs, const ClusteredBitVector &rhs) { - if (lhs.size() != rhs.size()) + if (lhs.size() != rhs.size()) { return false; - if (lhs.empty()) + } + if (lhs.size() == 0) { return true; - - if (!lhs.hasOutOfLineData() && !rhs.hasOutOfLineData()) { - return lhs.Data == rhs.Data; - } else { - return equalsSlowCase(lhs, rhs); } + return lhs.Bits.getValue() == rhs.Bits.getValue(); } friend bool operator!=(const ClusteredBitVector &lhs, const ClusteredBitVector &rhs) { @@ -559,73 +237,36 @@ class ClusteredBitVector { /// Return this bit-vector as an APInt, with low indices becoming /// the least significant bits of the number. - llvm::APInt asAPInt() const; - - /// Construct a bit-vector from an APInt. - static ClusteredBitVector fromAPInt(const llvm::APInt &value); - - /// Pretty-print the vector. - void print(llvm::raw_ostream &out) const; - void dump() const; - -private: - /// Make this object store an independent copy of the out of line - /// data it currently stores, simply overwriting the current pointer - /// without deleting it. - void makeIndependentCopy() { - assert(hasOutOfLineData()); - auto lengthToCopy = getLengthInChunks(); - allocateAndCopyFrom(getOutOfLineChunksPtr(), lengthToCopy, lengthToCopy); + APInt asAPInt() const { + // Return 1-bit wide zero APInt for a 0-bit vector. + return Bits ? Bits.getValue() : APInt(); } - /// Reallocate this vector, copying the current data into the new space. - void reallocate(size_t newCapacityInChunks); - - ChunkType *allocate(size_t newCapacityInChunks) { - assert(HasOutOfLineData && "bit should already be set"); - ChunkType *newData = new ChunkType[newCapacityInChunks + 1] + 1; - newData[-1] = newCapacityInChunks * ChunkSizeInBits; - Data = reinterpret_cast(newData); - assert(!isInlineAndAllClear()); - assert(getCapacityInChunks() == newCapacityInChunks); - return newData; - } - - void allocateAndCopyFrom(const ChunkType *oldData, - size_t newCapacityInChunks, - size_t numChunksToCopy) { - auto newData = allocate(newCapacityInChunks); - memcpy(newData, oldData, numChunksToCopy * sizeof(ChunkType)); + /// Construct a bit-vector from an APInt. + static ClusteredBitVector fromAPInt(const APInt &value) { + return ClusteredBitVector(value); } - /// Drop references to the current data. - void dropData() { - LengthInBits = 0; - HasOutOfLineData = false; - Data = 0; + /// Construct a bit-vector from an APInt. + static ClusteredBitVector fromAPInt(APInt &&value) { + return ClusteredBitVector(std::move(value)); } - /// Destroy the out of line data currently stored in this object. - void destroy() { - assert(hasOutOfLineData()); - delete[] (getOutOfLineChunksPtr() - 1); + /// Return a constant bit-vector of the given size. + static ClusteredBitVector getConstant(size_t numBits, bool value) { + if (numBits == 0) { + return ClusteredBitVector(); + } + auto vec = APInt::getNullValue(numBits); + if (value) { + vec.flipAllBits(); + } + return ClusteredBitVector(vec); } - /// Append a certain number of constant bits to this vector, given - /// that it's known to contain enough capacity for them. - void appendConstantBitsReserved(size_t numBits, bool addOnes); - - /// Append bits from the given array to this vector. - void appendReserved(size_t numBits, const ChunkType *nextChunk); - - /// Append bits to this vector, given that it's known to contain - /// enough capacity for them all. - void appendReserved(size_t numBits, - llvm::function_ref generator); - - /// The slow case of equality-checking. - static bool equalsSlowCase(const ClusteredBitVector &lhs, - const ClusteredBitVector &rhs); + /// Pretty-print the vector. + void print(llvm::raw_ostream &out) const; + void dump() const; }; } // end namespace swift diff --git a/lib/Basic/ClusteredBitVector.cpp b/lib/Basic/ClusteredBitVector.cpp index 0a7789554ccbc..8fd55836065aa 100644 --- a/lib/Basic/ClusteredBitVector.cpp +++ b/lib/Basic/ClusteredBitVector.cpp @@ -16,193 +16,10 @@ #include "swift/Basic/ClusteredBitVector.h" -#include "llvm/ADT/APInt.h" #include "llvm/Support/raw_ostream.h" using namespace swift; -ClusteredBitVector ClusteredBitVector::fromAPInt(const llvm::APInt &bits) { - // This is not a very efficient algorithm. - ClusteredBitVector result; - for (unsigned i = 0, e = bits.getBitWidth(); i != e; ++i) { - if (bits[i]) { - result.appendSetBits(1); - } else { - result.appendClearBits(1); - } - } - return result; -} - -llvm::APInt ClusteredBitVector::asAPInt() const { - if (size() == 0) { - // APInt doesn't like zero-bit values. - return llvm::APInt(1, 0); - } - - if (isInlineAndAllClear()) { - return llvm::APInt(size(), 0); - } else { - // This assumes that the chunk size is the same as APInt's. - // TODO: it'd be nice to be able to do this without copying. - return llvm::APInt(size(), getChunks()); - } -} - -void ClusteredBitVector::reallocate(size_t newCapacityInChunks) { - // If we already have out-of-line storage, the padding invariants - // will still apply, and we just need to copy the old data into - // the new allocation. - if (hasOutOfLineData()) { - auto oldData = getOutOfLineChunksPtr(); - allocateAndCopyFrom(oldData, newCapacityInChunks, getLengthInChunks()); - delete[] (oldData - 1); - return; - } - - // Otherwise, we might need to establish the invariants. If we - // were in inline-and-all-clear mode, the vector might logically - // be much longer than a single chunk, but all-zero. - HasOutOfLineData = true; - auto oldDataValue = Data; - auto newData = allocate(newCapacityInChunks); - - // All of these cases initialize 'length' chunks in newData. - switch (auto length = getLengthInChunks()) { - case 0: - break; - case 1: - newData[0] = oldDataValue; - break; - default: - assert(oldDataValue == 0 && "not previously in inline-and-all-clear?"); - memset(newData, 0, length * sizeof(ChunkType)); - break; - } -} - -void ClusteredBitVector::appendReserved(size_t numBits, - llvm::function_ref generator) { - assert(LengthInBits + numBits <= getCapacityInBits()); - assert(numBits > 0); - - auto getMoreBits = - [&](size_t numBitsWanted) -> ChunkType { - auto result = generator(numBitsWanted); - assert((numBitsWanted == ChunkSizeInBits || - result <= (ChunkType(1) << numBitsWanted)) && - "generator returned out-of-range value!"); - return result; - }; - - // Check whether the current end of the vector is a clean multiple - // of the chunk size. - auto offset = LengthInBits % ChunkSizeInBits; - ChunkType *nextChunk = &getChunksPtr()[LengthInBits / ChunkSizeInBits]; - - // Now we can go ahead and add in the right number of extra bits. - LengthInBits += numBits; - - // If not, we need to combine the generator result with that last chunk. - if (offset) { - auto claimedBits = std::min(numBits, size_t(ChunkSizeInBits - offset)); - - // The extra bits in data[chunkIndex] are guaranteed to be zero. - *nextChunk++ |= (getMoreBits(claimedBits) << offset); - - numBits -= claimedBits; - if (numBits == 0) return; - } - - // For the rest, just generator chunks one at a time. - do { - auto claimedBits = std::min(numBits, size_t(ChunkSizeInBits)); - *nextChunk++ = getMoreBits(claimedBits); - numBits -= claimedBits; - } while (numBits); -} - -void ClusteredBitVector::appendConstantBitsReserved(size_t numBits, - bool addOnes) { - assert(LengthInBits + numBits <= getCapacityInBits()); - assert(numBits > 0); - - ChunkType pattern = (addOnes ? ~ChunkType(0) : ChunkType(0)); - appendReserved(numBits, [=](size_t numBitsWanted) -> ChunkType { - return (pattern >> (ChunkSizeInBits - numBitsWanted)); - }); -} - -void ClusteredBitVector::appendReserved(size_t numBits, - const ChunkType *nextChunk) { - // This is easy if we're not currently at an offset. - // (Note that this special case generator relies on the exact - // implementation of the main appendReserved routine.) - auto offset = LengthInBits % ChunkSizeInBits; - if (!offset) { - appendReserved(numBits, [&](size_t numBitsWanted) -> ChunkType { - return *nextChunk++; - }); - return; - } - - // But if we are, we need to be constantly mixing values. - ChunkType prevChunk = 0; - size_t bitsRemaining = 0; - appendReserved(numBits, [&](size_t numBitsWanted) -> ChunkType { - auto resultMask = (numBitsWanted == ChunkSizeInBits - ? ~ChunkType(0) - : ((ChunkType(1) << numBitsWanted) - 1)); - - // If we can resolve the desired bits out of the current chunk, - // all the better. - if (numBitsWanted <= bitsRemaining) { - assert(numBitsWanted != ChunkSizeInBits); - auto result = prevChunk & resultMask; - bitsRemaining -= numBitsWanted; - prevChunk >>= numBitsWanted; - return result; - } - - // |-- bitsRemaining --|-------- ChunkSizeInBits --------| - // | prevChunk | nextChunk | - // |------ numBitsWanted ------|----- bitsRemaining' ----| - // | prevChunk' | - - auto newChunk = *nextChunk++; - auto result = (prevChunk | (newChunk << bitsRemaining)) & resultMask; - prevChunk = newChunk >> (numBitsWanted - bitsRemaining); - bitsRemaining = ChunkSizeInBits + bitsRemaining - numBitsWanted; - return result; - }); -} - -bool ClusteredBitVector::equalsSlowCase(const ClusteredBitVector &lhs, - const ClusteredBitVector &rhs) { - assert(lhs.size() == rhs.size()); - assert(!lhs.empty() && !rhs.empty()); - assert(lhs.hasOutOfLineData() || rhs.hasOutOfLineData()); - - if (!lhs.hasOutOfLineData()) { - assert(lhs.Data == 0 || lhs.getLengthInChunks() == 1); - for (auto chunk : rhs.getOutOfLineChunks()) - if (chunk != lhs.Data) - return false; - return true; - } else if (!rhs.hasOutOfLineData()) { - assert(rhs.Data == 0 || rhs.getLengthInChunks() == 1); - for (auto chunk : lhs.getOutOfLineChunks()) - if (chunk != rhs.Data) - return false; - return true; - } else { - auto lhsChunks = lhs.getOutOfLineChunks(); - auto rhsChunks = rhs.getOutOfLineChunks(); - assert(lhsChunks.size() == rhsChunks.size()); - return lhsChunks == rhsChunks; - } -} - void ClusteredBitVector::dump() const { print(llvm::errs()); } @@ -210,8 +27,12 @@ void ClusteredBitVector::dump() const { /// Pretty-print the vector. void ClusteredBitVector::print(llvm::raw_ostream &out) const { // Print in 8 clusters of 8 bits per row. + if (!Bits) { + return; + } + auto &v = Bits.getValue(); for (size_t i = 0, e = size(); ; ) { - out << ((*this)[i++] ? '1' : '0'); + out << (v[i++] ? '1' : '0'); if (i == e) { return; } else if ((i & 64) == 0) { diff --git a/lib/IRGen/GenStruct.cpp b/lib/IRGen/GenStruct.cpp index 7fd74c977962f..596ef72fbafaa 100644 --- a/lib/IRGen/GenStruct.cpp +++ b/lib/IRGen/GenStruct.cpp @@ -626,7 +626,6 @@ class ClangRecordLowering { TotalStride(Size(ClangLayout.getSize().getQuantity())), TotalAlignment(IGM.getCappedAlignment( Alignment(ClangLayout.getAlignment()))) { - SpareBits.reserve(TotalStride.getValue() * 8); } void collectRecordFields() { diff --git a/unittests/Basic/ClusteredBitVectorTest.cpp b/unittests/Basic/ClusteredBitVectorTest.cpp index 5fa3186db8cf3..02037ceee3085 100644 --- a/unittests/Basic/ClusteredBitVectorTest.cpp +++ b/unittests/Basic/ClusteredBitVectorTest.cpp @@ -115,22 +115,6 @@ TEST(ClusteredBitVector, AssignAfterGrowth) { EXPECT_EQ(false, vec[64]); } -/// define == on llvm::Optional, you jerks -template struct ComparableOptional { - Optional Value; - ComparableOptional(const T &value) : Value(value) {} - ComparableOptional() : Value() {} - - bool operator==(const Optional &other) const { - if (Value.hasValue()) { - return other.hasValue() - && Value.getValue() == other.getValue(); - } else { - return !other.hasValue(); - } - } -}; - TEST(ClusteredBitVector, SetClearBit) { ClusteredBitVector vec; vec.appendClearBits(64); From c50fee199ff639f92231d2e282fbebe50fffd252 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 3 Jun 2019 11:17:00 -0700 Subject: [PATCH 021/112] tests: improve resilience test helper for Windows Windows does not support the concept of RPATH. As a result, we must change the working directory for the test. This extends the support for the tests to work with PE/COFF on Windows. Use the newly minted `self.triple` property to drive the host detection. This means that the test coverage on Windows is able to test most of the resilience functionality. --- utils/rth | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/utils/rth b/utils/rth index fd507d466acf9..9b55de21203ff 100755 --- a/utils/rth +++ b/utils/rth @@ -74,7 +74,10 @@ class ResilienceTest(object): os.makedirs(self.before_dir) def is_apple_platform(self): - return any('-apple-' in arg for arg in self.target_build_swift) + return self.triple.split('-')[1] == 'apple' + + def is_windows_host(self): + return self.triple.split('-')[2] == 'windows' def compile_library(self): for config in self.config_dir_map: @@ -172,7 +175,10 @@ class ResilienceTest(object): config1_lower + '_' + config2_lower) if self.is_apple_platform(): rpath_origin = '@executable_path' + elif self.is_windows_host(): + pass else: + # assume it is an ELF host rpath_origin = '$ORIGIN' compiler_flags = [ @@ -180,13 +186,21 @@ class ResilienceTest(object): '-l' + self.lib_name, os.path.join(self.config_dir_map[config2], 'main.o'), - '-Xlinker', '-rpath', '-Xlinker', - os.path.join(rpath_origin, - os.path.relpath(self.config_dir_map[config1], - self.tmp_dir)), '-o', output_obj ] + if self.is_windows_host(): + # Emulate RPATH by changing to the location as `PATH` is what + # drives library searching on Windows + os.chdir(self.config_dir_map[config1]) + else: + compiler_flags.extend([ + '-Xlinker', '-rpath', '-Xlinker', + os.path.join(rpath_origin, + os.path.relpath(self.config_dir_map[config1], + self.tmp_dir)), + ]) + if self.is_apple_platform(): compiler_flags += ['-Xlinker', '-bind_at_load'] From 2f34b0b4b667b46525929baa08dd3e216bf29acc Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 4 Jun 2019 09:33:03 -0700 Subject: [PATCH 022/112] test: invoke scale-test with the interpreter The scale-test utility is a python script which was relying on the shebang to invoke the interpreter. However, not all targets support such an invocation mechanism (i.e. Windows doesn't support this). Explicitly invoke the interpreter to ensure that the tool is executed properly. --- test/lit.cfg | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/lit.cfg b/test/lit.cfg index 7dbb90dfde51b..afc39cc78ae49 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -1490,8 +1490,9 @@ config.substitutions.append(('%round-trip-syntax-test', config.round_trip_syntax_test))) config.substitutions.append(('%rth', '%r %s' % (sys.executable, config.rth))) config.substitutions.append(('%scale-test', - '{} --swiftc-binary={} --tmpdir=%t'.format( - config.scale_test, config.swiftc))) + '{} {} --swiftc-binary={} --tmpdir=%t'.format( + sys.executable, config.scale_test, + config.swiftc))) config.substitutions.append(('%empty-directory\(([^)]+)\)', SubstituteCaptures(r'rm -rf "\1" && mkdir -p "\1"'))) From 551c1be92698b4754c266205df0e04eda46592a7 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 4 Jun 2019 09:41:49 -0700 Subject: [PATCH 023/112] validation-test: make stdlib.string compile on Win32 The C library functions used here do not appear without the C runtime being imported (ucrt or MSVCRT). Adjust the test as such. This exposes a stack corruption in the test which needs to be resolved. --- validation-test/stdlib/String.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/validation-test/stdlib/String.swift b/validation-test/stdlib/String.swift index 02577109ccfbc..0a53cc3db5b76 100644 --- a/validation-test/stdlib/String.swift +++ b/validation-test/stdlib/String.swift @@ -20,6 +20,10 @@ import NSSlowString import Foundation // For NSRange #endif +#if os(Windows) +import ucrt +#endif + extension Collection { internal func index(_nth n: Int) -> Index { precondition(n >= 0) From db9a6cae4dd837a952f0c9b0495392fbe823f69b Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 4 Jun 2019 13:04:21 -0700 Subject: [PATCH 024/112] validation-test: refactor the test invocation (NFC) This just uses the `%target-build-swift-dylib` instead of `%target-build-swift` substitution along with `%target-library-name` to ensure that we are target independent. --- validation-test/execution/dsohandle-multi-module.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/validation-test/execution/dsohandle-multi-module.swift b/validation-test/execution/dsohandle-multi-module.swift index a88b78ae6115c..01a28856bcf6c 100644 --- a/validation-test/execution/dsohandle-multi-module.swift +++ b/validation-test/execution/dsohandle-multi-module.swift @@ -1,7 +1,7 @@ // RUN: %empty-directory(%t) -// RUN: (cd %t && %target-build-swift %S/Inputs/dsohandle-first.swift -emit-library -emit-module -module-name first -Xlinker -install_name -Xlinker '@executable_path/libfirst.dylib') -// RUN: (cd %t && %target-build-swift %S/Inputs/dsohandle-second.swift -emit-library -emit-module -module-name second -Xlinker -install_name -Xlinker '@executable_path/libsecond.dylib') +// RUN: %target-build-swift-dylib(%t/%target-library-name(first)) %S/Inputs/dsohandle-first.swift -emit-module -module-name first +// RUN: %target-build-swift-dylib(%t/%target-library-name(second)) %S/Inputs/dsohandle-second.swift -emit-module -module-name second // RUN: %target-build-swift -I %t -L %t -lfirst -lsecond %s -o %t/main // RUN: %target-codesign %t/main %t/%target-library-name(first) %t/%target-library-name(second) // RUN: %target-run %t/main %t/%target-library-name(first) %t/%target-library-name(second) From 72c6dbb33648c6b62c57ceab15c7594603834edd Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 4 Jun 2019 14:26:07 -0700 Subject: [PATCH 025/112] [ConstraintSystem] Separate parameter label removal from generic function opening --- lib/Sema/CSRanking.cpp | 19 ++++++--------- lib/Sema/ConstraintSystem.cpp | 46 ++++++++++++++++------------------- lib/Sema/ConstraintSystem.h | 15 +++++------- 3 files changed, 34 insertions(+), 46 deletions(-) diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp index 69a753507baa5..fe90112956766 100644 --- a/lib/Sema/CSRanking.cpp +++ b/lib/Sema/CSRanking.cpp @@ -517,12 +517,10 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc, OpenedTypeMap unused; Type openedType2; if (auto *funcType = type2->getAs()) { - openedType2 = cs.openFunctionType( - funcType, /*numArgumentLabelsToRemove=*/0, locator, - /*replacements=*/unused, - innerDC2, - outerDC2, - /*skipProtocolSelfConstraint=*/false); + openedType2 = + cs.openFunctionType(funcType, locator, + /*replacements=*/unused, innerDC2, outerDC2, + /*skipProtocolSelfConstraint=*/false); } else { cs.openGeneric(innerDC2, outerDC2, @@ -539,12 +537,9 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc, OpenedTypeMap replacements; Type openedType1; if (auto *funcType = type1->getAs()) { - openedType1 = cs.openFunctionType( - funcType, /*numArgumentLabelsToRemove=*/0, locator, - replacements, - innerDC1, - outerDC1, - /*skipProtocolSelfConstraint=*/false); + openedType1 = cs.openFunctionType(funcType, locator, replacements, + innerDC1, outerDC1, + /*skipProtocolSelfConstraint=*/false); } else { cs.openGeneric(innerDC1, outerDC1, diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 8a2f2d5fbb5c1..35e84ae67fb82 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -633,9 +633,8 @@ Type ConstraintSystem::openType(Type type, OpenedTypeMap &replacements) { }); } -Type ConstraintSystem::openFunctionType( +FunctionType *ConstraintSystem::openFunctionType( AnyFunctionType *funcType, - unsigned numArgumentLabelsToRemove, ConstraintLocatorBuilder locator, OpenedTypeMap &replacements, DeclContext *innerDC, @@ -671,7 +670,7 @@ Type ConstraintSystem::openFunctionType( FunctionType::ExtInfo().withThrows(genericFn->throws())); } - return funcType->removeArgumentLabels(numArgumentLabelsToRemove); + return funcType->castTo(); } Optional ConstraintSystem::isArrayType(Type type) { @@ -936,12 +935,10 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, auto openedType = openFunctionType( func->getInterfaceType()->castTo(), - /*numArgumentLabelsToRemove=*/0, locator, replacements, func->getInnermostDeclContext(), func->getDeclContext(), /*skipProtocolSelfConstraint=*/false); - auto openedFnType = openedType->castTo(); // If we opened up any type variables, record the replacements. recordOpenedTypes(locator, replacements); @@ -950,19 +947,18 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, // DynamicSelf with the actual object type. if (!func->getDeclContext()->getSelfProtocolDecl()) { if (func->hasDynamicSelf()) { - auto params = openedFnType->getParams(); + auto params = openedType->getParams(); assert(params.size() == 1); Type selfTy = params.front().getPlainType()->getMetatypeInstanceType(); - openedType = openedType->replaceCovariantResultType(selfTy, 2); - openedFnType = openedType->castTo(); + openedType = openedType->replaceCovariantResultType(selfTy, 2) + ->castTo(); } } else { - openedType = openedType->eraseDynamicSelfType(); - openedFnType = openedType->castTo(); + openedType = openedType->eraseDynamicSelfType()->castTo(); } // The reference implicitly binds 'self'. - return { openedType, openedFnType->getResult() }; + return {openedType, openedType->getResult()}; } // Unqualified reference to a local or global function. @@ -970,16 +966,15 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, OpenedTypeMap replacements; auto funcType = funcDecl->getInterfaceType()->castTo(); - auto openedType = - openFunctionType( - funcType, - getNumRemovedArgumentLabels(TC, funcDecl, - /*isCurriedInstanceReference=*/false, - functionRefKind), - locator, replacements, - funcDecl->getInnermostDeclContext(), - funcDecl->getDeclContext(), - /*skipProtocolSelfConstraint=*/false); + auto numLabelsToRemove = getNumRemovedArgumentLabels( + TC, funcDecl, + /*isCurriedInstanceReference=*/false, functionRefKind); + + auto openedType = openFunctionType(funcType, locator, replacements, + funcDecl->getInnermostDeclContext(), + funcDecl->getDeclContext(), + /*skipProtocolSelfConstraint=*/false) + ->removeArgumentLabels(numLabelsToRemove); // If we opened up any type variables, record the replacements. recordOpenedTypes(locator, replacements); @@ -1331,10 +1326,11 @@ ConstraintSystem::getTypeOfMemberReference( // While opening member function type, let's delay opening requirements // to allow contextual types to affect the situation. - openedType = openFunctionType(funcType, numRemovedArgumentLabels, - locator, replacements, innerDC, outerDC, - /*skipProtocolSelfConstraint=*/true, - /*skipGenericRequirements=*/true); + openedType = + openFunctionType(funcType, locator, replacements, innerDC, outerDC, + /*skipProtocolSelfConstraint=*/true, + /*skipGenericRequirements=*/true) + ->removeArgumentLabels(numRemovedArgumentLabels); if (!outerDC->getSelfProtocolDecl()) { // Class methods returning Self as well as constructors get the diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 326b374a8947d..0086b908692bf 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -2380,15 +2380,12 @@ class ConstraintSystem { /// requirements asscoiated with given function type. /// /// \returns The opened type, or \c type if there are no archetypes in it. - Type openFunctionType( - AnyFunctionType *funcType, - unsigned numArgumentLabelsToRemove, - ConstraintLocatorBuilder locator, - OpenedTypeMap &replacements, - DeclContext *innerDC, - DeclContext *outerDC, - bool skipProtocolSelfConstraint, - bool skipGenericRequirements = false); + FunctionType *openFunctionType(AnyFunctionType *funcType, + ConstraintLocatorBuilder locator, + OpenedTypeMap &replacements, + DeclContext *innerDC, DeclContext *outerDC, + bool skipProtocolSelfConstraint, + bool skipGenericRequirements = false); /// Open the generic parameter list and (if requested) its requirements, /// creating type variables for each of the type parameters. From fa513db7edd3da714790c5509eb46a543cd8fb77 Mon Sep 17 00:00:00 2001 From: Gwen Mittertreiner Date: Mon, 3 Jun 2019 13:23:12 -0700 Subject: [PATCH 026/112] Run Sourcekitd-tests in a non dispatch thread Since Dispatch threads have a 64k stack size, tests were failing due to blowing the stack on Windows. This runs the tests in thread with a larger stack size. This fixes some 90ish sourcekit tests on Windows. --- .../lib/SwiftLang/SwiftASTManager.cpp | 11 ++++++- .../tools/sourcekitd-test/sourcekitd-test.cpp | 33 +++++++++++++------ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp index 0c78d639e56c1..2537b837d7939 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp @@ -186,6 +186,15 @@ namespace SourceKit { void ASTUnit::Implementation::consumeAsync(SwiftASTConsumerRef ConsumerRef, ASTUnitRef ASTRef) { +#if defined(_WIN32) + // Windows uses more up for stack space (why?) than macOS/Linux which + // causes stack overflows in a dispatch thread with 64k stack. Passing + // useDeepStack=true means it's given a _beginthreadex thread with an 8MB + // stack. + bool useDeepStack = true; +#else + bool useDeepStack = false; +#endif Queue.dispatch([ASTRef, ConsumerRef]{ SwiftASTConsumer &ASTConsumer = *ConsumerRef; @@ -197,7 +206,7 @@ namespace SourceKit { LOG_WARN_FUNC("did not find primary SourceFile"); ConsumerRef->failed("did not find primary SourceFile"); } - }); + }, useDeepStack); } ASTUnit::ASTUnit(uint64_t Generation, std::shared_ptr Stats) diff --git a/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp b/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp index 4054778e4e46a..dd1a644691d5a 100644 --- a/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp +++ b/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp @@ -26,11 +26,12 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Regex.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" #include #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -#include #include +#include #elif defined(_WIN32) #define WIN32_LEAN_AND_MEAN #define NOMINMAX @@ -211,18 +212,26 @@ static void printBufferedNotifications(bool syncWithService = true) { }); } -static int skt_main(int argc, const char **argv); +struct skt_args { + int argc; + const char **argv; + int ret; +}; +static void skt_main(skt_args *args); int main(int argc, const char **argv) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ - int ret = skt_main(argc, argv); - exit(ret); + skt_args args = {argc, argv, 0}; + llvm::llvm_execute_on_thread((void (*)(void *))skt_main, &args); + exit(args.ret); }); dispatch_main(); } -static int skt_main(int argc, const char **argv) { +static void skt_main(skt_args *args) { + int argc = args->argc; + const char **argv = args->argv; llvm::sys::PrintStackTraceOnErrorSignal(argv[0]); sourcekitd_initialize(); @@ -261,14 +270,16 @@ static int skt_main(int argc, const char **argv) { break; if (int ret = handleTestInvocation(Args.slice(0, i), InitOpts)) { sourcekitd_shutdown(); - return ret; + args->ret = ret; + return; } - Args = Args.slice(i+1); + Args = Args.slice(i + 1); } if (int ret = handleTestInvocation(Args, InitOpts)) { sourcekitd_shutdown(); - return ret; + args->ret = ret; + return; } for (auto &info : asyncResponses) { @@ -279,13 +290,15 @@ static int skt_main(int argc, const char **argv) { if (handleResponse(info.response, info.options, info.sourceFilename, std::move(info.sourceBuffer), nullptr)) { sourcekitd_shutdown(); - return 1; + args->ret = 1; + return; } } printBufferedNotifications(); sourcekitd_shutdown(); - return 0; + args->ret = 0; + return; } static inline const char *getInterfaceGenDocumentName() { From af0b14e5edfacb8766e446d583e1b43932e877a5 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 4 Jun 2019 15:11:07 -0700 Subject: [PATCH 027/112] SILGen: refactor `#dsohandle` implementation Extract a couple of local variables. Reflow the text and rearrange the flow to support Windows. --- lib/SILGen/SILGenExpr.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index c490e36484928..4898309be67b8 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -3628,20 +3628,22 @@ visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *E, SGFContext C) { SGF.getLoweredType(UnsafeRawPointer->getDeclaredInterfaceType()); SILType BuiltinRawPtrTy = SILType::getRawPointerType(SGF.getASTContext()); + SILModule &M = SGF.SGM.M; + SILBuilder &B = SGF.B; - auto DSOGlobal = SGF.SGM.M.lookUpGlobalVariable("__dso_handle"); + auto DSOGlobal = M.lookUpGlobalVariable("__dso_handle"); if (!DSOGlobal) - DSOGlobal = SILGlobalVariable::create(SGF.SGM.M, - SILLinkage::PublicExternal, - IsNotSerialized, "__dso_handle", - BuiltinRawPtrTy); - auto DSOAddr = SGF.B.createGlobalAddr(SILLoc, DSOGlobal); + DSOGlobal = + SILGlobalVariable::create(M, SILLinkage::PublicExternal, + IsNotSerialized, "__dso_handle", + BuiltinRawPtrTy); - auto DSOPointer = SGF.B.createAddressToPointer(SILLoc, DSOAddr, - BuiltinRawPtrTy); + auto DSOAddr = B.createGlobalAddr(SILLoc, DSOGlobal); + auto DSOPointer = + B.createAddressToPointer(SILLoc, DSOAddr, BuiltinRawPtrTy); + auto UnsafeRawPtrStruct = + B.createStruct(SILLoc, UnsafeRawPtrTy, { DSOPointer }); - auto UnsafeRawPtrStruct = SGF.B.createStruct(SILLoc, UnsafeRawPtrTy, - { DSOPointer }); return RValue(SGF, E, ManagedValue::forUnmanaged(UnsafeRawPtrStruct)); } } From 585659177764a603428eded862d2b6202b4c8681 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 4 Jun 2019 16:20:31 -0700 Subject: [PATCH 028/112] SILGen: make `#dsohandle` work properly on Windows Windows has a special symbol `__ImageBase` whcih provides the constant value of the base of the image. This is roughly equivalent to the `__dso_handle` on the ELF and MachO targets. Use this to construct the value for the `#dsohandle` rather than attempting to use the non-existent symbol `__dso_handle`. This fixes the dsohandle-multi-module validation test on Windows. --- lib/SILGen/SILGenExpr.cpp | 41 +++++++++++++++++++---------- test/SILGen/default_arguments.swift | 2 +- test/SILGen/dso_handle.swift | 2 +- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 4898309be67b8..e1d02a526018d 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -3631,20 +3631,33 @@ visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *E, SGFContext C) { SILModule &M = SGF.SGM.M; SILBuilder &B = SGF.B; - auto DSOGlobal = M.lookUpGlobalVariable("__dso_handle"); - if (!DSOGlobal) - DSOGlobal = - SILGlobalVariable::create(M, SILLinkage::PublicExternal, - IsNotSerialized, "__dso_handle", - BuiltinRawPtrTy); - - auto DSOAddr = B.createGlobalAddr(SILLoc, DSOGlobal); - auto DSOPointer = - B.createAddressToPointer(SILLoc, DSOAddr, BuiltinRawPtrTy); - auto UnsafeRawPtrStruct = - B.createStruct(SILLoc, UnsafeRawPtrTy, { DSOPointer }); - - return RValue(SGF, E, ManagedValue::forUnmanaged(UnsafeRawPtrStruct)); + StructInst *S = nullptr; + if (M.getASTContext().LangOpts.Target.isOSWindows()) { + auto ImageBase = M.lookUpGlobalVariable("__ImageBase"); + if (!ImageBase) + ImageBase = + SILGlobalVariable::create(M, SILLinkage::Public, IsNotSerialized, + "__ImageBase", BuiltinRawPtrTy); + + auto ImageBaseAddr = B.createGlobalAddr(SILLoc, ImageBase); + auto ImageBasePointer = + B.createAddressToPointer(SILLoc, ImageBaseAddr, BuiltinRawPtrTy); + S = B.createStruct(SILLoc, UnsafeRawPtrTy, { ImageBasePointer }); + } else { + auto DSOGlobal = M.lookUpGlobalVariable("__dso_handle"); + if (!DSOGlobal) + DSOGlobal = + SILGlobalVariable::create(M, SILLinkage::PublicExternal, + IsNotSerialized, "__dso_handle", + BuiltinRawPtrTy); + + auto DSOAddr = B.createGlobalAddr(SILLoc, DSOGlobal); + auto DSOPointer = + B.createAddressToPointer(SILLoc, DSOAddr, BuiltinRawPtrTy); + S = B.createStruct(SILLoc, UnsafeRawPtrTy, { DSOPointer }); + } + + return RValue(SGF, E, ManagedValue::forUnmanaged(S)); } } diff --git a/test/SILGen/default_arguments.swift b/test/SILGen/default_arguments.swift index aa4b8db3f0d8b..e02df77f39b56 100644 --- a/test/SILGen/default_arguments.swift +++ b/test/SILGen/default_arguments.swift @@ -199,7 +199,7 @@ func takeDSOHandle(_ handle: UnsafeRawPointer = #dsohandle) { } // CHECK-LABEL: sil hidden [ossa] @$s17default_arguments13testDSOHandleyyF func testDSOHandle() { - // CHECK: [[DSO_HANDLE:%[0-9]+]] = global_addr @__dso_handle : $*Builtin.RawPointer + // CHECK: [[DSO_HANDLE:%[0-9]+]] = global_addr {{@__dso_handle|@__ImageBase}} : $*Builtin.RawPointer takeDSOHandle() } diff --git a/test/SILGen/dso_handle.swift b/test/SILGen/dso_handle.swift index e20b3ac3845e6..e7fec3557f27d 100644 --- a/test/SILGen/dso_handle.swift +++ b/test/SILGen/dso_handle.swift @@ -1,6 +1,6 @@ // RUN: %target-swift-emit-silgen -Xllvm -sil-full-demangle %s | %FileCheck %s -// CHECK: sil_global [[DSO:@__dso_handle]] : $Builtin.RawPointer +// CHECK: sil_global [[DSO:@__dso_handle|@__ImageBase]] : $Builtin.RawPointer // CHECK-LABEL: sil [ossa] @main : $@convention(c) // CHECK: bb0 From 655a60af4d0b2dcf97c52a5d518729324974634d Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 4 Jun 2019 16:35:14 -0700 Subject: [PATCH 029/112] validation-test: correct typo in ParseableInterface.verify_all_overlays The `%{python}` substitution was typoed with the `%` sigil being replaced with `$`. --- validation-test/ParseableInterface/verify_all_overlays.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validation-test/ParseableInterface/verify_all_overlays.py b/validation-test/ParseableInterface/verify_all_overlays.py index 7235fb045c1ba..96c07b0c3834b 100755 --- a/validation-test/ParseableInterface/verify_all_overlays.py +++ b/validation-test/ParseableInterface/verify_all_overlays.py @@ -4,7 +4,7 @@ # generated. # RUN: %empty-directory(%t) -# RUN: ${python} %s %target-os %target-cpu %platform-sdk-overlay-dir %t \ +# RUN: %{python} %s %target-os %target-cpu %platform-sdk-overlay-dir %t \ # RUN: %target-swift-frontend -build-module-from-parseable-interface \ # RUN: -Fsystem %sdk/System/Library/PrivateFrameworks/ >> %t/failures.txt # RUN: test ! -e %t/failures.txt || \ From ef1e5425d4f7f5eabbe88d142077b8340db30cab Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 4 Jun 2019 17:50:44 -0700 Subject: [PATCH 030/112] [ConstraintSystem] Extract logic for opening generic parameters into its own method --- lib/Sema/ConstraintSystem.cpp | 48 +++++++++++++++++++---------------- lib/Sema/ConstraintSystem.h | 7 +++++ 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 35e84ae67fb82..56f13b114e280 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1108,28 +1108,7 @@ void ConstraintSystem::openGeneric( if (sig == nullptr) return; - auto locatorPtr = getConstraintLocator(locator); - - // Create the type variables for the generic parameters. - for (auto gp : sig->getGenericParams()) { - locatorPtr = getConstraintLocator( - locator.withPathElement(LocatorPathElt(gp))); - - auto typeVar = createTypeVariable(locatorPtr, - TVO_PrefersSubtypeBinding); - auto result = replacements.insert( - std::make_pair(cast(gp->getCanonicalType()), - typeVar)); - assert(result.second); - (void) result; - } - - // Remember that any new constraints generated by opening this generic are - // due to the opening. - locatorPtr = getConstraintLocator( - locator.withPathElement(LocatorPathElt::getOpenedGeneric(sig))); - - bindArchetypesFromContext(*this, outerDC, locatorPtr, replacements); + openGenericParameters(outerDC, sig, replacements, locator); if (skipGenericRequirements) return; @@ -1140,6 +1119,31 @@ void ConstraintSystem::openGeneric( [&](Type type) { return openType(type, replacements); }); } +void ConstraintSystem::openGenericParameters(DeclContext *outerDC, + GenericSignature *sig, + OpenedTypeMap &replacements, + ConstraintLocatorBuilder locator) { + assert(sig); + + // Create the type variables for the generic parameters. + for (auto gp : sig->getGenericParams()) { + auto *paramLocator = + getConstraintLocator(locator.withPathElement(LocatorPathElt(gp))); + + auto typeVar = createTypeVariable(paramLocator, TVO_PrefersSubtypeBinding); + auto result = replacements.insert(std::make_pair( + cast(gp->getCanonicalType()), typeVar)); + + assert(result.second); + (void)result; + } + + auto *baseLocator = getConstraintLocator( + locator.withPathElement(LocatorPathElt::getOpenedGeneric(sig))); + + bindArchetypesFromContext(*this, outerDC, baseLocator, replacements); +} + void ConstraintSystem::openGenericRequirements( DeclContext *outerDC, GenericSignature *signature, bool skipProtocolSelfConstraint, ConstraintLocatorBuilder locator, diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 0086b908692bf..af465b4b93dfe 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -2397,6 +2397,13 @@ class ConstraintSystem { OpenedTypeMap &replacements, bool skipGenericRequirements = false); + /// Open the generic parameter list creating type variables for each of the + /// type parameters. + void openGenericParameters(DeclContext *outerDC, + GenericSignature *signature, + OpenedTypeMap &replacements, + ConstraintLocatorBuilder locator); + /// Given generic signature open its generic requirements, /// using substitution function, and record them in the /// constraint system for further processing. From 930f74a023c57a87e28643b945f3d9f2ffa0c909 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 4 Jun 2019 18:00:22 -0700 Subject: [PATCH 031/112] [ConstraintSystem] Remove unused inner declaration context parameter from `openGeneric*` --- lib/Sema/CSRanking.cpp | 33 ++++++++++++--------------------- lib/Sema/CSSimplify.cpp | 7 +++---- lib/Sema/ConstraintSystem.cpp | 29 ++++++++--------------------- lib/Sema/ConstraintSystem.h | 7 ++----- 4 files changed, 25 insertions(+), 51 deletions(-) diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp index fe90112956766..aa8884ef9037b 100644 --- a/lib/Sema/CSRanking.cpp +++ b/lib/Sema/CSRanking.cpp @@ -341,10 +341,9 @@ static bool isProtocolExtensionAsSpecializedAs(TypeChecker &tc, // the second protocol extension. ConstraintSystem cs(tc, dc1, None); OpenedTypeMap replacements; - cs.openGeneric(dc2, dc2, sig2, + cs.openGeneric(dc2, sig2, /*skipProtocolSelfConstraint=*/false, - ConstraintLocatorBuilder(nullptr), - replacements); + ConstraintLocatorBuilder(nullptr), replacements); // Bind the 'Self' type from the first extension to the type parameter from // opening 'Self' of the second extension. @@ -517,17 +516,12 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc, OpenedTypeMap unused; Type openedType2; if (auto *funcType = type2->getAs()) { - openedType2 = - cs.openFunctionType(funcType, locator, - /*replacements=*/unused, innerDC2, outerDC2, - /*skipProtocolSelfConstraint=*/false); + openedType2 = cs.openFunctionType(funcType, locator, + /*replacements=*/unused, outerDC2, + /*skipProtocolSelfConstraint=*/false); } else { - cs.openGeneric(innerDC2, - outerDC2, - innerDC2->getGenericSignatureOfContext(), - /*skipProtocolSelfConstraint=*/false, - locator, - unused); + cs.openGeneric(outerDC2, innerDC2->getGenericSignatureOfContext(), + /*skipProtocolSelfConstraint=*/false, locator, unused); openedType2 = cs.openType(type2, unused); } @@ -537,15 +531,12 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc, OpenedTypeMap replacements; Type openedType1; if (auto *funcType = type1->getAs()) { - openedType1 = cs.openFunctionType(funcType, locator, replacements, - innerDC1, outerDC1, - /*skipProtocolSelfConstraint=*/false); + openedType1 = + cs.openFunctionType(funcType, locator, replacements, outerDC1, + /*skipProtocolSelfConstraint=*/false); } else { - cs.openGeneric(innerDC1, - outerDC1, - innerDC1->getGenericSignatureOfContext(), - /*skipProtocolSelfConstraint=*/false, - locator, + cs.openGeneric(outerDC1, innerDC1->getGenericSignatureOfContext(), + /*skipProtocolSelfConstraint=*/false, locator, replacements); openedType1 = cs.openType(type1, replacements); diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 8c766b12ffc9d..fd459a73aac16 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -4883,10 +4883,9 @@ ConstraintSystem::simplifyOpaqueUnderlyingTypeConstraint(Type type1, Type type2, // corresponding to the underlying type should be the constraints on the // underlying return type. OpenedTypeMap replacements; - openGeneric(nullptr, DC, opaque2->getBoundSignature(), - /*skip self*/ false, - locator, replacements); - + openGeneric(DC, opaque2->getBoundSignature(), + /*skip self*/ false, locator, replacements); + auto underlyingTyVar = openType(opaque2->getInterfaceType(), replacements); assert(underlyingTyVar); diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 56f13b114e280..667849f953295 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -465,12 +465,8 @@ Type ConstraintSystem::openUnboundGenericType(UnboundGenericType *unbound, } // Open up the generic type. - openGeneric(unboundDecl->getInnermostDeclContext(), - unboundDecl->getDeclContext(), - unboundDecl->getGenericSignature(), - /*skipProtocolSelfConstraint=*/false, - locator, - replacements); + openGeneric(unboundDecl->getDeclContext(), unboundDecl->getGenericSignature(), + /*skipProtocolSelfConstraint=*/false, locator, replacements); if (parentTy) { auto subs = parentTy->getContextSubstitutions( @@ -637,7 +633,6 @@ FunctionType *ConstraintSystem::openFunctionType( AnyFunctionType *funcType, ConstraintLocatorBuilder locator, OpenedTypeMap &replacements, - DeclContext *innerDC, DeclContext *outerDC, bool skipProtocolSelfConstraint, bool skipGenericRequirements) { @@ -645,12 +640,8 @@ FunctionType *ConstraintSystem::openFunctionType( if (auto *genericFn = funcType->getAs()) { // Open up the generic parameters and requirements. - openGeneric(innerDC, - outerDC, - genericFn->getGenericSignature(), - skipProtocolSelfConstraint, - locator, - replacements, + openGeneric(outerDC, genericFn->getGenericSignature(), + skipProtocolSelfConstraint, locator, replacements, skipGenericRequirements); // Transform the parameters and output type. @@ -936,7 +927,6 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, auto openedType = openFunctionType( func->getInterfaceType()->castTo(), locator, replacements, - func->getInnermostDeclContext(), func->getDeclContext(), /*skipProtocolSelfConstraint=*/false); @@ -971,7 +961,6 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, /*isCurriedInstanceReference=*/false, functionRefKind); auto openedType = openFunctionType(funcType, locator, replacements, - funcDecl->getInnermostDeclContext(), funcDecl->getDeclContext(), /*skipProtocolSelfConstraint=*/false) ->removeArgumentLabels(numLabelsToRemove); @@ -1098,7 +1087,6 @@ static void bindArchetypesFromContext( } void ConstraintSystem::openGeneric( - DeclContext *innerDC, DeclContext *outerDC, GenericSignature *sig, bool skipProtocolSelfConstraint, @@ -1330,11 +1318,10 @@ ConstraintSystem::getTypeOfMemberReference( // While opening member function type, let's delay opening requirements // to allow contextual types to affect the situation. - openedType = - openFunctionType(funcType, locator, replacements, innerDC, outerDC, - /*skipProtocolSelfConstraint=*/true, - /*skipGenericRequirements=*/true) - ->removeArgumentLabels(numRemovedArgumentLabels); + openedType = openFunctionType(funcType, locator, replacements, outerDC, + /*skipProtocolSelfConstraint=*/true, + /*skipGenericRequirements=*/true) + ->removeArgumentLabels(numRemovedArgumentLabels); if (!outerDC->getSelfProtocolDecl()) { // Class methods returning Self as well as constructors get the diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index af465b4b93dfe..24766e0e64545 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -2369,8 +2369,6 @@ class ConstraintSystem { /// \param replacements The mapping from opened types to the type /// variables to which they were opened. /// - /// \param innerDC The generic context from which the type originates. - /// /// \param outerDC The generic context containing the declaration. /// /// \param skipProtocolSelfConstraint Whether to skip the constraint on a @@ -2383,14 +2381,13 @@ class ConstraintSystem { FunctionType *openFunctionType(AnyFunctionType *funcType, ConstraintLocatorBuilder locator, OpenedTypeMap &replacements, - DeclContext *innerDC, DeclContext *outerDC, + DeclContext *outerDC, bool skipProtocolSelfConstraint, bool skipGenericRequirements = false); /// Open the generic parameter list and (if requested) its requirements, /// creating type variables for each of the type parameters. - void openGeneric(DeclContext *innerDC, - DeclContext *outerDC, + void openGeneric(DeclContext *outerDC, GenericSignature *signature, bool skipProtocolSelfConstraint, ConstraintLocatorBuilder locator, From a06abbb3b5f3b6cae3ec5dfefe883dbfb6993118 Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Wed, 5 Jun 2019 14:19:00 +0100 Subject: [PATCH 032/112] IRGen: Generate spare bit mask lazily in StructLayoutBuilder Wait until we know the full size of the SpareBitVector before we construct it from the spare bit masks of the individual elements in the struct. This process mirrors the way we construct the rest of the struct type. This should reduce the number of short-lived allocations required to build small struct types (especially after #25240). It also provides a convenient place to insert code to handle the construction of big-endian bit masks on when targeting big-endian machines, assuming we decide to go down that route. --- lib/IRGen/StructLayout.cpp | 38 ++++++++++++++++++++++++++++++++------ lib/IRGen/StructLayout.h | 7 ++----- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/lib/IRGen/StructLayout.cpp b/lib/IRGen/StructLayout.cpp index b3096bd0d5464..b01fd1266695f 100644 --- a/lib/IRGen/StructLayout.cpp +++ b/lib/IRGen/StructLayout.cpp @@ -78,7 +78,7 @@ StructLayout::StructLayout(IRGenModule &IGM, } else { MinimumAlign = builder.getAlignment(); MinimumSize = builder.getSize(); - SpareBits = std::move(builder.getSpareBits()); + SpareBits = builder.getSpareBits(); IsFixedLayout = builder.isFixedLayout(); IsKnownPOD = builder.isPOD(); IsKnownBitwiseTakable = builder.isBitwiseTakable(); @@ -263,9 +263,11 @@ void StructLayoutBuilder::addFixedSizeElement(ElementLayout &elt) { if (isFixedLayout()) { auto paddingTy = llvm::ArrayType::get(IGM.Int8Ty, paddingRequired); StructFields.push_back(paddingTy); - + // The padding can be used as spare bits by enum layout. - CurSpareBits.appendSetBits(Size(paddingRequired).getValueInBits()); + auto numBits = Size(paddingRequired).getValueInBits(); + auto mask = llvm::APInt::getAllOnesValue(numBits); + CurSpareBits.push_back(SpareBitVector::fromAPInt(mask)); } } @@ -318,7 +320,7 @@ void StructLayoutBuilder::addElementAtFixedOffset(ElementLayout &elt) { StructFields.push_back(elt.getType().getStorageType()); // Carry over the spare bits from the element. - CurSpareBits.append(eltTI.getSpareBits()); + CurSpareBits.push_back(eltTI.getSpareBits()); } /// Add an element at a non-fixed offset to the aggregate. @@ -326,7 +328,7 @@ void StructLayoutBuilder::addElementAtNonFixedOffset(ElementLayout &elt) { assert(!isFixedLayout()); elt.completeNonFixed(elt.getType().isPOD(ResilienceExpansion::Maximal), NextNonFixedOffsetIndex); - CurSpareBits.clear(); + CurSpareBits = SmallVector(); // clear spare bits } /// Add a non-fixed-size element to the aggregate at offset zero. @@ -335,7 +337,7 @@ void StructLayoutBuilder::addNonFixedSizeElementAtOffsetZero(ElementLayout &elt) assert(!isa(elt.getType())); assert(CurSize.isZero()); elt.completeInitialNonFixedSize(elt.getType().isPOD(ResilienceExpansion::Maximal)); - CurSpareBits.clear(); + CurSpareBits = SmallVector(); // clear spare bits } /// Produce the current fields as an anonymous structure. @@ -358,3 +360,27 @@ void StructLayoutBuilder::setAsBodyOfStruct(llvm::StructType *type) const { == CurSize.getValue()) && "LLVM size of fixed struct type does not match StructLayout size"); } + +/// Return the spare bit mask of the structure built so far. +SpareBitVector StructLayoutBuilder::getSpareBits() const { + // Calculate the size up front to reduce possible allocations. + unsigned numBits = 0; + for (auto &v : CurSpareBits) { + numBits += v.size(); + } + if (numBits == 0) { + return SpareBitVector(); + } + // Assemble the spare bit mask. + auto mask = llvm::APInt::getNullValue(numBits); + unsigned offset = 0; + for (auto &v : CurSpareBits) { + if (v.size() == 0) { + continue; + } + mask.insertBits(v.asAPInt(), offset); + offset += v.size(); + } + assert(offset == numBits); + return SpareBitVector::fromAPInt(std::move(mask)); +} diff --git a/lib/IRGen/StructLayout.h b/lib/IRGen/StructLayout.h index a4a00c74b61ad..1d3fc715d1610 100644 --- a/lib/IRGen/StructLayout.h +++ b/lib/IRGen/StructLayout.h @@ -239,7 +239,7 @@ class StructLayoutBuilder { Size CurSize = Size(0); private: Alignment CurAlignment = Alignment(1); - SpareBitVector CurSpareBits; + SmallVector CurSpareBits; unsigned NextNonFixedOffsetIndex = 0; bool IsFixedLayout = true; IsPOD_t IsKnownPOD = IsPOD; @@ -300,12 +300,9 @@ class StructLayoutBuilder { /// Return the alignment of the structure built so far. Alignment getAlignment() const { return CurAlignment; } - - /// Return the spare bit mask of the structure built so far. - const SpareBitVector &getSpareBits() const { return CurSpareBits; } /// Return the spare bit mask of the structure built so far. - SpareBitVector &getSpareBits() { return CurSpareBits; } + SpareBitVector getSpareBits() const; /// Build the current elements as a new anonymous struct type. llvm::StructType *getAsAnonStruct() const; From 8e0189181ecba8ecd051d8739aa9cbb0dcc3df35 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 5 Jun 2019 07:52:32 -0700 Subject: [PATCH 033/112] IRGen: Fix handling of singleton aggregate projections and tuple types Follow up to "IRGen: getSingletonAggregateFieldType must not return field if its access level does not match" rdar://50554717 --- lib/IRGen/GenType.cpp | 22 +++-------- test/IRGen/Inputs/metadata2.swift | 63 +++++++++++++++++++++++++++++++ test/IRGen/metadata.swift | 3 ++ 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp index 32415136c143b..232fb15e61343 100644 --- a/lib/IRGen/GenType.cpp +++ b/lib/IRGen/GenType.cpp @@ -2291,14 +2291,9 @@ SILType irgen::getSingletonAggregateFieldType(IRGenModule &IGM, SILType t, auto field = allFields.begin(); if (!allFields.empty() && std::next(field) == allFields.end()) { auto fieldTy = t.getFieldType(*field, IGM.getSILModule()); - if (auto fieldDecl = fieldTy.getNominalOrBoundGenericNominal()) { - // The field's access level must be higher or equal to the enclosing - // struct's. - if (fieldDecl->getEffectiveAccess() >= structDecl->getEffectiveAccess()) - return fieldTy; - } else { - return fieldTy; - } + if (!IGM.isTypeABIAccessible(fieldTy)) + return SILType(); + return fieldTy; } return SILType(); @@ -2316,14 +2311,9 @@ SILType irgen::getSingletonAggregateFieldType(IRGenModule &IGM, SILType t, if (!allCases.empty() && std::next(theCase) == allCases.end() && (*theCase)->hasAssociatedValues()) { auto enumEltTy = t.getEnumElementType(*theCase, IGM.getSILModule()); - if (auto eltDecl = enumEltTy.getNominalOrBoundGenericNominal()) { - // The enum element's access level must be higher or equal to the - // enclosing struct's. - if (eltDecl->getEffectiveAccess() >= enumDecl->getEffectiveAccess()) - return enumEltTy; - } else { - return enumEltTy; - } + if (!IGM.isTypeABIAccessible(enumEltTy)) + return SILType(); + return enumEltTy; } return SILType(); diff --git a/test/IRGen/Inputs/metadata2.swift b/test/IRGen/Inputs/metadata2.swift index 3d3ea8334bfca..723980f1f6e55 100644 --- a/test/IRGen/Inputs/metadata2.swift +++ b/test/IRGen/Inputs/metadata2.swift @@ -24,3 +24,66 @@ struct InternalContainer { self.type = SomeEnumType(item: item) } } + +struct InternalContainer2 { + + fileprivate enum SomeEnumType { + case none + case single(Item) + + init(item: [Item]) { + if item.count >= 1 { + self = .single(item.first!) + } else { + self = .none + } + } + } + + private var type: (SomeEnumType, SomeEnumType) + + init(item: [Item]) { + self.type = SomeEnumType(item: item) + } +} + +enum InternalSingletonEnum { + fileprivate enum SomeEnumType { + case none + case single(Item) + + init(item: [Item]) { + if item.count >= 1 { + self = .single(item.first!) + } else { + self = .none + } + } + } + case first(SomeEnumType) + + init() { + return .first(.none) + } +} + +enum InternalSingletonEnum2 { + fileprivate enum SomeEnumType { + case none + case single(Item) + + init(item: [Item]) { + if item.count >= 1 { + self = .single(item.first!) + } else { + self = .none + } + } + } + + case first(SomeEnumType, SomeEnumType) + + init() { + return .first(.none, .none) + } +} diff --git a/test/IRGen/metadata.swift b/test/IRGen/metadata.swift index 5afefb1abe9d5..6ebbb5e000690 100644 --- a/test/IRGen/metadata.swift +++ b/test/IRGen/metadata.swift @@ -8,6 +8,9 @@ // CHECK: ret class MyController { var c = InternalContainer(item: []) + var c2 = InternalContainer2(item: []) + var e = InternalSingletonEnum() + var e2 = InternalSingletonEnum2() func update(_ n: InternalContainer) { c = n } From c63114f12c8bd788f28a42fdca895ba82b156f6e Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 5 Jun 2019 09:03:11 -0700 Subject: [PATCH 034/112] stdlib: enable RuntimeUnittest on Windows No longer limit this to POSIX platforms. The threading has been generalised to support all targets. --- stdlib/private/RuntimeUnittest/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/private/RuntimeUnittest/CMakeLists.txt b/stdlib/private/RuntimeUnittest/CMakeLists.txt index 8085bf72281bf..5fa531676d5ff 100644 --- a/stdlib/private/RuntimeUnittest/CMakeLists.txt +++ b/stdlib/private/RuntimeUnittest/CMakeLists.txt @@ -12,8 +12,8 @@ add_swift_target_library(swiftRuntimeUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES SWIFT_MODULE_DEPENDS_FREEBSD Glibc SWIFT_MODULE_DEPENDS_CYGWIN Glibc SWIFT_MODULE_DEPENDS_HAIKU Glibc + SWIFT_MODULE_DEPENDS_WINDOWS MSVCRT SWIFT_COMPILE_FLAGS ${swift_stdlib_unittest_compile_flags} - TARGET_SDKS ALL_POSIX_PLATFORMS INSTALL_IN_COMPONENT stdlib-experimental DARWIN_INSTALL_NAME_DIR "${SWIFT_DARWIN_STDLIB_PRIVATE_INSTALL_NAME_DIR}") From 24d6a3c484d4c414124c967e70778f58f148a7d6 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 5 Jun 2019 10:32:39 -0700 Subject: [PATCH 035/112] [ConstraintSystem] Remove `skipGenericRequirements` flag from `openGeneric` --- lib/Sema/ConstraintSystem.cpp | 21 ++++++++++----------- lib/Sema/ConstraintSystem.h | 5 ++--- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 667849f953295..eb5e19ae23a66 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -636,13 +636,16 @@ FunctionType *ConstraintSystem::openFunctionType( DeclContext *outerDC, bool skipProtocolSelfConstraint, bool skipGenericRequirements) { - Type type; - if (auto *genericFn = funcType->getAs()) { - // Open up the generic parameters and requirements. - openGeneric(outerDC, genericFn->getGenericSignature(), - skipProtocolSelfConstraint, locator, replacements, - skipGenericRequirements); + auto *signature = genericFn->getGenericSignature(); + + openGenericParameters(outerDC, signature, replacements, locator); + + if (!skipGenericRequirements) { + openGenericRequirements( + outerDC, signature, skipProtocolSelfConstraint, locator, + [&](Type type) -> Type { return openType(type, replacements); }); + } // Transform the parameters and output type. llvm::SmallVector openedParams; @@ -1091,16 +1094,12 @@ void ConstraintSystem::openGeneric( GenericSignature *sig, bool skipProtocolSelfConstraint, ConstraintLocatorBuilder locator, - OpenedTypeMap &replacements, - bool skipGenericRequirements) { + OpenedTypeMap &replacements) { if (sig == nullptr) return; openGenericParameters(outerDC, sig, replacements, locator); - if (skipGenericRequirements) - return; - // Add the requirements as constraints. openGenericRequirements( outerDC, sig, skipProtocolSelfConstraint, locator, diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 24766e0e64545..bf15ff05ac6af 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -2385,14 +2385,13 @@ class ConstraintSystem { bool skipProtocolSelfConstraint, bool skipGenericRequirements = false); - /// Open the generic parameter list and (if requested) its requirements, + /// Open the generic parameter list and its requirements, /// creating type variables for each of the type parameters. void openGeneric(DeclContext *outerDC, GenericSignature *signature, bool skipProtocolSelfConstraint, ConstraintLocatorBuilder locator, - OpenedTypeMap &replacements, - bool skipGenericRequirements = false); + OpenedTypeMap &replacements); /// Open the generic parameter list creating type variables for each of the /// type parameters. From 0da4a5b2b363dc939e3fac494a7222d1ebd70a4a Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 5 Jun 2019 10:34:22 -0700 Subject: [PATCH 036/112] [CSRanking] Remove code duplication related to opening types --- lib/Sema/CSRanking.cpp | 50 +++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp index aa8884ef9037b..41ebb81b970ab 100644 --- a/lib/Sema/CSRanking.cpp +++ b/lib/Sema/CSRanking.cpp @@ -506,41 +506,35 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc, checkKind = CheckAll; } + auto openType = [&](ConstraintSystem &cs, DeclContext *innerDC, + DeclContext *outerDC, Type type, + OpenedTypeMap &replacements, + ConstraintLocator *locator) -> Type { + if (auto *funcType = type->getAs()) { + return cs.openFunctionType(funcType, locator, replacements, outerDC, + /*skipProtocolSelfConstraint=*/false); + } + + cs.openGeneric(outerDC, innerDC->getGenericSignatureOfContext(), + /*skipProtocolSelfConstraint=*/false, locator, + replacements); + + return cs.openType(type, replacements); + }; + // Construct a constraint system to compare the two declarations. ConstraintSystem cs(tc, dc, ConstraintSystemOptions()); bool knownNonSubtype = false; - auto locator = cs.getConstraintLocator(nullptr); + auto *locator = cs.getConstraintLocator(nullptr); // FIXME: Locator when anchored on a declaration. // Get the type of a reference to the second declaration. - OpenedTypeMap unused; - Type openedType2; - if (auto *funcType = type2->getAs()) { - openedType2 = cs.openFunctionType(funcType, locator, - /*replacements=*/unused, outerDC2, - /*skipProtocolSelfConstraint=*/false); - } else { - cs.openGeneric(outerDC2, innerDC2->getGenericSignatureOfContext(), - /*skipProtocolSelfConstraint=*/false, locator, unused); - openedType2 = cs.openType(type2, unused); - } - - // Get the type of a reference to the first declaration, swapping in - // archetypes for the dependent types. - OpenedTypeMap replacements; - Type openedType1; - if (auto *funcType = type1->getAs()) { - openedType1 = - cs.openFunctionType(funcType, locator, replacements, outerDC1, - /*skipProtocolSelfConstraint=*/false); - } else { - cs.openGeneric(outerDC1, innerDC1->getGenericSignatureOfContext(), - /*skipProtocolSelfConstraint=*/false, locator, - replacements); - - openedType1 = cs.openType(type1, replacements); - } + OpenedTypeMap unused, replacements; + auto openedType2 = + openType(cs, innerDC1, outerDC2, type2, unused, locator); + auto openedType1 = + openType(cs, innerDC2, outerDC1, type1, replacements, locator); for (const auto &replacement : replacements) { if (auto mapped = innerDC1->mapTypeIntoContext(replacement.first)) { From 569c8afc54926ab67216682fb6e546aebb46de1a Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Wed, 5 Jun 2019 10:38:10 -0700 Subject: [PATCH 037/112] [Profiler] Separate profiler instances for property inits and constructors (#25247) Assign separate SILProfiler instances to stored property initializers and constructors. Starting with rdar://39460313, coverage reporting for these constructs was bundled up into a single SILProfiler uniqued by the NominalTypeDecl. There are two problems with doing this. First, the shared SILProfiler is given a fake name that can't be demangled. That breaks Xcode's reports. Second, the relationship between SILProfiler and SILFunction is supposed to be 1:1. Having a shared SILProfiler muddies things a bit and requires extra bookkeeping. rdar://47467864 --- include/swift/SIL/SILFunction.h | 4 +- include/swift/SIL/SILProfiler.h | 10 +- lib/SIL/SILFunction.cpp | 5 +- lib/SIL/SILProfiler.cpp | 191 ++++++++++------------ lib/SILGen/SILGen.cpp | 53 ++---- lib/SILGen/SILGen.h | 11 -- lib/SILGen/SILGenFunction.cpp | 5 +- lib/SILGen/SILGenFunction.h | 5 +- test/Profiler/coverage_class.swift | 32 ++-- test/Profiler/coverage_closures.swift | 5 +- test/Profiler/coverage_exceptions.swift | 22 +-- test/Profiler/coverage_primary_file.swift | 2 +- test/Profiler/coverage_smoke.swift | 6 +- test/Profiler/coverage_ternary.swift | 27 ++- 14 files changed, 171 insertions(+), 207 deletions(-) diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h index 179743b8da935..08d8f13dc9101 100644 --- a/include/swift/SIL/SILFunction.h +++ b/include/swift/SIL/SILFunction.h @@ -22,6 +22,7 @@ #include "swift/Basic/ProfileCounter.h" #include "swift/SIL/SILBasicBlock.h" #include "swift/SIL/SILDebugScope.h" +#include "swift/SIL/SILDeclRef.h" #include "swift/SIL/SILLinkage.h" #include "swift/SIL/SILPrintContext.h" #include "llvm/ADT/StringMap.h" @@ -362,7 +363,8 @@ class SILFunction Profiler = InheritedProfiler; } - void createProfiler(ASTNode Root, ForDefinition_t forDefinition); + void createProfiler(ASTNode Root, SILDeclRef forDecl, + ForDefinition_t forDefinition); void discardProfiler() { Profiler = nullptr; } diff --git a/include/swift/SIL/SILProfiler.h b/include/swift/SIL/SILProfiler.h index c7cfb3b595860..caa5de30d3f5a 100644 --- a/include/swift/SIL/SILProfiler.h +++ b/include/swift/SIL/SILProfiler.h @@ -41,6 +41,8 @@ class SILProfiler : public SILAllocated { ASTNode Root; + SILDeclRef forDecl; + bool EmitCoverageMapping; SILCoverageMap *CovMap = nullptr; @@ -61,12 +63,14 @@ class SILProfiler : public SILAllocated { std::vector> CoverageData; - SILProfiler(SILModule &M, ASTNode Root, bool EmitCoverageMapping) - : M(M), Root(Root), EmitCoverageMapping(EmitCoverageMapping) {} + SILProfiler(SILModule &M, ASTNode Root, SILDeclRef forDecl, + bool EmitCoverageMapping) + : M(M), Root(Root), forDecl(forDecl), + EmitCoverageMapping(EmitCoverageMapping) {} public: static SILProfiler *create(SILModule &M, ForDefinition_t forDefinition, - ASTNode N); + ASTNode N, SILDeclRef forDecl); /// Check if the function is set up for profiling. bool hasRegionCounters() const { return NumRegionCounters != 0; } diff --git a/lib/SIL/SILFunction.cpp b/lib/SIL/SILFunction.cpp index b93ebf3d853f8..c8e0716e24c52 100644 --- a/lib/SIL/SILFunction.cpp +++ b/lib/SIL/SILFunction.cpp @@ -151,9 +151,10 @@ SILFunction::~SILFunction() { "Function cannot be deleted while function_ref's still exist"); } -void SILFunction::createProfiler(ASTNode Root, ForDefinition_t forDefinition) { +void SILFunction::createProfiler(ASTNode Root, SILDeclRef forDecl, + ForDefinition_t forDefinition) { assert(!Profiler && "Function already has a profiler"); - Profiler = SILProfiler::create(Module, forDefinition, Root); + Profiler = SILProfiler::create(Module, forDefinition, Root, forDecl); } bool SILFunction::hasForeignBody() const { diff --git a/lib/SIL/SILProfiler.cpp b/lib/SIL/SILProfiler.cpp index 7631898979038..302403872cb67 100644 --- a/lib/SIL/SILProfiler.cpp +++ b/lib/SIL/SILProfiler.cpp @@ -43,32 +43,43 @@ static bool doesClosureHaveBody(AbstractClosureExpr *ACE) { /// Check whether a root AST node is unmapped, i.e not profiled. static bool isUnmapped(ASTNode N) { // Do not map AST nodes with invalid source locations. - if (N.getStartLoc().isInvalid() || N.getEndLoc().isInvalid()) + if (N.getStartLoc().isInvalid() || N.getEndLoc().isInvalid()) { + LLVM_DEBUG(llvm::dbgs() + << "Skipping ASTNode: invalid start/end locations\n"); return true; + } if (auto *E = N.dyn_cast()) { - auto *CE = dyn_cast(E); - - // Only map closure expressions with bodies. - if (!CE || !doesClosureHaveBody(CE)) + if (isa(E)) { + LLVM_DEBUG(llvm::dbgs() << "Skipping ASTNode: literal expr\n"); return true; + } - // Don't map implicit closures, unless they're autoclosures. - if (!isa(CE) && CE->isImplicit()) - return true; + if (auto *CE = dyn_cast(E)) { + // Only map closure expressions with bodies. + if (!doesClosureHaveBody(CE)) { + LLVM_DEBUG(llvm::dbgs() << "Skipping ASTNode: closure without body\n"); + return true; + } + // Don't map implicit closures, unless they're autoclosures. + if (!isa(CE) && CE->isImplicit()) { + LLVM_DEBUG(llvm::dbgs() << "Skipping ASTNode: implicit closure expr\n"); + return true; + } + } + + // Map all other kinds of expressions. return false; } auto *D = N.get(); if (auto *AFD = dyn_cast(D)) { // Don't map functions without bodies. - if (!AFD->getBody()) + if (!AFD->getBody()) { + LLVM_DEBUG(llvm::dbgs() << "Skipping ASTNode: function without body\n"); return true; - - // Map all *structors, even if they are implicit. - if (isa(D) || isa(D)) - return false; + } // Map implicit getters. if (auto *accessor = dyn_cast(AFD)) @@ -77,8 +88,10 @@ static bool isUnmapped(ASTNode N) { } // Skip any remaining implicit, or otherwise unsupported decls. - if (D->isImplicit() || isa(D)) + if (D->isImplicit() || isa(D)) { + LLVM_DEBUG(llvm::dbgs() << "Skipping ASTNode: implicit/unsupported decl\n"); return true; + } return false; } @@ -89,18 +102,29 @@ bool doesASTRequireProfiling(SILModule &M, ASTNode N) { } } // namespace swift +/// Get the DeclContext for the decl referenced by \p forDecl. +DeclContext *getProfilerContextForDecl(ASTNode N, SILDeclRef forDecl) { + if (auto *D = N.dyn_cast()) + if (auto *TLCD = dyn_cast(D)) + return TLCD; + assert(!forDecl.isNull() && "Expected a nonnull SILDeclRef"); + if (auto *ACE = forDecl.getAbstractClosureExpr()) + return ACE; + return forDecl.getDecl()->getDeclContext(); +} + /// Check that the input AST has at least been type-checked. LLVM_ATTRIBUTE_UNUSED -static bool hasASTBeenTypeChecked(ASTNode N) { - DeclContext *DC = N.getAsDeclContext(); - assert(DC && "Invalid AST node for profiling"); +static bool hasASTBeenTypeChecked(ASTNode N, SILDeclRef forDecl) { + DeclContext *DC = getProfilerContextForDecl(N, forDecl); SourceFile *SF = DC->getParentSourceFile(); return !SF || SF->ASTStage >= SourceFile::TypeChecked; } /// Check whether a mapped AST node requires a new profiler. -static bool canCreateProfilerForAST(ASTNode N) { - assert(hasASTBeenTypeChecked(N) && "Cannot use this AST for profiling"); +static bool canCreateProfilerForAST(ASTNode N, SILDeclRef forDecl) { + assert(hasASTBeenTypeChecked(N, forDecl) && + "Cannot use this AST for profiling"); if (auto *D = N.dyn_cast()) { if (isa(D)) @@ -108,19 +132,16 @@ static bool canCreateProfilerForAST(ASTNode N) { if (isa(D)) return true; - - if (isa(D)) - return true; - } else { - auto *E = N.get(); - if (isa(E)) + } else if (auto *E = N.get()) { + if (forDecl.isStoredPropertyInitializer() || + forDecl.getAbstractClosureExpr()) return true; } return false; } SILProfiler *SILProfiler::create(SILModule &M, ForDefinition_t forDefinition, - ASTNode N) { + ASTNode N, SILDeclRef forDecl) { // Avoid generating profiling state for declarations. if (!forDefinition) return nullptr; @@ -129,11 +150,12 @@ SILProfiler *SILProfiler::create(SILModule &M, ForDefinition_t forDefinition, if (!doesASTRequireProfiling(M, N) && Opts.UseProfile.empty()) return nullptr; - if (!canCreateProfilerForAST(N)) + if (!canCreateProfilerForAST(N, forDecl)) llvm_unreachable("Invalid AST node for profiling"); auto *Buf = M.allocate(1); - auto *SP = ::new (Buf) SILProfiler(M, N, Opts.EmitProfileCoverageMapping); + auto *SP = + ::new (Buf) SILProfiler(M, N, forDecl, Opts.EmitProfileCoverageMapping); SP->assignRegionCounters(); return SP; } @@ -149,42 +171,14 @@ static void walkPatternForProfiling(PatternBindingDecl *PBD, init->walk(Walker); } -/// Special logic for handling closure visitation. -/// -/// To prevent a closure from being mapped twice, avoid recursively walking -/// into one unless the closure's function definition is being profiled. -/// -/// Apply \p Func if the closure can be visited. -template -std::pair visitClosureExpr(ASTWalker &Walker, - AbstractClosureExpr *CE, F Func) { - if (!Walker.Parent.isNull()) - return {false, CE}; - Func(); - return {true, CE}; -} - /// Special logic for handling function visitation. /// /// To avoid creating duplicate mappings, a function decl is only profiled if -/// it hasn't been reached via recursive walk, or if it's a constructor for a -/// nominal type (these are profiled in a group). +/// it hasn't been reached via recursive walk. /// -/// Apply \p Func is the function can be visited. +/// Apply \p Func if the function can be visited. template bool visitFunctionDecl(ASTWalker &Walker, AbstractFunctionDecl *AFD, F Func) { - bool continueWalk = Walker.Parent.isNull() || isa(AFD); - if (continueWalk) - Func(); - return continueWalk; -} - -/// Special logic for handling nominal type visitation. -/// -/// Apply \p Func if the nominal type can be visited (i.e it has not been -/// reached via recursive walk). -template -bool visitNominalTypeDecl(ASTWalker &Walker, NominalTypeDecl *NTD, F Func) { bool continueWalk = Walker.Parent.isNull(); if (continueWalk) Func(); @@ -199,9 +193,6 @@ struct MapRegionCounters : public ASTWalker { /// The map of statements to counters. llvm::DenseMap &CounterMap; - /// A flag indicating whether we're walking a nominal type. - bool WithinNominalType = false; - MapRegionCounters(llvm::DenseMap &CounterMap) : CounterMap(CounterMap) {} @@ -229,9 +220,6 @@ struct MapRegionCounters : public ASTWalker { return visitFunctionDecl(*this, AFD, [&] { mapRegion(AFD->getBody()); }); } else if (auto *TLCD = dyn_cast(D)) { mapRegion(TLCD->getBody()); - } else if (auto *NTD = dyn_cast(D)) { - return visitNominalTypeDecl(*this, NTD, - [&] { WithinNominalType = true; }); } return true; } @@ -259,10 +247,15 @@ struct MapRegionCounters : public ASTWalker { } std::pair walkToExprPre(Expr *E) override { + // If AST visitation begins with an expression, the counter map must be + // empty. Set up a counter for the root. + if (Parent.isNull()) { + assert(CounterMap.empty() && "Mapped a region before visiting the root?"); + mapRegion(E); + } + if (auto *IE = dyn_cast(E)) { mapRegion(IE->getThenExpr()); - } else if (auto *ACE = dyn_cast(E)) { - return visitClosureExpr(*this, ACE, [&] { mapRegion(ACE); }); } // rdar://42792053 @@ -507,9 +500,6 @@ struct PGOMapping : public ASTWalker { auto count = loadExecutionCount(node); LoadedCounterMap[node] = count; } - if (auto *NTD = dyn_cast(D)) { - return visitNominalTypeDecl(*this, NTD, [&] {}); - } return true; } @@ -594,6 +584,13 @@ struct PGOMapping : public ASTWalker { std::pair walkToExprPre(Expr *E) override { unsigned parent = getParentCounter(); + + if (Parent.isNull()) { + CounterMap[E] = NextCounter++; + auto eCount = loadExecutionCount(E); + LoadedCounterMap[E] = eCount; + } + if (auto *IE = dyn_cast(E)) { auto thenExpr = IE->getThenExpr(); CounterMap[thenExpr] = NextCounter++; @@ -614,12 +611,6 @@ struct PGOMapping : public ASTWalker { } } LoadedCounterMap[elseExpr] = subtract(count, thenCount); - } else if (auto *ACE = dyn_cast(E)) { - return visitClosureExpr(*this, ACE, [&] { - CounterMap[E] = NextCounter++; - auto eCount = loadExecutionCount(E); - LoadedCounterMap[E] = eCount; - }); } return {true, E}; } @@ -651,8 +642,6 @@ struct CoverageMapping : public ASTWalker { Stmt *ImplicitTopLevelBody = nullptr; - NominalTypeDecl *ParentNominalType = nullptr; - /// Return true if \c Node has an associated counter. bool hasCounter(ASTNode Node) { return CounterMap.count(Node); } @@ -856,20 +845,11 @@ struct CoverageMapping : public ASTWalker { if (auto *AFD = dyn_cast(D)) { return visitFunctionDecl(*this, AFD, [&] { - CounterExpr &funcCounter = assignCounter(AFD->getBody()); - - if (ParentNominalType && isa(AFD)) - addToCounter(ParentNominalType, funcCounter); + assignCounter(AFD->getBody()); }); } else if (auto *TLCD = dyn_cast(D)) { assignCounter(TLCD->getBody()); ImplicitTopLevelBody = TLCD->getBody(); - } else if (auto *NTD = dyn_cast(D)) { - return visitNominalTypeDecl(*this, NTD, [&] { - ParentNominalType = NTD; - assignCounter(NTD, CounterExpr::Zero()); - pushRegion(NTD); - }); } return true; } @@ -1030,17 +1010,22 @@ struct CoverageMapping : public ASTWalker { if (!RegionStack.empty()) extendRegion(E); - if (auto *ACE = dyn_cast(E)) { - auto Result = visitClosureExpr(*this, ACE, [&] { assignCounter(ACE); }); - if (!Result.first) - return Result; - } else if (auto *IE = dyn_cast(E)) { + // If AST visitation begins with an expression, the region stack must be + // empty. Set up a region for the root. + if (Parent.isNull()) { + assert(RegionStack.empty() && + "Mapped a region before visiting the root?"); + assignCounter(E); + pushRegion(E); + } + + if (auto *IE = dyn_cast(E)) { CounterExpr &ThenCounter = assignCounter(IE->getThenExpr()); assignCounter(IE->getElseExpr(), CounterExpr::Sub(getCurrentCounter(), ThenCounter)); } - if (hasCounter(E)) + if (hasCounter(E) && !Parent.isNull()) pushRegion(E); return {true, E}; } @@ -1070,8 +1055,8 @@ getEquivalentPGOLinkage(FormalLinkage Linkage) { llvm_unreachable("Unhandled FormalLinkage in switch."); } -static StringRef getCurrentFileName(ASTNode Root) { - DeclContext *Ctx = Root.getAsDeclContext(); +static StringRef getCurrentFileName(ASTNode N, SILDeclRef forDecl) { + DeclContext *Ctx = getProfilerContextForDecl(N, forDecl); if (auto *ParentFile = Ctx->getParentSourceFile()) return ParentFile->getFilename(); return {}; @@ -1080,7 +1065,7 @@ static StringRef getCurrentFileName(ASTNode Root) { void SILProfiler::assignRegionCounters() { const auto &SM = M.getASTContext().SourceMgr; - CurrentFileName = getCurrentFileName(Root); + CurrentFileName = getCurrentFileName(Root, forDecl); MapRegionCounters Mapper(RegionCounterMap); @@ -1088,23 +1073,17 @@ void SILProfiler::assignRegionCounters() { FormalLinkage CurrentFuncLinkage; if (auto *D = Root.dyn_cast()) { if (auto *AFD = dyn_cast(D)) { - CurrentFuncName = SILDeclRef(AFD).mangle(); + CurrentFuncName = forDecl.mangle(); CurrentFuncLinkage = getDeclLinkage(AFD); - } else if (auto *TLCD = dyn_cast(D)) { + } else { + auto *TLCD = cast(D); llvm::raw_string_ostream OS{CurrentFuncName}; OS << "__tlcd_"; TLCD->getStartLoc().printLineAndColumn(OS, SM); CurrentFuncLinkage = FormalLinkage::HiddenUnique; - } else { - auto *NTD = cast(D); - llvm::raw_string_ostream OS{CurrentFuncName}; - OS << "__ntd_" << NTD->getNameStr() << "_"; - NTD->getStartLoc().printLineAndColumn(OS, SM); - CurrentFuncLinkage = FormalLinkage::HiddenUnique; } } else { - auto *CE = cast(Root.get()); - CurrentFuncName = SILDeclRef(CE).mangle(); + CurrentFuncName = forDecl.mangle(); CurrentFuncLinkage = FormalLinkage::HiddenUnique; } diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index c4a6ed614ee86..9124cef26c78b 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -573,29 +573,6 @@ static bool haveProfiledAssociatedFunction(SILDeclRef constant) { constant.isCurried; } -SILProfiler * -SILGenModule::getOrCreateProfilerForConstructors(DeclContext *ctx, - ConstructorDecl *cd) { - const auto &Opts = M.getOptions(); - if (!Opts.GenerateProfile && Opts.UseProfile.empty()) - return nullptr; - - // Profile nominal types and extensions separately, as they may live in - // distinct files. For extensions, just pass in the constructor, because - // there are no stored property initializers to visit. - Decl *decl = nullptr; - if (isa(ctx)) - decl = cd; - else - decl = ctx->getSelfNominalTypeDecl(); - assert(decl && "No decl available for profiling in this context"); - - SILProfiler *&profiler = constructorProfilers[decl]; - if (!profiler) - profiler = SILProfiler::create(M, ForDefinition, decl); - return profiler; -} - /// Set up the function for profiling instrumentation. static void setUpForProfiling(SILDeclRef constant, SILFunction *F, ForDefinition_t forDefinition) { @@ -607,12 +584,12 @@ static void setUpForProfiling(SILDeclRef constant, SILFunction *F, if (constant.hasDecl()) { if (auto *fd = constant.getFuncDecl()) { if (fd->hasBody()) { - F->createProfiler(fd, forDefinition); + F->createProfiler(fd, constant, forDefinition); profiledNode = fd->getBody(/*canSynthesize=*/false); } } } else if (auto *ace = constant.getAbstractClosureExpr()) { - F->createProfiler(ace, forDefinition); + F->createProfiler(ace, constant, forDefinition); profiledNode = ace; } // Set the function entry count for PGO. @@ -915,12 +892,11 @@ void SILGenModule::emitConstructor(ConstructorDecl *decl) { SILDeclRef initConstant(decl, SILDeclRef::Kind::Initializer); emitOrDelayFunction( *this, initConstant, - [this, initConstant, decl, declCtx](SILFunction *initF) { + [this, initConstant, decl](SILFunction *initF) { preEmitFunction(initConstant, decl, initF, decl); PrettyStackTraceSILFunction X("silgen constructor initializer", initF); - initF->setProfiler( - getOrCreateProfilerForConstructors(declCtx, decl)); + initF->createProfiler(decl, initConstant, ForDefinition); SILGenFunction(*this, *initF, decl) .emitClassConstructorInitializer(decl); postEmitFunction(initConstant, initF); @@ -935,10 +911,10 @@ void SILGenModule::emitConstructor(ConstructorDecl *decl) { // non-@objc convenience initializers for classes. if (decl->hasBody()) { emitOrDelayFunction( - *this, constant, [this, constant, decl, declCtx](SILFunction *f) { + *this, constant, [this, constant, decl](SILFunction *f) { preEmitFunction(constant, decl, f, decl); PrettyStackTraceSILFunction X("silgen emitConstructor", f); - f->setProfiler(getOrCreateProfilerForConstructors(declCtx, decl)); + f->createProfiler(decl, constant, ForDefinition); SILGenFunction(*this, *f, decl).emitValueConstructor(decl); postEmitFunction(constant, f); }); @@ -1026,7 +1002,7 @@ void SILGenModule::emitObjCAllocatorDestructor(ClassDecl *cd, SILFunction *f = getFunction(dealloc, ForDefinition); preEmitFunction(dealloc, dd, f, dd); PrettyStackTraceSILFunction X("silgen emitDestructor -dealloc", f); - f->createProfiler(dd, ForDefinition); + f->createProfiler(dd, dealloc, ForDefinition); SILGenFunction(*this, *f, dd).emitObjCDestructor(dealloc); postEmitFunction(dealloc, f); } @@ -1096,7 +1072,7 @@ void SILGenModule::emitDestructor(ClassDecl *cd, DestructorDecl *dd) { SILFunction *f = getFunction(deallocator, ForDefinition); preEmitFunction(deallocator, dd, f, dd); PrettyStackTraceSILFunction X("silgen emitDeallocatingDestructor", f); - f->createProfiler(dd, ForDefinition); + f->createProfiler(dd, deallocator, ForDefinition); SILGenFunction(*this, *f, dd).emitDeallocatingDestructor(dd); f->setDebugScope(new (M) SILDebugScope(dd, f)); postEmitFunction(deallocator, f); @@ -1169,15 +1145,12 @@ emitStoredPropertyInitialization(PatternBindingDecl *pbd, unsigned i) { SILDeclRef constant(var, SILDeclRef::Kind::StoredPropertyInitializer); emitOrDelayFunction(*this, constant, - [this,constant,init,initDC,var](SILFunction *f) { + [this,constant,init,initDC](SILFunction *f) { preEmitFunction(constant, init, f, init); PrettyStackTraceSILFunction X("silgen emitStoredPropertyInitialization", f); - - // Inherit a profiler instance from the constructor. - f->setProfiler( - getOrCreateProfilerForConstructors(var->getDeclContext(), nullptr)); - - SILGenFunction(*this, *f, initDC).emitGeneratorFunction(constant, init); + f->createProfiler(init, constant, ForDefinition); + SILGenFunction(*this, *f, initDC) + .emitGeneratorFunction(constant, init, /*EmitProfilerIncrement=*/true); postEmitFunction(constant, f); }); } @@ -1530,7 +1503,7 @@ void SILGenModule::visitTopLevelCodeDecl(TopLevelCodeDecl *td) { // A single SILFunction may be used to lower multiple top-level decls. When // this happens, fresh profile counters must be assigned to the new decl. TopLevelSGF->F.discardProfiler(); - TopLevelSGF->F.createProfiler(td, ForDefinition); + TopLevelSGF->F.createProfiler(td, SILDeclRef(), ForDefinition); TopLevelSGF->emitProfilerIncrement(td->getBody()); diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h index 6c40317869a5c..3f03f59136d3a 100644 --- a/lib/SILGen/SILGen.h +++ b/lib/SILGen/SILGen.h @@ -88,11 +88,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor { /// Set of delayed conformances that have already been forced. llvm::DenseSet forcedConformances; - /// Profiler instances for constructors, grouped by associated decl. - /// Each profiler is shared by all member initializers for a nominal type. - /// Constructors within extensions are profiled separately. - llvm::DenseMap constructorProfilers; - SILFunction *emitTopLevelFunction(SILLocation Loc); size_t anonymousSymbolCounter = 0; @@ -455,12 +450,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor { /// Emit a property descriptor for the given storage decl if it needs one. void tryEmitPropertyDescriptor(AbstractStorageDecl *decl); - /// Get or create the shared profiler instance for a type's constructors. - /// This takes care to create separate profilers for extensions, which may - /// reside in a different file than the one where the base type is defined. - SILProfiler *getOrCreateProfilerForConstructors(DeclContext *ctx, - ConstructorDecl *cd); - private: /// Emit the deallocator for a class that uses the objc allocator. void emitObjCAllocatorDestructor(ClassDecl *cd, DestructorDecl *dd); diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index ef35b17e57c3b..e499512626f51 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -612,7 +612,8 @@ void SILGenFunction::emitArtificialTopLevel(ClassDecl *mainClass) { } } -void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value) { +void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value, + bool EmitProfilerIncrement) { MagicFunctionName = SILGenModule::getMagicFunctionName(function); RegularLocation Loc(value); @@ -635,6 +636,8 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value) { auto interfaceType = value->getType()->mapTypeOutOfContext(); emitProlog(/*paramList=*/nullptr, /*selfParam=*/nullptr, interfaceType, dc, false); + if (EmitProfilerIncrement) + emitProfilerIncrement(value); prepareEpilog(value->getType(), false, CleanupLocation::get(Loc)); emitReturnExpr(Loc, value); emitEpilog(Loc); diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h index 8aa121780c703..831254e9e0683 100644 --- a/lib/SILGen/SILGenFunction.h +++ b/lib/SILGen/SILGenFunction.h @@ -627,7 +627,10 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction void emitNativeToForeignThunk(SILDeclRef thunk); /// Generate a nullary function that returns the given value. - void emitGeneratorFunction(SILDeclRef function, Expr *value); + /// If \p emitProfilerIncrement is set, emit a profiler increment for + /// \p value. + void emitGeneratorFunction(SILDeclRef function, Expr *value, + bool emitProfilerIncrement = false); /// Generate a nullary function that returns the value of the given variable's /// expression initializer. diff --git a/test/Profiler/coverage_class.swift b/test/Profiler/coverage_class.swift index 3ca3e8e46c09c..3c4188978474a 100644 --- a/test/Profiler/coverage_class.swift +++ b/test/Profiler/coverage_class.swift @@ -1,32 +1,43 @@ // RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sil -module-name coverage_class %s | %FileCheck %s class C { - // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.C.foo + // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.C.foo() -> () + // CHECK-NEXT: [[@LINE+1]]:14 -> [[@LINE+1]]:16 : 0 func foo() {} - // CHECK: sil_coverage_map {{.*}}// __ntd_C_line:[[@LINE-3]]:1 + + // CHECK: sil_coverage_map {{.*}}// coverage_class.C.init() -> coverage_class.C // CHECK-NEXT: [[@LINE+1]]:10 -> [[@LINE+1]]:12 init() {} + // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.C.__deallocating_deinit + // CHECK-NEXT: [[@LINE+1]]:10 -> [[@LINE+1]]:12 deinit {} } extension C { - // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.C.bar + // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.C.bar() -> () + // CHECK-NEXT: [[@LINE+1]]:14 -> [[@LINE+1]]:16 : 0 func bar() {} } struct S { - // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.S.foo + // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.S.foo() -> () + // CHECK-NEXT: [[@LINE+1]]:14 -> [[@LINE+1]]:16 : 0 func foo() {} - // CHECK: sil_coverage_map {{.*}}// __ntd_S_line:[[@LINE-3]]:1 + + // CHECK: sil_coverage_map {{.*}}// coverage_class.S.init() -> coverage_class.S + // CHECK-NEXT: [[@LINE+1]]:10 -> [[@LINE+1]]:12 init() {} } enum E { case X, Y, Z - // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.E.foo + + // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.E.foo() -> () + // CHECK-NEXT: [[@LINE+1]]:14 -> [[@LINE+1]]:16 : 0 func foo() {} - // CHECK: sil_coverage_map {{.*}}// __ntd_E_line:[[@LINE-4]]:1 + + // CHECK: sil_coverage_map {{.*}}// coverage_class.E.init() -> coverage_class.E // CHECK-NEXT: [[@LINE+1]]:10 -> [[@LINE+1]]:23 init() { self = .Y } } @@ -34,9 +45,10 @@ enum E { var g1: Bool = true struct S2 { - // CHECK: sil_coverage_map {{.*}}// __ntd_S2_line:[[@LINE-1]]:1 - // CHECK-NEXT: [[@LINE+2]]:22 -> [[@LINE+2]]:23 : 0 - // CHECK-NEXT: [[@LINE+1]]:26 -> [[@LINE+1]]:27 : (1 - 0) + // CHECK: sil_coverage_map {{.*}}// variable initialization expression of coverage_class.S2.m1 : Swift.Int + // CHECK-NEXT: [[@LINE+3]]:22 -> [[@LINE+3]]:23 : 1 + // CHECK-NEXT: [[@LINE+2]]:26 -> [[@LINE+2]]:27 : (0 - 1) + // CHECK-NEXT: [[@LINE+1]]:17 -> [[@LINE+1]]:27 : 0 var m1: Int = g1 ? 0 : 1 } diff --git a/test/Profiler/coverage_closures.swift b/test/Profiler/coverage_closures.swift index 4f7b893a244eb..2136f7432a34c 100644 --- a/test/Profiler/coverage_closures.swift +++ b/test/Profiler/coverage_closures.swift @@ -34,9 +34,10 @@ func foo() { f1 { left, right in left == 0 || right == 1 } } -// SR-2615: Implicit constructor decl has no body, and shouldn't be mapped +// SR-2615: Display coverage for implicit member initializers without crashing struct C1 { -// CHECK-NOT: sil_coverage_map{{.*}}errors + // CHECK-LABEL: sil_coverage_map{{.*}}// variable initialization expression of coverage_closures.C1 + // CHECK-NEXT: [[@LINE+1]]:24 -> [[@LINE+1]]:34 : 0 private var errors = [String]() } diff --git a/test/Profiler/coverage_exceptions.swift b/test/Profiler/coverage_exceptions.swift index b697e8a10c76e..b48ea05c8d8b3 100644 --- a/test/Profiler/coverage_exceptions.swift +++ b/test/Profiler/coverage_exceptions.swift @@ -1,5 +1,16 @@ // RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_catch %s | %FileCheck %s +struct S { + // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_catch.S.init() -> coverage_catch.S + init() { // CHECK: [[@LINE]]:10 -> [[@LINE+6]]:4 : 0 + do { // CHECK: [[@LINE]]:8 -> [[@LINE+2]]:6 : 0 + throw SomeErr.Err1 + } catch { + // CHECK: [[@LINE-1]]:13 -> [[@LINE+1]]:6 : 1 + } // CHECK: [[@LINE]]:6 -> [[@LINE+1]]:4 : 0 + } +} + enum SomeErr : Error { case Err1 case Err2 @@ -109,14 +120,3 @@ func joo() -> Int { } while false // CHECK: [[@LINE]]:11 {{.*}} : (1 - 2) return 1 } - -struct S { - // CHECK: sil_coverage_map {{.*}}// __ntd_S_line:[[@LINE-1]] - init() { - do { - throw SomeErr.Err1 - } catch { - // CHECK: [[@LINE-1]]:13 -> [[@LINE+1]]:6 : 1 - } // CHECK: [[@LINE]]:6 -> [[@LINE+1]]:4 : 0 - } -} diff --git a/test/Profiler/coverage_primary_file.swift b/test/Profiler/coverage_primary_file.swift index 03b3faf1ae0f8..deafa2ec82c40 100644 --- a/test/Profiler/coverage_primary_file.swift +++ b/test/Profiler/coverage_primary_file.swift @@ -4,8 +4,8 @@ // ALL: sil_coverage_map {{.*}} // closure #1 () -> Swift.Int in coverage_primary_file.Box.x.getter : Swift.Int // ALL: sil_coverage_map {{.*}} // coverage_primary_file.Box.init(y: Swift.Int) -> coverage_primary_file.Box // ALL: sil_coverage_map {{.*}} // coverage_primary_file.Box.init(z: Swift.String) -> coverage_primary_file.Box +// ALL: sil_coverage_map {{.*}} // coverage_primary_file.Box.init() -> coverage_primary_file.Box // ALL: sil_coverage_map {{.*}} // coverage_primary_file.main() -> () -// ALL: sil_coverage_map {{.*}} // __ntd_Box // PRIMARY-NOT: sil_coverage_map // PRIMARY: sil_coverage_map {{.*}} // coverage_primary_file.Box.init(y: Swift.Int) -> coverage_primary_file.Box diff --git a/test/Profiler/coverage_smoke.swift b/test/Profiler/coverage_smoke.swift index ca7f64c78ee10..9c60045ceaa97 100644 --- a/test/Profiler/coverage_smoke.swift +++ b/test/Profiler/coverage_smoke.swift @@ -133,9 +133,9 @@ extension Struct1 { var g2: Int = 0 class Class3 { - var m1 = g2 == 0 - ? "false" // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1 - : "true"; // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1 + var m1 = g2 == 0 // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}2 + ? "false" // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}2 + : "true"; // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}2 } // rdar://34244637: Wrong coverage for do/catch sequence diff --git a/test/Profiler/coverage_ternary.swift b/test/Profiler/coverage_ternary.swift index 8bb6432c35d75..e9006c1264304 100644 --- a/test/Profiler/coverage_ternary.swift +++ b/test/Profiler/coverage_ternary.swift @@ -1,17 +1,25 @@ // RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_ternary %s | %FileCheck %s +// coverage_ternary.bar.init() -> coverage_ternary.bar // CHECK-LABEL: sil hidden @$s16coverage_ternary3barCACycfc // CHECK-NOT: return // CHECK: builtin "int_instrprof_increment" -// CHECK-LABEL: sil hidden @$s16coverage_ternary3barCfD -// CHECK-NOT: return -// CHECK: builtin "int_instrprof_increment" +// rdar://problem/23256795 - Avoid crash if an if_expr has no parent +// CHECK: sil_coverage_map {{.*}}// variable initialization expression of coverage_ternary.bar.m1 : Swift.String +class bar { + var m1 = flag == 0 // CHECK: [[@LINE]]:12 -> [[@LINE+2]]:22 : 0 + ? "false" // CHECK: [[@LINE]]:16 -> [[@LINE]]:23 : 1 + : "true"; // CHECK: [[@LINE]]:16 -> [[@LINE]]:22 : (0 - 1) +} + +// Note: We didn't instantiate bar, but we still expect to see instrumentation +// for its *structors, and coverage mapping information for it. var flag: Int = 0 // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_ternary.foo -func foo(_ x : Int32) -> Int32 { +func foo(_ x : Int32) -> Int32 { // CHECK: [[@LINE]]:32 -> [[@LINE+4]]:2 : 0 return x == 3 ? 9000 // CHECK: [[@LINE]]:16 -> [[@LINE]]:20 : 1 : 1234 // CHECK: [[@LINE]]:16 -> [[@LINE]]:20 : (0 - 1) @@ -20,14 +28,3 @@ func foo(_ x : Int32) -> Int32 { foo(1) foo(2) foo(3) - -// rdar://problem/23256795 - Avoid crash if an if_expr has no parent -// CHECK: sil_coverage_map {{.*}}// __ntd_bar_line:[[@LINE+1]] -class bar { - var m1 = flag == 0 - ? "false" // CHECK: [[@LINE]]:16 -> [[@LINE]]:23 : 0 - : "true"; // CHECK: [[@LINE]]:16 -> [[@LINE]]:22 : (1 - 0) -} - -// Note: We didn't instantiate bar, but we still expect to see instrumentation -// for its *structors, and coverage mapping information for it. From d86ccc9741eb2caefda133008940cd664368715c Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 5 Jun 2019 12:13:50 -0700 Subject: [PATCH 038/112] [ConstraintSystem] Fix regression in partial application of initializers Correct a regression related to use of partially applied initializers, which should be rejected only if it happens in a delegation chain. Resolves: [SR-10837](https://bugs.swift.org/browse/SR-10837) Resolves: rdar://problem/51442825 --- lib/Sema/ConstraintSystem.cpp | 8 +++++-- test/Constraints/construction.swift | 35 +++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 8a2f2d5fbb5c1..dafbf5c35b58f 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1734,11 +1734,15 @@ isInvalidPartialApplication(ConstraintSystem &cs, const ValueDecl *member, auto baseTy = cs.simplifyType(cs.getType(anchor->getBase()))->getWithoutSpecifierType(); + // Partial applications are not allowed only for constructor + // delegation, reference on the metatype is considered acceptable. + if (baseTy->is() && isa(member)) + return {false, 0}; + // If base is a metatype it would be ignored (unless this is an initializer // call), but if it is some other type it means that we have a single // application level already. - unsigned level = - baseTy->is() && !isa(member) ? 0 : 1; + unsigned level = baseTy->is() ? 0 : 1; if (auto *call = dyn_cast_or_null(cs.getParentExpr(anchor))) { level += dyn_cast_or_null(cs.getParentExpr(call)) ? 2 : 1; } diff --git a/test/Constraints/construction.swift b/test/Constraints/construction.swift index d4c860818916c..6f8742a467812 100644 --- a/test/Constraints/construction.swift +++ b/test/Constraints/construction.swift @@ -220,3 +220,38 @@ func rdar_50668864() { } } } + +// SR-10837 (rdar://problem/51442825) - init partial application regression +func sr_10837() { + struct S { + let value: Int + + static func foo(_ v: Int?) { + _ = v.flatMap(self.init(value:)) // Ok + _ = v.flatMap(S.init(value:)) // Ok + _ = v.flatMap { S.init(value:)($0) } // Ok + _ = v.flatMap { self.init(value:)($0) } // Ok + } + } + + class A { + init(bar: Int) {} + } + + class B : A { + init(value: Int) {} + convenience init(foo: Int = 42) { + self.init(value:)(foo) // Ok + self.init(value:) + // expected-error@-1 {{partial application of 'self.init' initializer delegation is not allowed}} + } + } + + class C : A { + override init(bar: Int) { + super.init(bar:)(bar) // Ok + super.init(bar:) + // expected-error@-1 {{partial application of 'super.init' initializer chain is not allowed}} + } + } +} From 574dc53a864f002ea811ea7b1e97786110b91f4d Mon Sep 17 00:00:00 2001 From: Mishal Shah Date: Wed, 5 Jun 2019 13:11:32 -0700 Subject: [PATCH 039/112] Update the test simulator to iPhone Xs --- test/lit.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lit.cfg b/test/lit.cfg index 99e0ba05be13c..e4cb220c92851 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -118,7 +118,7 @@ def get_simulator_command(run_os, run_cpu, sdk_path): else: return "simctl spawn 'iPhone 5'" else: - return "simctl spawn 'iPhone 6s'" + return "simctl spawn 'iPhone Xs'" elif run_os == 'tvos': return "simctl spawn 'Apple TV 4K'" elif run_os == 'watchos': From a7025522a41e588921bea1d29e93ead25e0321c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodr=C3=ADguez=20Troiti=C3=B1o?= Date: Thu, 30 May 2019 17:45:22 -0700 Subject: [PATCH 040/112] [android] Basic support for backtraces. Android doesn't support the GNU backtrace call, but unwind.h is there to help. The code is a little bit more complicated than a simple backtrace call, but it is just a callback and the context struct. Sadly, it seems that -funwind-tables is needed in every piece of code that the backtrace needs to traverse, which means that at least the runtime and the stubs need -funwind-tables. However, the flag has been enabled for all targets (only on Android), just in case some other code ends up being in the stack. This might only be necessary for ARM targets, but currently we only build ARM targets in Android. The Swift parts of the stack seems to have unwind information and can be unwind. Another problem at the moment is the symbols from the executable are normally missing. To get symbol names two things need to happen: the symbol has to be public (so it is an exported symbol, and not just a local symbol that dladdr seems to not provide the name), and the linker has to be invoked with -export-dynamic. Without those two pieces, the addresses are returned (and match the binary just fine), but no names are printed. --- cmake/modules/AddSwift.cmake | 5 ++++ stdlib/public/runtime/Errors.cpp | 39 +++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 69ddf7669c537..a157185487507 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -303,6 +303,11 @@ function(_add_variant_c_compile_flags) "-fcoverage-mapping") endif() + if((CFLAGS_ARCH STREQUAL "armv7" OR CFLAGS_ARCH STREQUAL "aarch64") AND + (CFLAGS_SDK STREQUAL "LINUX" OR CFLAGS_SDK STREQUAL "ANDROID")) + list(APPEND result -funwind-tables) + endif() + if("${CFLAGS_SDK}" STREQUAL "ANDROID") swift_android_libcxx_include_paths(CFLAGS_CXX_INCLUDES) swift_android_include_for_arch("${CFLAGS_ARCH}" "${CFLAGS_ARCH}_INCLUDE") diff --git a/stdlib/public/runtime/Errors.cpp b/stdlib/public/runtime/Errors.cpp index a79d59e906dc7..5352f8738e9f9 100644 --- a/stdlib/public/runtime/Errors.cpp +++ b/stdlib/public/runtime/Errors.cpp @@ -14,7 +14,7 @@ // //===----------------------------------------------------------------------===// -#if defined(__CYGWIN__) || defined(__ANDROID__) || defined(__HAIKU__) +#if defined(__CYGWIN__) || defined(__HAIKU__) #define SWIFT_SUPPORTS_BACKTRACE_REPORTING 0 #else #define SWIFT_SUPPORTS_BACKTRACE_REPORTING 1 @@ -58,6 +58,10 @@ #include #endif +#if defined(__ELF__) +#include +#endif + namespace FatalErrorFlags { enum: uint32_t { ReportBacktrace = 1 << 0 @@ -188,6 +192,35 @@ void swift::dumpStackTraceEntry(unsigned index, void *framePC, #endif } +#if defined(__ELF__) +struct UnwindState { + void **current; + void **end; +}; + +static _Unwind_Reason_Code SwiftUnwindFrame(struct _Unwind_Context *context, void *arg) { + struct UnwindState *state = static_cast(arg); + if (state->current == state->end) { + return _URC_END_OF_STACK; + } + + uintptr_t pc; +#if defined(__arm__) + // ARM r15 is PC. UNW_REG_PC is *not* the same value, and using that will + // result in abnormal behaviour. + _Unwind_VRS_Get(context, _UVRSC_CORE, 15, _UVRSD_UINT32, &pc); + // Clear the ISA bit during the reporting. + pc &= ~(uintptr_t)0x1; +#else + pc = _Unwind_GetIP(context); +#endif + if (pc) { + *state->current++ = reinterpret_cast(pc); + } + return _URC_NO_REASON; +} +#endif + LLVM_ATTRIBUTE_NOINLINE void swift::printCurrentBacktrace(unsigned framesToSkip) { #if SWIFT_SUPPORTS_BACKTRACE_REPORTING @@ -195,6 +228,10 @@ void swift::printCurrentBacktrace(unsigned framesToSkip) { void *addrs[maxSupportedStackDepth]; #if defined(_WIN32) int symbolCount = CaptureStackBackTrace(0, maxSupportedStackDepth, addrs, NULL); +#elif defined(__ELF__) + struct UnwindState state = {&addrs[0], &addrs[maxSupportedStackDepth]}; + _Unwind_Backtrace(SwiftUnwindFrame, &state); + int symbolCount = state.current - addrs; #else int symbolCount = backtrace(addrs, maxSupportedStackDepth); #endif From 6f803155d7690ef4c851115b74ddd0a4226394de Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 5 Jun 2019 08:37:33 -0700 Subject: [PATCH 041/112] validation-test: avoid shell in ParseableInterface.verify_all_overlays Avoid using shell in the test as not all targets run with a POSIX shell for the test executor. --- validation-test/ParseableInterface/verify_all_overlays.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/validation-test/ParseableInterface/verify_all_overlays.py b/validation-test/ParseableInterface/verify_all_overlays.py index 96c07b0c3834b..1a11600252c32 100755 --- a/validation-test/ParseableInterface/verify_all_overlays.py +++ b/validation-test/ParseableInterface/verify_all_overlays.py @@ -6,9 +6,11 @@ # RUN: %empty-directory(%t) # RUN: %{python} %s %target-os %target-cpu %platform-sdk-overlay-dir %t \ # RUN: %target-swift-frontend -build-module-from-parseable-interface \ -# RUN: -Fsystem %sdk/System/Library/PrivateFrameworks/ >> %t/failures.txt +# RUN: -Fsystem %sdk/System/Library/PrivateFrameworks/ \ +# RUN: | sort > %t/failures.txt +# RUN: grep '# %target-os:' %s > %t/filter.txt || true # RUN: test ! -e %t/failures.txt || \ -# RUN: diff <(grep '# %target-os:' %s) <(sort -f %t/failures.txt) +# RUN: diff %t/filter.txt %t/failures.txt # REQUIRES: nonexecutable_test From fcb0ee59ae192269b460907cfe87c2cd645a3e78 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 5 Jun 2019 09:05:36 -0700 Subject: [PATCH 042/112] build: remove `ALL_POSIX_PLATFORMS` which is no longer used Cleanup some CMake logic that we no longer need as the entire code base now builds on all the targets. --- cmake/modules/AddSwift.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 69ddf7669c537..592e757abec5c 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -1693,7 +1693,6 @@ function(add_swift_target_library name) if("${SWIFTLIB_TARGET_SDKS}" STREQUAL "") set(SWIFTLIB_TARGET_SDKS ${SWIFT_SDKS}) endif() - list_replace(SWIFTLIB_TARGET_SDKS ALL_POSIX_PLATFORMS "ALL_APPLE_PLATFORMS;ANDROID;CYGWIN;FREEBSD;LINUX;HAIKU") list_replace(SWIFTLIB_TARGET_SDKS ALL_APPLE_PLATFORMS "${SWIFT_APPLE_PLATFORMS}") # All Swift code depends on the standard library, except for the standard From 1d1c362aba8062d5908383e1398cc40e6ea2e93b Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 5 Jun 2019 11:08:10 -0700 Subject: [PATCH 043/112] StdlibUnittest: consume the carriage return on stdout This was already being done for the stderr, but not for stdout. Doing this means that we no longer get spurious carriage returns on the stdout output stream on Windows. This is needed for supporting the validation test suite on Windows. --- stdlib/private/StdlibUnittest/StdlibUnittest.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift b/stdlib/private/StdlibUnittest/StdlibUnittest.swift index 3d25d17a3266b..a71120b6ce7d0 100644 --- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift +++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift @@ -934,7 +934,10 @@ class _ParentProcess { let (_, stdoutThread) = _stdlib_thread_create_block({ while !self._childStdout.isEOF { self._childStdout.read() - while let line = self._childStdout.getline() { + while var line = self._childStdout.getline() { + if let cr = line.firstIndex(of: "\r") { + line.remove(at: cr) + } var done: Bool (done: done, ()) = onStdoutLine(line) if done { return } From a82d33ff4fc79d965b77429da62f44b157bfbeda Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 5 Jun 2019 14:05:24 -0700 Subject: [PATCH 044/112] [SE-0258] Fix crash with implicitly-initialized backing storage. Fixes SR-10830 / rdar://problem/51443591 --- lib/AST/Decl.cpp | 5 +++++ test/SILGen/property_wrappers.swift | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index bd532848f0013..adda2e17fa04f 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -5478,6 +5478,11 @@ bool VarDecl::isPropertyWrapperInitializedWithInitialValue() const { // If there is no initializer, the initialization form depends on // whether the property wrapper type has an init(initialValue:). if (!isParentInitialized()) { + // If it's default-initializable, that doesn't use an initial value. + if (auto *PBD = getParentPatternBinding()) + if (PBD->isDefaultInitializable()) + return false; + auto wrapperTypeInfo = getAttachedPropertyWrapperTypeInfo(); return wrapperTypeInfo.initialValueInit != nullptr; } diff --git a/test/SILGen/property_wrappers.swift b/test/SILGen/property_wrappers.swift index 1045f7d5c2a26..759436c5c70e3 100644 --- a/test/SILGen/property_wrappers.swift +++ b/test/SILGen/property_wrappers.swift @@ -269,6 +269,34 @@ extension ClassUsingWrapper { } } +// +@_propertyWrapper +struct WrapperWithDefaultInit { + private var storage: T? + + init() { + self.storage = nil + } + + init(initialValue: T) { + self.storage = initialValue + } + + var value: T { + get { return storage! } + set { storage = newValue } + } +} + +class UseWrapperWithDefaultInit { + @WrapperWithDefaultInit var name: String +} + +// CHECK-LABEL: sil hidden [transparent] [ossa] @$s17property_wrappers25UseWrapperWithDefaultInitC5$name33_F728088E0028E14D18C6A10CF68512E8LLAA0defG0VySSGvpfi : $@convention(thin) () -> @owned WrapperWithDefaultInit +// CHECK: function_ref @$s17property_wrappers22WrapperWithDefaultInitVACyxGycfC +// CHECK: return {{%.*}} : $WrapperWithDefaultInit + + // CHECK-LABEL: sil_vtable ClassUsingWrapper { // CHECK: #ClassUsingWrapper.x!getter.1: (ClassUsingWrapper) -> () -> Int : @$s17property_wrappers17ClassUsingWrapperC1xSivg // ClassUsingWrapper.x.getter // CHECK: #ClassUsingWrapper.x!setter.1: (ClassUsingWrapper) -> (Int) -> () : @$s17property_wrappers17ClassUsingWrapperC1xSivs // ClassUsingWrapper.x.setter From 8abffa7d8997921adeddd2887219691a3654cc27 Mon Sep 17 00:00:00 2001 From: David Smith Date: Tue, 28 May 2019 16:09:17 -0700 Subject: [PATCH 045/112] Use the remaining half bit in the refcount to bypass ObjC deallocation overhead --- stdlib/public/SwiftShims/RefCount.h | 133 +++++++++++++----- stdlib/public/runtime/HeapObject.cpp | 39 ++++- stdlib/public/runtime/RefCount.cpp | 8 +- .../runtime/LongTests/LongRefcounting.cpp | 8 +- 4 files changed, 143 insertions(+), 45 deletions(-) diff --git a/stdlib/public/SwiftShims/RefCount.h b/stdlib/public/SwiftShims/RefCount.h index aa2462c0c7197..ca039ea9132cf 100644 --- a/stdlib/public/SwiftShims/RefCount.h +++ b/stdlib/public/SwiftShims/RefCount.h @@ -238,14 +238,29 @@ struct RefCountBitOffsets; // 32-bit out of line template <> struct RefCountBitOffsets<8> { - static const size_t IsImmortalShift = 0; - static const size_t IsImmortalBitCount = 1; - static const uint64_t IsImmortalMask = maskForField(IsImmortal); - - static const size_t UnownedRefCountShift = shiftAfterField(IsImmortal); + /* + The bottom 32 bits (on 64 bit architectures, fewer on 32 bit) of the refcount + field are effectively a union of two different configurations: + + ---Normal case--- + Bit 0: Does this object need to call out to the ObjC runtime for deallocation + Bits 1-31: Unowned refcount + + ---Immortal case--- + All bits set, the object does not deallocate or have a refcount + */ + static const size_t PureSwiftDeallocShift = 0; + static const size_t PureSwiftDeallocBitCount = 1; + static const uint64_t PureSwiftDeallocMask = maskForField(PureSwiftDealloc); + + static const size_t UnownedRefCountShift = shiftAfterField(PureSwiftDealloc); static const size_t UnownedRefCountBitCount = 31; static const uint64_t UnownedRefCountMask = maskForField(UnownedRefCount); + static const size_t IsImmortalShift = 0; // overlaps PureSwiftDealloc and UnownedRefCount + static const size_t IsImmortalBitCount = 32; + static const uint64_t IsImmortalMask = maskForField(IsImmortal); + static const size_t IsDeinitingShift = shiftAfterField(UnownedRefCount); static const size_t IsDeinitingBitCount = 1; static const uint64_t IsDeinitingMask = maskForField(IsDeiniting); @@ -271,14 +286,18 @@ struct RefCountBitOffsets<8> { // 32-bit inline template <> struct RefCountBitOffsets<4> { - static const size_t IsImmortalShift = 0; - static const size_t IsImmortalBitCount = 1; - static const uint64_t IsImmortalMask = maskForField(IsImmortal); + static const size_t PureSwiftDeallocShift = 0; + static const size_t PureSwiftDeallocBitCount = 1; + static const uint32_t PureSwiftDeallocMask = maskForField(PureSwiftDealloc); - static const size_t UnownedRefCountShift = shiftAfterField(IsImmortal); + static const size_t UnownedRefCountShift = shiftAfterField(PureSwiftDealloc); static const size_t UnownedRefCountBitCount = 7; static const uint32_t UnownedRefCountMask = maskForField(UnownedRefCount); + static const size_t IsImmortalShift = 0; // overlaps PureSwiftDealloc and UnownedRefCount + static const size_t IsImmortalBitCount = 8; + static const uint32_t IsImmortalMask = maskForField(IsImmortal); + static const size_t IsDeinitingShift = shiftAfterField(UnownedRefCount); static const size_t IsDeinitingBitCount = 1; static const uint32_t IsDeinitingMask = maskForField(IsDeiniting); @@ -369,16 +388,38 @@ class RefCountBitsT { enum Immortal_t { Immortal }; LLVM_ATTRIBUTE_ALWAYS_INLINE - bool isImmortal() const { - return bool(getField(IsImmortal)); + bool isImmortal(bool checkSlowRCBit) const { + if (checkSlowRCBit) { + return (getField(IsImmortal) == Offsets::IsImmortalMask) && + bool(getField(UseSlowRC)); + } else { + return (getField(IsImmortal) == Offsets::IsImmortalMask); + } + } + + LLVM_ATTRIBUTE_ALWAYS_INLINE + bool isOverflowingUnownedRefCount(uint32_t oldValue, uint32_t inc) const { + auto newValue = getUnownedRefCount(); + return newValue != oldValue + inc || + newValue == Offsets::UnownedRefCountMask; } LLVM_ATTRIBUTE_ALWAYS_INLINE void setIsImmortal(bool value) { - setField(IsImmortal, value); + setField(IsImmortal, value ? Offsets::IsImmortalMask : 0); setField(UseSlowRC, value); } + LLVM_ATTRIBUTE_ALWAYS_INLINE + bool pureSwiftDeallocation() const { + return bool(getField(PureSwiftDealloc)) && !bool(getField(UseSlowRC)); + } + + LLVM_ATTRIBUTE_ALWAYS_INLINE + void setPureSwiftDeallocation(bool value) { + setField(PureSwiftDealloc, value); + } + LLVM_ATTRIBUTE_ALWAYS_INLINE RefCountBitsT() = default; @@ -386,16 +427,16 @@ class RefCountBitsT { constexpr RefCountBitsT(uint32_t strongExtraCount, uint32_t unownedCount) : bits((BitsType(strongExtraCount) << Offsets::StrongExtraRefCountShift) | + (BitsType(1) << Offsets::PureSwiftDeallocShift) | (BitsType(unownedCount) << Offsets::UnownedRefCountShift)) { } LLVM_ATTRIBUTE_ALWAYS_INLINE constexpr RefCountBitsT(Immortal_t immortal) - : bits((BitsType(2) << Offsets::StrongExtraRefCountShift) | - (BitsType(2) << Offsets::UnownedRefCountShift) | - (BitsType(1) << Offsets::IsImmortalShift) | - (BitsType(1) << Offsets::UseSlowRCShift)) + : bits((BitsType(2) << Offsets::StrongExtraRefCountShift) | + (BitsType(Offsets::IsImmortalMask)) | + (BitsType(1) << Offsets::UseSlowRCShift)) { } LLVM_ATTRIBUTE_ALWAYS_INLINE @@ -433,7 +474,7 @@ class RefCountBitsT { LLVM_ATTRIBUTE_ALWAYS_INLINE bool hasSideTable() const { - bool hasSide = getUseSlowRC() && !isImmortal(); + bool hasSide = getUseSlowRC() && !isImmortal(false); // Side table refcount must not point to another side table. assert((refcountIsInline || !hasSide) && @@ -523,7 +564,7 @@ class RefCountBitsT { LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool decrementStrongExtraRefCount(uint32_t dec) { #ifndef NDEBUG - if (!hasSideTable() && !isImmortal()) { + if (!hasSideTable() && !isImmortal(false)) { // Can't check these assertions with side table present. if (getIsDeiniting()) @@ -558,7 +599,7 @@ class RefCountBitsT { static_assert(Offsets::UnownedRefCountBitCount + Offsets::IsDeinitingBitCount + Offsets::StrongExtraRefCountBitCount + - Offsets::IsImmortalBitCount + + Offsets::PureSwiftDeallocBitCount + Offsets::UseSlowRCBitCount == sizeof(bits)*8, "inspect isUniquelyReferenced after adding fields"); @@ -715,7 +756,7 @@ class RefCounts { void setIsImmortal(bool immortal) { auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); - if (oldbits.isImmortal()) { + if (oldbits.isImmortal(true)) { return; } RefCountBits newbits; @@ -725,7 +766,27 @@ class RefCounts { } while (!refCounts.compare_exchange_weak(oldbits, newbits, std::memory_order_relaxed)); } - + + void setPureSwiftDeallocation(bool nonobjc) { + auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); + //Immortal and no objc complications share a bit, so don't let setting + //the complications one clear the immmortal one + if (oldbits.isImmortal(true) || oldbits.pureSwiftDeallocation() == nonobjc){ + return; + } + RefCountBits newbits; + do { + newbits = oldbits; + newbits.setPureSwiftDeallocation(nonobjc); + } while (!refCounts.compare_exchange_weak(oldbits, newbits, + std::memory_order_relaxed)); + } + + bool getPureSwiftDeallocation() { + auto bits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); + return bits.pureSwiftDeallocation(); + } + // Initialize from another refcount bits. // Only inline -> out-of-line is allowed (used for new side table entries). void init(InlineRefCountBits newBits) { @@ -740,7 +801,7 @@ class RefCounts { newbits = oldbits; bool fast = newbits.incrementStrongExtraRefCount(inc); if (SWIFT_UNLIKELY(!fast)) { - if (oldbits.isImmortal()) + if (oldbits.isImmortal(false)) return; return incrementSlow(oldbits, inc); } @@ -753,7 +814,7 @@ class RefCounts { auto newbits = oldbits; bool fast = newbits.incrementStrongExtraRefCount(inc); if (SWIFT_UNLIKELY(!fast)) { - if (oldbits.isImmortal()) + if (oldbits.isImmortal(false)) return; return incrementNonAtomicSlow(oldbits, inc); } @@ -771,7 +832,7 @@ class RefCounts { newbits = oldbits; bool fast = newbits.incrementStrongExtraRefCount(1); if (SWIFT_UNLIKELY(!fast)) { - if (oldbits.isImmortal()) + if (oldbits.isImmortal(false)) return true; return tryIncrementSlow(oldbits); } @@ -788,7 +849,7 @@ class RefCounts { auto newbits = oldbits; bool fast = newbits.incrementStrongExtraRefCount(1); if (SWIFT_UNLIKELY(!fast)) { - if (oldbits.isImmortal()) + if (oldbits.isImmortal(false)) return true; return tryIncrementNonAtomicSlow(oldbits); } @@ -824,7 +885,7 @@ class RefCounts { // Precondition: the reference count must be 1 void decrementFromOneNonAtomic() { auto bits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); - if (bits.isImmortal()) { + if (bits.isImmortal(true)) { return; } if (bits.hasSideTable()) @@ -922,7 +983,7 @@ class RefCounts { // Decrement completed normally. New refcount is not zero. deinitNow = false; } - else if (oldbits.isImmortal()) { + else if (oldbits.isImmortal(false)) { return false; } else if (oldbits.hasSideTable()) { // Decrement failed because we're on some other slow path. @@ -961,7 +1022,7 @@ class RefCounts { // Decrement completed normally. New refcount is not zero. deinitNow = false; } - else if (oldbits.isImmortal()) { + else if (oldbits.isImmortal(false)) { return false; } else if (oldbits.hasSideTable()) { @@ -1001,7 +1062,7 @@ class RefCounts { bool fast = newbits.decrementStrongExtraRefCount(dec); if (SWIFT_UNLIKELY(!fast)) { - if (oldbits.isImmortal()) { + if (oldbits.isImmortal(false)) { return false; } // Slow paths include side table; deinit; underflow @@ -1025,7 +1086,7 @@ class RefCounts { // Increment the unowned reference count. void incrementUnowned(uint32_t inc) { auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); - if (oldbits.isImmortal()) + if (oldbits.isImmortal(true)) return; RefCountBits newbits; do { @@ -1037,7 +1098,7 @@ class RefCounts { uint32_t oldValue = newbits.incrementUnownedRefCount(inc); // Check overflow and use the side table on overflow. - if (newbits.getUnownedRefCount() != oldValue + inc) + if (newbits.isOverflowingUnownedRefCount(oldValue, inc)) return incrementUnownedSlow(inc); } while (!refCounts.compare_exchange_weak(oldbits, newbits, @@ -1046,7 +1107,7 @@ class RefCounts { void incrementUnownedNonAtomic(uint32_t inc) { auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); - if (oldbits.isImmortal()) + if (oldbits.isImmortal(true)) return; if (oldbits.hasSideTable()) return oldbits.getSideTable()->incrementUnownedNonAtomic(inc); @@ -1056,7 +1117,7 @@ class RefCounts { uint32_t oldValue = newbits.incrementUnownedRefCount(inc); // Check overflow and use the side table on overflow. - if (newbits.getUnownedRefCount() != oldValue + inc) + if (newbits.isOverflowingUnownedRefCount(oldValue, inc)) return incrementUnownedSlow(inc); refCounts.store(newbits, std::memory_order_relaxed); @@ -1066,7 +1127,7 @@ class RefCounts { // Return true if the caller should free the object. bool decrementUnownedShouldFree(uint32_t dec) { auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); - if (oldbits.isImmortal()) + if (oldbits.isImmortal(true)) return false; RefCountBits newbits; @@ -1094,7 +1155,7 @@ class RefCounts { bool decrementUnownedShouldFreeNonAtomic(uint32_t dec) { auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); - if (oldbits.isImmortal()) + if (oldbits.isImmortal(true)) return false; if (oldbits.hasSideTable()) return oldbits.getSideTable()->decrementUnownedShouldFreeNonAtomic(dec); @@ -1383,7 +1444,7 @@ inline bool RefCounts::doDecrementNonAtomic(uint32_t dec) { auto newbits = oldbits; bool fast = newbits.decrementStrongExtraRefCount(dec); if (!fast) { - if (oldbits.isImmortal()) { + if (oldbits.isImmortal(false)) { return false; } return doDecrementNonAtomicSlow(oldbits, dec); diff --git a/stdlib/public/runtime/HeapObject.cpp b/stdlib/public/runtime/HeapObject.cpp index 65f52fbaecbf9..7088ed253f943 100644 --- a/stdlib/public/runtime/HeapObject.cpp +++ b/stdlib/public/runtime/HeapObject.cpp @@ -42,6 +42,7 @@ # include # include # include "swift/Runtime/ObjCBridge.h" +# include "swift/Runtime/Once.h" #endif #include "Leaks.h" @@ -78,6 +79,32 @@ HeapObject *swift::swift_allocObject(HeapMetadata const *metadata, return _swift_allocObject(metadata, requiredSize, requiredAlignmentMask); } +#if OBJC_SETASSOCIATEDOBJECTHOOK_DEFINED +//We interpose objc_setAssociatedObject so that we can set a flag in +//the refcount field of Swift objects to indicate that they have associations, +//since we can't safely skip ObjC dealloc work if they do +static objc_hook_setAssociatedObject originalAssocObjectFunc = nullptr; + +static void _swift_setAssociatedObject_hook( + id _Nonnull object, + const void * _Nonnull key, + id _Nullable value, + objc_AssociationPolicy policy +) { + if (!isObjCTaggedPointerOrNull(object) && + objectUsesNativeSwiftReferenceCounting(object)) { + auto heapObj = reinterpret_cast(object); + heapObj->refCounts.setPureSwiftDeallocation(false); + } + originalAssocObjectFunc(object, key, value, policy); +} + +static void _interpose_objc_association(void *ctxt) { + objc_setHook_setAssociatedObject(_swift_setAssociatedObject_hook, + &originalAssocObjectFunc); +} +#endif + static HeapObject *_swift_allocObject_(HeapMetadata const *metadata, size_t requiredSize, size_t requiredAlignmentMask) { @@ -90,6 +117,11 @@ static HeapObject *_swift_allocObject_(HeapMetadata const *metadata, // Linux, and macOS. new (object) HeapObject(metadata); +#if OBJC_SETASSOCIATEDOBJECTHOOK_DEFINED + static swift_once_t associatedObjectHookOnce; + swift_once(&associatedObjectHookOnce, _interpose_objc_association, nullptr); +#endif + // If leak tracking is enabled, start tracking this object. SWIFT_LEAKS_START_TRACKING_OBJECT(object); @@ -594,9 +626,14 @@ void swift::swift_rootObjCDealloc(HeapObject *self) { void swift::swift_deallocClassInstance(HeapObject *object, size_t allocatedSize, size_t allocatedAlignMask) { -#if SWIFT_OBJC_INTEROP +#if OBJC_SETASSOCIATEDOBJECTHOOK_DEFINED // We need to let the ObjC runtime clean up any associated objects or weak // references associated with this object. + if (originalAssocObjectFunc == nullptr || + !object->refCounts.getPureSwiftDeallocation()) { + objc_destructInstance((id)object); + } +#elif SWIFT_OBJC_INTEROP objc_destructInstance((id)object); #endif swift_deallocObject(object, allocatedSize, allocatedAlignMask); diff --git a/stdlib/public/runtime/RefCount.cpp b/stdlib/public/runtime/RefCount.cpp index 4b3ca72a4e2fe..4dc7394f92540 100644 --- a/stdlib/public/runtime/RefCount.cpp +++ b/stdlib/public/runtime/RefCount.cpp @@ -17,7 +17,7 @@ namespace swift { template void RefCounts::incrementSlow(RefCountBits oldbits, uint32_t n) { - if (oldbits.isImmortal()) { + if (oldbits.isImmortal(false)) { return; } else if (oldbits.hasSideTable()) { @@ -36,7 +36,7 @@ template void RefCounts::incrementSlow(SideTableRefCountB template void RefCounts::incrementNonAtomicSlow(RefCountBits oldbits, uint32_t n) { - if (oldbits.isImmortal()) { + if (oldbits.isImmortal(false)) { return; } else if (oldbits.hasSideTable()) { @@ -52,7 +52,7 @@ template void RefCounts::incrementNonAtomicSlow(SideTable template bool RefCounts::tryIncrementSlow(RefCountBits oldbits) { - if (oldbits.isImmortal()) { + if (oldbits.isImmortal(false)) { return true; } else if (oldbits.hasSideTable()) @@ -65,7 +65,7 @@ template bool RefCounts::tryIncrementSlow(SideTableRefCou template bool RefCounts::tryIncrementNonAtomicSlow(RefCountBits oldbits) { - if (oldbits.isImmortal()) { + if (oldbits.isImmortal(false)) { return true; } else if (oldbits.hasSideTable()) diff --git a/unittests/runtime/LongTests/LongRefcounting.cpp b/unittests/runtime/LongTests/LongRefcounting.cpp index 3b83f10c77e24..d3cd449e91bff 100644 --- a/unittests/runtime/LongTests/LongRefcounting.cpp +++ b/unittests/runtime/LongTests/LongRefcounting.cpp @@ -239,8 +239,8 @@ static void unownedReleaseALot(TestObject *object, uint64_t count) { } } -// Maximum legal unowned retain count. 31 bits with no implicit +1. -const uint64_t maxURC = (1ULL << (32 - 1)) - 1; +// Maximum legal unowned retain count. 31 bits minus one with no implicit +1. +const uint64_t maxURC = (1ULL << (32 - 1)) - 2; TEST(LongRefcountingTest, unowned_retain_max) { // Don't generate millions of failures if something goes wrong. @@ -282,7 +282,7 @@ TEST(LongRefcountingTest, unowned_retain_overflow_DeathTest) { auto object = allocTestObject(&deinited, 1); // URC is 1. Retain to maxURC, then retain again and verify overflow error. - unownedRetainALot(object, maxURC - 1); + unownedRetainALot(object, maxURC); EXPECT_EQ(0u, deinited); EXPECT_ALLOCATED(object); ASSERT_DEATH(swift_unownedRetain(object), @@ -329,7 +329,7 @@ TEST(LongRefcountingTest, nonatomic_unowned_retain_overflow_DeathTest) { auto object = allocTestObject(&deinited, 1); // URC is 1. Retain to maxURC, then retain again and verify overflow error. - unownedRetainALot(object, maxURC - 1); + unownedRetainALot(object, maxURC); EXPECT_EQ(0u, deinited); EXPECT_ALLOCATED(object); ASSERT_DEATH(swift_nonatomic_unownedRetain(object), From 6c349eca99c306b74d15b63e8c435b6bf92f6572 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodr=C3=ADguez=20Troiti=C3=B1o?= Date: Wed, 5 Jun 2019 14:44:45 -0700 Subject: [PATCH 046/112] [windows] Use only a drive letter as build directory. Caveat: two builds cannot happen at the same time in the same machine. --- utils/build-windows.bat | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/utils/build-windows.bat b/utils/build-windows.bat index 71f0fe73ae6f3..4ba12aea6fe8b 100644 --- a/utils/build-windows.bat +++ b/utils/build-windows.bat @@ -37,10 +37,15 @@ set source_root=%current_directory%\..\.. cd %source_root% set source_root=%CD% -set build_root=%source_root%\build +set full_build_root=%source_root%\build set install_directory=%build_root%\Library\Developer\Toolchains\unknown-Asserts-development.xctoolchain\usr -mkdir %build_root% +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 S: /d +subst S: %full_build_root% %exitOnError% +set build_root=S: call :clone_repositories %exitOnError% call :download_icu %exitOnError% From ae68558daea1633ccfce050cfba076d8c27eee34 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 5 Jun 2019 16:50:34 -0700 Subject: [PATCH 047/112] [ConstraintSystem] Generalize and extract opening function params/result into `substGenericArgs` --- include/swift/AST/Types.h | 1 + lib/AST/Type.cpp | 16 ++++++++++++++++ lib/Sema/ConstraintSystem.cpp | 17 ++--------------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index ffa347b95a04e..012d5c59c3f8f 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -3172,6 +3172,7 @@ class GenericFunctionType final : public AnyFunctionType, /// Substitute the given generic arguments into this generic /// function type and return the resulting non-generic type. FunctionType *substGenericArgs(SubstitutionMap subs); + FunctionType *substGenericArgs(llvm::function_ref substFn) const; void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getGenericSignature(), getParams(), getResult(), diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 825891dc61d2c..b9af83796638d 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -2878,6 +2878,22 @@ GenericFunctionType::substGenericArgs(SubstitutionMap subs) { substFn->getResult(), getExtInfo()); } +FunctionType *GenericFunctionType::substGenericArgs( + llvm::function_ref substFn) const { + llvm::SmallVector params; + params.reserve(getNumParams()); + + llvm::transform(getParams(), std::back_inserter(params), + [&](const AnyFunctionType::Param ¶m) { + return param.withType(substFn(param.getPlainType())); + }); + + auto resultTy = substFn(getResult()); + + // Build the resulting (non-generic) function type. + return FunctionType::get(params, resultTy, getExtInfo()); +} + CanFunctionType CanGenericFunctionType::substGenericArgs(SubstitutionMap subs) const { return cast( diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index eb5e19ae23a66..2c8c93cff0516 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -647,21 +647,8 @@ FunctionType *ConstraintSystem::openFunctionType( [&](Type type) -> Type { return openType(type, replacements); }); } - // Transform the parameters and output type. - llvm::SmallVector openedParams; - openedParams.reserve(genericFn->getNumParams()); - for (const auto ¶m : genericFn->getParams()) { - auto type = openType(param.getPlainType(), replacements); - openedParams.push_back(AnyFunctionType::Param(type, param.getLabel(), - param.getParameterFlags())); - } - - auto resultTy = openType(genericFn->getResult(), replacements); - - // Build the resulting (non-generic) function type. - funcType = FunctionType::get( - openedParams, resultTy, - FunctionType::ExtInfo().withThrows(genericFn->throws())); + funcType = genericFn->substGenericArgs( + [&](Type type) { return openType(type, replacements); }); } return funcType->castTo(); From 329ed30b71e6955b8466d69a9f5974255163f382 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 5 Jun 2019 17:09:00 -0700 Subject: [PATCH 048/112] [ConstraintSystem] Make sure that read-only keypath is preferred for read-only properties This fixes an oversight related to `ReferenceWritableKeyPath` overloads of the KeyPath dynamic member lookup. Original check filtered out only `WritableKeyPath` if the storage is read-only, but it should check for both `WritableKeyPath` and `ReferenceWritableKeyPath`, otherwise program is going to crash at run time. Resolves: rdar://problem/51456614 --- lib/Sema/CSSimplify.cpp | 6 ++-- .../keypath_dynamic_member_lookup.swift | 35 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 8c766b12ffc9d..d4713caa7db47 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -4114,8 +4114,10 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName, if (auto *storage = dyn_cast(decl)) { // If this is an attempt to access read-only member via // writable key path, let's fail this choice early. + auto &ctx = getASTContext(); if (isReadOnlyKeyPathComponent(storage) && - keyPath == getASTContext().getWritableKeyPathDecl()) { + (keyPath == ctx.getWritableKeyPathDecl() || + keyPath == ctx.getReferenceWritableKeyPathDecl())) { result.addUnviable( candidate, MemberLookupResult::UR_WritableKeyPathOnReadOnlyMember); @@ -4126,7 +4128,7 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName, // on the other hand if setter is mutating there is no point // of attempting `ReferenceWritableKeyPath` overload. if (storage->isSetterMutating() && - keyPath == getASTContext().getReferenceWritableKeyPathDecl()) { + keyPath == ctx.getReferenceWritableKeyPathDecl()) { result.addUnviable( candidate, MemberLookupResult::UR_ReferenceWritableKeyPathOnMutatingMember); diff --git a/test/Constraints/keypath_dynamic_member_lookup.swift b/test/Constraints/keypath_dynamic_member_lookup.swift index fb4f1bb899870..80ec2c3ade99a 100644 --- a/test/Constraints/keypath_dynamic_member_lookup.swift +++ b/test/Constraints/keypath_dynamic_member_lookup.swift @@ -250,3 +250,38 @@ func test_recursive_dynamic_lookup(_ lens: Lens>) { // CHECK-NEXT: keypath $KeyPath>, Lens>>, (root $Lens>; settable_property $Lens>, id @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs15WritableKeyPathCyxqd__G_tcluig : {{.*}}) _ = \Lens>.topLeft.x } + +@dynamicMemberLookup +struct RefWritableBox { + var obj: T + + init(_ obj: T) { + self.obj = obj + } + + subscript(dynamicMember member: KeyPath) -> U { + get { return obj[keyPath: member] } + } + + subscript(dynamicMember member: ReferenceWritableKeyPath) -> U { + get { return obj[keyPath: member] } + set { obj[keyPath: member] = newValue } + } +} + +func prefer_readonly_keypath_over_reference_writable() { + class C { + let foo: Int + + init(_ foo: Int) { + self.foo = foo + } + } + + var box = RefWritableBox(C(42)) + // expected-warning@-1 {{variable 'box' was never mutated; consider changing to 'let' constant}} + + // CHECK: function_ref RefWritableBox.subscript.getter + // CHECK-NEXT: function_ref @$s29keypath_dynamic_member_lookup14RefWritableBoxV0B6Memberqd__s7KeyPathCyxqd__G_tcluig + _ = box.foo +} From 903547f694b7916439bc16e54bf272ada9c0f840 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Wed, 5 Jun 2019 21:35:24 -0700 Subject: [PATCH 049/112] [stdlib-standalone] Always configure with lit-args=--filter=stdlib/ Otherwise, we will need to reconfigure when someone uses the build vs test preset. Because the reconfiguring forces a rebuild, this is unfortunate. Luckily, we want to make it so we always only build stdlib tests, so this works around the problem. --- utils/build-presets.ini | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/utils/build-presets.ini b/utils/build-presets.ini index 7842a20abc117..87954fe809c05 100644 --- a/utils/build-presets.ini +++ b/utils/build-presets.ini @@ -2049,6 +2049,7 @@ native-llvm-tools-path=%(toolchain_path)s native-clang-tools-path=%(toolchain_path)s build-ninja +lit-args=--filter=stdlib/ [preset: stdlib_RA_standalone,build] mixin-preset=stdlib_base_standalone @@ -2064,7 +2065,6 @@ mixin-preset=stdlib_RA_standalone,build test validation-test -lit-args=-v --filter=stdlib/ [preset: stdlib_RDA_standalone,build] mixin-preset=stdlib_base_standalone @@ -2080,7 +2080,6 @@ mixin-preset=stdlib_RDA_standalone,build test validation-test -lit-args=-v --filter=stdlib/ [preset: stdlib_DA_standalone,build] mixin-preset=stdlib_base_standalone @@ -2096,4 +2095,3 @@ mixin-preset=stdlib_DA_standalone,build test validation-test -lit-args=-v --filter=stdlib/ From 6b8f8267d841c445d6e02f3755315b181fd0f9f7 Mon Sep 17 00:00:00 2001 From: Mishal Shah Date: Tue, 4 Jun 2019 08:55:52 -0700 Subject: [PATCH 050/112] [Test] Update attr_ibaction_ios.swift test to only run on Apple platform --- test/attr/attr_ibaction_ios.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/test/attr/attr_ibaction_ios.swift b/test/attr/attr_ibaction_ios.swift index dea44ffc0c918..47546317e5655 100644 --- a/test/attr/attr_ibaction_ios.swift +++ b/test/attr/attr_ibaction_ios.swift @@ -1,4 +1,5 @@ // RUN: not %target-build-swift -typecheck %s 2>&1 | %FileCheck -check-prefix=CHECK-%target-os %s +// REQUIRES: objc_interop // REQUIRES: executable_test class IBActionWrapperTy { From 817ea129f2ef93071da95953cd77e0138f886e06 Mon Sep 17 00:00:00 2001 From: Mishal Shah Date: Wed, 5 Jun 2019 23:10:34 -0700 Subject: [PATCH 051/112] Revert "Use the remaining half bit in the refcount to bypass ObjC deallocation overhead" --- stdlib/public/SwiftShims/RefCount.h | 133 +++++------------- stdlib/public/runtime/HeapObject.cpp | 39 +---- stdlib/public/runtime/RefCount.cpp | 8 +- .../runtime/LongTests/LongRefcounting.cpp | 8 +- 4 files changed, 45 insertions(+), 143 deletions(-) diff --git a/stdlib/public/SwiftShims/RefCount.h b/stdlib/public/SwiftShims/RefCount.h index ca039ea9132cf..aa2462c0c7197 100644 --- a/stdlib/public/SwiftShims/RefCount.h +++ b/stdlib/public/SwiftShims/RefCount.h @@ -238,29 +238,14 @@ struct RefCountBitOffsets; // 32-bit out of line template <> struct RefCountBitOffsets<8> { - /* - The bottom 32 bits (on 64 bit architectures, fewer on 32 bit) of the refcount - field are effectively a union of two different configurations: - - ---Normal case--- - Bit 0: Does this object need to call out to the ObjC runtime for deallocation - Bits 1-31: Unowned refcount - - ---Immortal case--- - All bits set, the object does not deallocate or have a refcount - */ - static const size_t PureSwiftDeallocShift = 0; - static const size_t PureSwiftDeallocBitCount = 1; - static const uint64_t PureSwiftDeallocMask = maskForField(PureSwiftDealloc); - - static const size_t UnownedRefCountShift = shiftAfterField(PureSwiftDealloc); + static const size_t IsImmortalShift = 0; + static const size_t IsImmortalBitCount = 1; + static const uint64_t IsImmortalMask = maskForField(IsImmortal); + + static const size_t UnownedRefCountShift = shiftAfterField(IsImmortal); static const size_t UnownedRefCountBitCount = 31; static const uint64_t UnownedRefCountMask = maskForField(UnownedRefCount); - static const size_t IsImmortalShift = 0; // overlaps PureSwiftDealloc and UnownedRefCount - static const size_t IsImmortalBitCount = 32; - static const uint64_t IsImmortalMask = maskForField(IsImmortal); - static const size_t IsDeinitingShift = shiftAfterField(UnownedRefCount); static const size_t IsDeinitingBitCount = 1; static const uint64_t IsDeinitingMask = maskForField(IsDeiniting); @@ -286,18 +271,14 @@ struct RefCountBitOffsets<8> { // 32-bit inline template <> struct RefCountBitOffsets<4> { - static const size_t PureSwiftDeallocShift = 0; - static const size_t PureSwiftDeallocBitCount = 1; - static const uint32_t PureSwiftDeallocMask = maskForField(PureSwiftDealloc); + static const size_t IsImmortalShift = 0; + static const size_t IsImmortalBitCount = 1; + static const uint64_t IsImmortalMask = maskForField(IsImmortal); - static const size_t UnownedRefCountShift = shiftAfterField(PureSwiftDealloc); + static const size_t UnownedRefCountShift = shiftAfterField(IsImmortal); static const size_t UnownedRefCountBitCount = 7; static const uint32_t UnownedRefCountMask = maskForField(UnownedRefCount); - static const size_t IsImmortalShift = 0; // overlaps PureSwiftDealloc and UnownedRefCount - static const size_t IsImmortalBitCount = 8; - static const uint32_t IsImmortalMask = maskForField(IsImmortal); - static const size_t IsDeinitingShift = shiftAfterField(UnownedRefCount); static const size_t IsDeinitingBitCount = 1; static const uint32_t IsDeinitingMask = maskForField(IsDeiniting); @@ -388,38 +369,16 @@ class RefCountBitsT { enum Immortal_t { Immortal }; LLVM_ATTRIBUTE_ALWAYS_INLINE - bool isImmortal(bool checkSlowRCBit) const { - if (checkSlowRCBit) { - return (getField(IsImmortal) == Offsets::IsImmortalMask) && - bool(getField(UseSlowRC)); - } else { - return (getField(IsImmortal) == Offsets::IsImmortalMask); - } - } - - LLVM_ATTRIBUTE_ALWAYS_INLINE - bool isOverflowingUnownedRefCount(uint32_t oldValue, uint32_t inc) const { - auto newValue = getUnownedRefCount(); - return newValue != oldValue + inc || - newValue == Offsets::UnownedRefCountMask; + bool isImmortal() const { + return bool(getField(IsImmortal)); } LLVM_ATTRIBUTE_ALWAYS_INLINE void setIsImmortal(bool value) { - setField(IsImmortal, value ? Offsets::IsImmortalMask : 0); + setField(IsImmortal, value); setField(UseSlowRC, value); } - LLVM_ATTRIBUTE_ALWAYS_INLINE - bool pureSwiftDeallocation() const { - return bool(getField(PureSwiftDealloc)) && !bool(getField(UseSlowRC)); - } - - LLVM_ATTRIBUTE_ALWAYS_INLINE - void setPureSwiftDeallocation(bool value) { - setField(PureSwiftDealloc, value); - } - LLVM_ATTRIBUTE_ALWAYS_INLINE RefCountBitsT() = default; @@ -427,16 +386,16 @@ class RefCountBitsT { constexpr RefCountBitsT(uint32_t strongExtraCount, uint32_t unownedCount) : bits((BitsType(strongExtraCount) << Offsets::StrongExtraRefCountShift) | - (BitsType(1) << Offsets::PureSwiftDeallocShift) | (BitsType(unownedCount) << Offsets::UnownedRefCountShift)) { } LLVM_ATTRIBUTE_ALWAYS_INLINE constexpr RefCountBitsT(Immortal_t immortal) - : bits((BitsType(2) << Offsets::StrongExtraRefCountShift) | - (BitsType(Offsets::IsImmortalMask)) | - (BitsType(1) << Offsets::UseSlowRCShift)) + : bits((BitsType(2) << Offsets::StrongExtraRefCountShift) | + (BitsType(2) << Offsets::UnownedRefCountShift) | + (BitsType(1) << Offsets::IsImmortalShift) | + (BitsType(1) << Offsets::UseSlowRCShift)) { } LLVM_ATTRIBUTE_ALWAYS_INLINE @@ -474,7 +433,7 @@ class RefCountBitsT { LLVM_ATTRIBUTE_ALWAYS_INLINE bool hasSideTable() const { - bool hasSide = getUseSlowRC() && !isImmortal(false); + bool hasSide = getUseSlowRC() && !isImmortal(); // Side table refcount must not point to another side table. assert((refcountIsInline || !hasSide) && @@ -564,7 +523,7 @@ class RefCountBitsT { LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool decrementStrongExtraRefCount(uint32_t dec) { #ifndef NDEBUG - if (!hasSideTable() && !isImmortal(false)) { + if (!hasSideTable() && !isImmortal()) { // Can't check these assertions with side table present. if (getIsDeiniting()) @@ -599,7 +558,7 @@ class RefCountBitsT { static_assert(Offsets::UnownedRefCountBitCount + Offsets::IsDeinitingBitCount + Offsets::StrongExtraRefCountBitCount + - Offsets::PureSwiftDeallocBitCount + + Offsets::IsImmortalBitCount + Offsets::UseSlowRCBitCount == sizeof(bits)*8, "inspect isUniquelyReferenced after adding fields"); @@ -756,7 +715,7 @@ class RefCounts { void setIsImmortal(bool immortal) { auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); - if (oldbits.isImmortal(true)) { + if (oldbits.isImmortal()) { return; } RefCountBits newbits; @@ -766,27 +725,7 @@ class RefCounts { } while (!refCounts.compare_exchange_weak(oldbits, newbits, std::memory_order_relaxed)); } - - void setPureSwiftDeallocation(bool nonobjc) { - auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); - //Immortal and no objc complications share a bit, so don't let setting - //the complications one clear the immmortal one - if (oldbits.isImmortal(true) || oldbits.pureSwiftDeallocation() == nonobjc){ - return; - } - RefCountBits newbits; - do { - newbits = oldbits; - newbits.setPureSwiftDeallocation(nonobjc); - } while (!refCounts.compare_exchange_weak(oldbits, newbits, - std::memory_order_relaxed)); - } - - bool getPureSwiftDeallocation() { - auto bits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); - return bits.pureSwiftDeallocation(); - } - + // Initialize from another refcount bits. // Only inline -> out-of-line is allowed (used for new side table entries). void init(InlineRefCountBits newBits) { @@ -801,7 +740,7 @@ class RefCounts { newbits = oldbits; bool fast = newbits.incrementStrongExtraRefCount(inc); if (SWIFT_UNLIKELY(!fast)) { - if (oldbits.isImmortal(false)) + if (oldbits.isImmortal()) return; return incrementSlow(oldbits, inc); } @@ -814,7 +753,7 @@ class RefCounts { auto newbits = oldbits; bool fast = newbits.incrementStrongExtraRefCount(inc); if (SWIFT_UNLIKELY(!fast)) { - if (oldbits.isImmortal(false)) + if (oldbits.isImmortal()) return; return incrementNonAtomicSlow(oldbits, inc); } @@ -832,7 +771,7 @@ class RefCounts { newbits = oldbits; bool fast = newbits.incrementStrongExtraRefCount(1); if (SWIFT_UNLIKELY(!fast)) { - if (oldbits.isImmortal(false)) + if (oldbits.isImmortal()) return true; return tryIncrementSlow(oldbits); } @@ -849,7 +788,7 @@ class RefCounts { auto newbits = oldbits; bool fast = newbits.incrementStrongExtraRefCount(1); if (SWIFT_UNLIKELY(!fast)) { - if (oldbits.isImmortal(false)) + if (oldbits.isImmortal()) return true; return tryIncrementNonAtomicSlow(oldbits); } @@ -885,7 +824,7 @@ class RefCounts { // Precondition: the reference count must be 1 void decrementFromOneNonAtomic() { auto bits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); - if (bits.isImmortal(true)) { + if (bits.isImmortal()) { return; } if (bits.hasSideTable()) @@ -983,7 +922,7 @@ class RefCounts { // Decrement completed normally. New refcount is not zero. deinitNow = false; } - else if (oldbits.isImmortal(false)) { + else if (oldbits.isImmortal()) { return false; } else if (oldbits.hasSideTable()) { // Decrement failed because we're on some other slow path. @@ -1022,7 +961,7 @@ class RefCounts { // Decrement completed normally. New refcount is not zero. deinitNow = false; } - else if (oldbits.isImmortal(false)) { + else if (oldbits.isImmortal()) { return false; } else if (oldbits.hasSideTable()) { @@ -1062,7 +1001,7 @@ class RefCounts { bool fast = newbits.decrementStrongExtraRefCount(dec); if (SWIFT_UNLIKELY(!fast)) { - if (oldbits.isImmortal(false)) { + if (oldbits.isImmortal()) { return false; } // Slow paths include side table; deinit; underflow @@ -1086,7 +1025,7 @@ class RefCounts { // Increment the unowned reference count. void incrementUnowned(uint32_t inc) { auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); - if (oldbits.isImmortal(true)) + if (oldbits.isImmortal()) return; RefCountBits newbits; do { @@ -1098,7 +1037,7 @@ class RefCounts { uint32_t oldValue = newbits.incrementUnownedRefCount(inc); // Check overflow and use the side table on overflow. - if (newbits.isOverflowingUnownedRefCount(oldValue, inc)) + if (newbits.getUnownedRefCount() != oldValue + inc) return incrementUnownedSlow(inc); } while (!refCounts.compare_exchange_weak(oldbits, newbits, @@ -1107,7 +1046,7 @@ class RefCounts { void incrementUnownedNonAtomic(uint32_t inc) { auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); - if (oldbits.isImmortal(true)) + if (oldbits.isImmortal()) return; if (oldbits.hasSideTable()) return oldbits.getSideTable()->incrementUnownedNonAtomic(inc); @@ -1117,7 +1056,7 @@ class RefCounts { uint32_t oldValue = newbits.incrementUnownedRefCount(inc); // Check overflow and use the side table on overflow. - if (newbits.isOverflowingUnownedRefCount(oldValue, inc)) + if (newbits.getUnownedRefCount() != oldValue + inc) return incrementUnownedSlow(inc); refCounts.store(newbits, std::memory_order_relaxed); @@ -1127,7 +1066,7 @@ class RefCounts { // Return true if the caller should free the object. bool decrementUnownedShouldFree(uint32_t dec) { auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); - if (oldbits.isImmortal(true)) + if (oldbits.isImmortal()) return false; RefCountBits newbits; @@ -1155,7 +1094,7 @@ class RefCounts { bool decrementUnownedShouldFreeNonAtomic(uint32_t dec) { auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME); - if (oldbits.isImmortal(true)) + if (oldbits.isImmortal()) return false; if (oldbits.hasSideTable()) return oldbits.getSideTable()->decrementUnownedShouldFreeNonAtomic(dec); @@ -1444,7 +1383,7 @@ inline bool RefCounts::doDecrementNonAtomic(uint32_t dec) { auto newbits = oldbits; bool fast = newbits.decrementStrongExtraRefCount(dec); if (!fast) { - if (oldbits.isImmortal(false)) { + if (oldbits.isImmortal()) { return false; } return doDecrementNonAtomicSlow(oldbits, dec); diff --git a/stdlib/public/runtime/HeapObject.cpp b/stdlib/public/runtime/HeapObject.cpp index 7088ed253f943..65f52fbaecbf9 100644 --- a/stdlib/public/runtime/HeapObject.cpp +++ b/stdlib/public/runtime/HeapObject.cpp @@ -42,7 +42,6 @@ # include # include # include "swift/Runtime/ObjCBridge.h" -# include "swift/Runtime/Once.h" #endif #include "Leaks.h" @@ -79,32 +78,6 @@ HeapObject *swift::swift_allocObject(HeapMetadata const *metadata, return _swift_allocObject(metadata, requiredSize, requiredAlignmentMask); } -#if OBJC_SETASSOCIATEDOBJECTHOOK_DEFINED -//We interpose objc_setAssociatedObject so that we can set a flag in -//the refcount field of Swift objects to indicate that they have associations, -//since we can't safely skip ObjC dealloc work if they do -static objc_hook_setAssociatedObject originalAssocObjectFunc = nullptr; - -static void _swift_setAssociatedObject_hook( - id _Nonnull object, - const void * _Nonnull key, - id _Nullable value, - objc_AssociationPolicy policy -) { - if (!isObjCTaggedPointerOrNull(object) && - objectUsesNativeSwiftReferenceCounting(object)) { - auto heapObj = reinterpret_cast(object); - heapObj->refCounts.setPureSwiftDeallocation(false); - } - originalAssocObjectFunc(object, key, value, policy); -} - -static void _interpose_objc_association(void *ctxt) { - objc_setHook_setAssociatedObject(_swift_setAssociatedObject_hook, - &originalAssocObjectFunc); -} -#endif - static HeapObject *_swift_allocObject_(HeapMetadata const *metadata, size_t requiredSize, size_t requiredAlignmentMask) { @@ -117,11 +90,6 @@ static HeapObject *_swift_allocObject_(HeapMetadata const *metadata, // Linux, and macOS. new (object) HeapObject(metadata); -#if OBJC_SETASSOCIATEDOBJECTHOOK_DEFINED - static swift_once_t associatedObjectHookOnce; - swift_once(&associatedObjectHookOnce, _interpose_objc_association, nullptr); -#endif - // If leak tracking is enabled, start tracking this object. SWIFT_LEAKS_START_TRACKING_OBJECT(object); @@ -626,14 +594,9 @@ void swift::swift_rootObjCDealloc(HeapObject *self) { void swift::swift_deallocClassInstance(HeapObject *object, size_t allocatedSize, size_t allocatedAlignMask) { -#if OBJC_SETASSOCIATEDOBJECTHOOK_DEFINED +#if SWIFT_OBJC_INTEROP // We need to let the ObjC runtime clean up any associated objects or weak // references associated with this object. - if (originalAssocObjectFunc == nullptr || - !object->refCounts.getPureSwiftDeallocation()) { - objc_destructInstance((id)object); - } -#elif SWIFT_OBJC_INTEROP objc_destructInstance((id)object); #endif swift_deallocObject(object, allocatedSize, allocatedAlignMask); diff --git a/stdlib/public/runtime/RefCount.cpp b/stdlib/public/runtime/RefCount.cpp index 4dc7394f92540..4b3ca72a4e2fe 100644 --- a/stdlib/public/runtime/RefCount.cpp +++ b/stdlib/public/runtime/RefCount.cpp @@ -17,7 +17,7 @@ namespace swift { template void RefCounts::incrementSlow(RefCountBits oldbits, uint32_t n) { - if (oldbits.isImmortal(false)) { + if (oldbits.isImmortal()) { return; } else if (oldbits.hasSideTable()) { @@ -36,7 +36,7 @@ template void RefCounts::incrementSlow(SideTableRefCountB template void RefCounts::incrementNonAtomicSlow(RefCountBits oldbits, uint32_t n) { - if (oldbits.isImmortal(false)) { + if (oldbits.isImmortal()) { return; } else if (oldbits.hasSideTable()) { @@ -52,7 +52,7 @@ template void RefCounts::incrementNonAtomicSlow(SideTable template bool RefCounts::tryIncrementSlow(RefCountBits oldbits) { - if (oldbits.isImmortal(false)) { + if (oldbits.isImmortal()) { return true; } else if (oldbits.hasSideTable()) @@ -65,7 +65,7 @@ template bool RefCounts::tryIncrementSlow(SideTableRefCou template bool RefCounts::tryIncrementNonAtomicSlow(RefCountBits oldbits) { - if (oldbits.isImmortal(false)) { + if (oldbits.isImmortal()) { return true; } else if (oldbits.hasSideTable()) diff --git a/unittests/runtime/LongTests/LongRefcounting.cpp b/unittests/runtime/LongTests/LongRefcounting.cpp index d3cd449e91bff..3b83f10c77e24 100644 --- a/unittests/runtime/LongTests/LongRefcounting.cpp +++ b/unittests/runtime/LongTests/LongRefcounting.cpp @@ -239,8 +239,8 @@ static void unownedReleaseALot(TestObject *object, uint64_t count) { } } -// Maximum legal unowned retain count. 31 bits minus one with no implicit +1. -const uint64_t maxURC = (1ULL << (32 - 1)) - 2; +// Maximum legal unowned retain count. 31 bits with no implicit +1. +const uint64_t maxURC = (1ULL << (32 - 1)) - 1; TEST(LongRefcountingTest, unowned_retain_max) { // Don't generate millions of failures if something goes wrong. @@ -282,7 +282,7 @@ TEST(LongRefcountingTest, unowned_retain_overflow_DeathTest) { auto object = allocTestObject(&deinited, 1); // URC is 1. Retain to maxURC, then retain again and verify overflow error. - unownedRetainALot(object, maxURC); + unownedRetainALot(object, maxURC - 1); EXPECT_EQ(0u, deinited); EXPECT_ALLOCATED(object); ASSERT_DEATH(swift_unownedRetain(object), @@ -329,7 +329,7 @@ TEST(LongRefcountingTest, nonatomic_unowned_retain_overflow_DeathTest) { auto object = allocTestObject(&deinited, 1); // URC is 1. Retain to maxURC, then retain again and verify overflow error. - unownedRetainALot(object, maxURC); + unownedRetainALot(object, maxURC - 1); EXPECT_EQ(0u, deinited); EXPECT_ALLOCATED(object); ASSERT_DEATH(swift_nonatomic_unownedRetain(object), From 14b96d1e12ab5cc6f9ded65e372f48a9770c2fd3 Mon Sep 17 00:00:00 2001 From: Mishal Shah Date: Thu, 6 Jun 2019 01:06:33 -0700 Subject: [PATCH 052/112] [Test] Fix complete_decl_attribute.swift for Xcode 11 beta --- test/IDE/complete_decl_attribute.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/IDE/complete_decl_attribute.swift b/test/IDE/complete_decl_attribute.swift index 28ddce79748f1..d3bdd5d7db4ac 100644 --- a/test/IDE/complete_decl_attribute.swift +++ b/test/IDE/complete_decl_attribute.swift @@ -166,6 +166,7 @@ struct _S { // ON_METHOD-DAG: Keyword/None: warn_unqualified_access[#Func Attribute#]; name=warn_unqualified_access // ON_METHOD-DAG: Keyword/None: usableFromInline[#Func Attribute#]; name=usableFromInline // ON_METHOD-DAG: Keyword/None: discardableResult[#Func Attribute#]; name=discardableResult +// ON_METHOD-DAG: Keyword/None: IBSegueAction[#Func Attribute#]; name=IBSegueAction // ON_METHOD: End completions @#^ON_MEMBER_LAST^# @@ -191,6 +192,7 @@ struct _S { // ON_MEMBER_LAST-DAG: Keyword/None: usableFromInline[#Declaration Attribute#]; name=usableFromInline // ON_MEMBER_LAST-DAG: Keyword/None: discardableResult[#Declaration Attribute#]; name=discardableResult // ON_MEMBER_LAST-DAG: Keyword/None: GKInspectable[#Declaration Attribute#]; name=GKInspectable +// ON_MEMBER_LAST-DAG: Keyword/None: IBSegueAction[#Declaration Attribute#]; name=IBSegueAction // ON_MEMBER_LAST-DAG: Keyword/None: _propertyWrapper[#Declaration Attribute#]; name=_propertyWrapper // ON_MEMBER_LAST-NOT: Keyword // ON_MEMBER_LAST: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct @@ -224,6 +226,5 @@ struct _S { // KEYWORD_LAST-NEXT: Keyword/None: GKInspectable[#Declaration Attribute#]; name=GKInspectable{{$}} // KEYWORD_LAST-NEXT: Keyword/None: _propertyWrapper[#Declaration Attribute#]; name=_propertyWrapper // KEYWORD_LAST-NEXT: Keyword/None: IBSegueAction[#Declaration Attribute#]; name=IBSegueAction{{$}} -// KEYWORD_LAST-NOT: Keyword // KEYWORD_LAST: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct // KEYWORD_LAST: End completions From bc9eac9f1f58dd877e71ffb309179ba0dce6f60e Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 5 Jun 2019 15:48:07 -0700 Subject: [PATCH 053/112] IRGen: Allow stored_property keypaths on class constraint archetypes rdar://50271944 --- lib/IRGen/GenKeyPath.cpp | 52 ++++++++++++++++++++++++++-------- test/IRGen/keypaths.sil | 7 +++++ test/Interpreter/keypath.swift | 28 ++++++++++++++++++ 3 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 test/Interpreter/keypath.swift diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp index 4175868472dd2..db240198c8f74 100644 --- a/lib/IRGen/GenKeyPath.cpp +++ b/lib/IRGen/GenKeyPath.cpp @@ -747,31 +747,47 @@ emitKeyPathComponent(IRGenModule &IGM, fields.addInt32(fieldOffset.getValue()); break; } - + + auto *classDecl = baseTy->getClassOrBoundGenericClass(); + auto loweredClassTy = loweredBaseTy; + + // Recover class decl from superclass constraint + if (!classDecl && genericEnv) { + auto ty = genericEnv->mapTypeIntoContext(baseTy)->getCanonicalType(); + auto archetype = dyn_cast(ty); + if (archetype && archetype->requiresClass()) { + auto superClassTy = ty->getSuperclass(false)->getCanonicalType(); + classDecl = superClassTy->getClassOrBoundGenericClass(); + loweredClassTy = + IGM.getLoweredType(AbstractionPattern::getOpaque(), + superClassTy->getWithoutSpecifierType()); + } + } + // For a class, we may know the fixed offset of a field at compile time, // or we may need to fetch it at instantiation time. Depending on the // ObjC-ness and resilience of the class hierarchy, there might be a few // different ways we need to go about this. - if (loweredBaseTy.getClassOrBoundGenericClass()) { + if (loweredClassTy.getClassOrBoundGenericClass()) { // Use the property's class type to determine the field access. auto propertyBaseDecl = property->getDeclContext()->getSelfClassDecl(); auto currentBaseTy = - loweredBaseTy.getASTType()->getSuperclassForDecl(propertyBaseDecl); + loweredClassTy.getASTType()->getSuperclassForDecl(propertyBaseDecl); assert(currentBaseTy->getClassOrBoundGenericClass() == propertyBaseDecl); - loweredBaseTy = + loweredClassTy = IGM.getLoweredType(AbstractionPattern::getOpaque(), currentBaseTy); auto loweredBaseContextTy = SILType::getPrimitiveObjectType( GenericEnvironment::mapTypeIntoContext(genericEnv, - loweredBaseTy.getASTType()) + loweredClassTy.getASTType()) ->getCanonicalType()); switch (getClassFieldAccess(IGM, loweredBaseContextTy, property)) { case FieldAccess::ConstantDirect: { // Known constant fixed offset. auto offset = tryEmitConstantClassFragilePhysicalMemberOffset(IGM, - loweredBaseTy, + loweredClassTy, property); assert(offset && "no constant offset for ConstantDirect field?!"); addFixedOffset(/*struct*/ false, property->isLet(), offset); @@ -794,10 +810,8 @@ emitKeyPathComponent(IRGenModule &IGM, auto header = KeyPathComponentHeader ::forClassComponentWithUnresolvedFieldOffset(property->isLet()); fields.addInt32(header.getData()); - auto fieldOffset = - getClassFieldOffsetOffset(IGM, - loweredBaseTy.getClassOrBoundGenericClass(), - property); + auto fieldOffset = getClassFieldOffsetOffset( + IGM, loweredClassTy.getClassOrBoundGenericClass(), property); fields.addInt32(fieldOffset.getValue()); break; } @@ -960,6 +974,20 @@ emitKeyPathComponent(IRGenModule &IGM, // the property. auto property = id.getProperty(); idKind = KeyPathComponentHeader::StoredPropertyIndex; + auto *classDecl = baseTy->getClassOrBoundGenericClass(); + auto loweredClassTy = loweredBaseTy; + // Recover class decl from superclass constraint + if (!classDecl && genericEnv) { + auto ty = genericEnv->mapTypeIntoContext(baseTy)->getCanonicalType(); + auto archetype = dyn_cast(ty); + if (archetype && archetype->requiresClass()) { + auto superClassTy = ty->getSuperclass(false)->getCanonicalType(); + classDecl = superClassTy->getClassOrBoundGenericClass(); + loweredClassTy = + IGM.getLoweredType(AbstractionPattern::getOpaque(), + superClassTy->getWithoutSpecifierType()); + } + } if (auto struc = baseTy->getStructOrBoundGenericStruct()) { // Scan the stored properties of the struct to find the index. We should // only ever use a struct field as a uniquing key from inside the @@ -976,12 +1004,12 @@ emitKeyPathComponent(IRGenModule &IGM, } assert(structIdx && "not a stored property of the struct?!"); idValue = llvm::ConstantInt::get(IGM.SizeTy, structIdx.getValue()); - } else if (auto *classDecl = baseTy->getClassOrBoundGenericClass()) { + } else if (classDecl) { // TODO: This field index would require runtime resolution with Swift // native class resilience. We never directly access ObjC-imported // ivars so we can disregard ObjC ivar resilience for this computation // and start counting at the Swift native root. - switch (getClassFieldAccess(IGM, loweredBaseTy, property)) { + switch (getClassFieldAccess(IGM, loweredClassTy, property)) { case FieldAccess::ConstantDirect: case FieldAccess::ConstantIndirect: case FieldAccess::NonConstantDirect: diff --git a/test/IRGen/keypaths.sil b/test/IRGen/keypaths.sil index fc6717ea3cc0f..dd232e87ed240 100644 --- a/test/IRGen/keypaths.sil +++ b/test/IRGen/keypaths.sil @@ -553,6 +553,13 @@ entry: return undef : $() } +sil @class_constrainted : $@convention(thin) () -> () { +bb0: + %k = keypath $KeyPath, <τ_0_0 where τ_0_0 : C> (root $τ_0_0; stored_property #C.y : $String) + %t = tuple () + return %t : $() +} + sil @s_get : $@convention(thin) (@in_guaranteed A, UnsafeRawPointer) -> @out B sil @s_set : $@convention(thin) (@in_guaranteed B, @in_guaranteed A, UnsafeRawPointer) -> () sil @s_equals : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool diff --git a/test/Interpreter/keypath.swift b/test/Interpreter/keypath.swift new file mode 100644 index 0000000000000..bd39a73cedca5 --- /dev/null +++ b/test/Interpreter/keypath.swift @@ -0,0 +1,28 @@ +// RUN: %target-run-simple-swift +// REQUIRES: executable_test + +class MyLabel { + var text = "label" +} + +class Controller { + fileprivate let label = MyLabel() +} + +struct Container { + var v : V + init(_ v: V) { + self.v = v + } + func useKeyPath(_ keyPath: KeyPath) -> String { + return (v[keyPath: keyPath] as! MyLabel).text + } +} + +extension Container where V: Controller { + func test() -> String { + return useKeyPath(\.label) + } +} +// CHECK: label +print(Container(Controller()).test()) From caa22861827b143a727d686b27547e635b78e8ad Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Thu, 6 Jun 2019 08:23:45 -0700 Subject: [PATCH 054/112] [stdlib_standalone] Add a update-checkout scheme for people to test out stdlib_standalone. --- .../update-checkout-config.json | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/utils/update_checkout/update-checkout-config.json b/utils/update_checkout/update-checkout-config.json index df7e46585b14d..ee2ab258ff208 100644 --- a/utils/update_checkout/update-checkout-config.json +++ b/utils/update_checkout/update-checkout-config.json @@ -321,6 +321,32 @@ "indexstore-db": "swift-5.1-branch", "sourcekit-lsp": "swift-5.1-branch" } + }, + "stdlib_standalone" : { + "aliases": ["stdlib_standalone"], + "repos": { + "llvm": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "clang": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "compiler-rt": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift": "stdlib_standalone", + "lldb": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "cmark": "master", + "llbuild": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swiftpm": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift-syntax": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift-stress-tester": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift-corelibs-xctest": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift-corelibs-foundation": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift-corelibs-libdispatch": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift-integration-tests": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift-xcode-playground-support": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "ninja": "release", + "icu": "release-61-1", + "clang-tools-extra": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "libcxx": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "indexstore-db": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "sourcekit-lsp": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a" + } } } } From b8dec80f95731939f35c787f9581ef72a52d941c Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Thu, 6 Jun 2019 10:03:03 -0700 Subject: [PATCH 055/112] [build-script-impl] Use `cmake-file-api` in case the CMake used supports it --- utils/build-script-impl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/utils/build-script-impl b/utils/build-script-impl index 1d22fa1eb55ae..45dbf48644136 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -2893,6 +2893,11 @@ for host in "${ALL_HOSTS[@]}"; do if [[ "${RECONFIGURE}" || ! -f "${cmake_cache_path}" || \ ( ! -z "${generator_output_path}" && ! -f "${generator_output_path}" ) ]] ; then call mkdir -p "${build_dir}" + + # Use `cmake-file-api` in case it is available. + call mkdir -p "${build_dir}/.cmake/api/v1/query" + call touch "${build_dir}/.cmake/api/v1/query/codemodel-v2" "${build_dir}/.cmake/api/v1/query/cache-v2" + if [[ -n "${DISTCC}" ]]; then EXTRA_DISTCC_OPTIONS=("DISTCC_HOSTS=localhost,lzo,cpp") fi From 1a555dfedaed51de22be6a59344a3b6330c6ad7f Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Thu, 6 Jun 2019 11:01:45 -0700 Subject: [PATCH 056/112] [SE-0258] Fix memberwise initializer involving wrapped properties. The determination of which type to use within the implicit memberwise initializer for a wrapper property (between the original property type and the wrapper type) could be affected by the synthesis of the call to the default initializer. Rewrite the logic here to depend on aspects of the AST that don't change with further type checking. --- lib/AST/Decl.cpp | 38 +++++++++++++++++--------- test/IDE/print_property_wrappers.swift | 2 +- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index adda2e17fa04f..99a2860b0f7d0 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -5475,21 +5475,33 @@ bool VarDecl::isPropertyWrapperInitializedWithInitialValue() const { if (!ctx.getLazyResolver()) return false; - // If there is no initializer, the initialization form depends on - // whether the property wrapper type has an init(initialValue:). - if (!isParentInitialized()) { - // If it's default-initializable, that doesn't use an initial value. - if (auto *PBD = getParentPatternBinding()) - if (PBD->isDefaultInitializable()) - return false; + auto customAttr = getAttachedPropertyWrapper(); + if (!customAttr) + return false; - auto wrapperTypeInfo = getAttachedPropertyWrapperTypeInfo(); - return wrapperTypeInfo.initialValueInit != nullptr; - } + auto *PBD = getParentPatternBinding(); + if (!PBD) + return false; + + // If there was an initializer on the original property, initialize + // via the initial value. + if (PBD->getPatternList()[0].getEqualLoc().isValid()) + return true; + + // If there was an initializer on the attribute itself, initialize + // via the full wrapper. + if (customAttr->getArg() != nullptr) + return false; - // Otherwise, check whether the '=' initialization form was used. - return getPropertyWrapperBackingPropertyInfo().originalInitialValue - != nullptr; + // If the property wrapper is default-initializable, it's the wrapper + // being initialized. + if (PBD->isDefaultInitializable(0)) + return false; + + // There is no initializer, so the initialization form depends on + // whether the property wrapper type has an init(initialValue:). + auto wrapperTypeInfo = getAttachedPropertyWrapperTypeInfo(); + return wrapperTypeInfo.initialValueInit != nullptr; } Identifier VarDecl::getObjCPropertyName() const { diff --git a/test/IDE/print_property_wrappers.swift b/test/IDE/print_property_wrappers.swift index ca61c4c4bc80d..5b1001f3b4075 100644 --- a/test/IDE/print_property_wrappers.swift +++ b/test/IDE/print_property_wrappers.swift @@ -47,7 +47,7 @@ struct HasWrappers { var z: String // Memberwise initializer. - // CHECK: init(x: Wrapper = Wrapper(closure: foo), y: Bool = true, z: String = Wrapper()) + // CHECK: init(x: Wrapper = Wrapper(closure: foo), y: Bool = true, z: Wrapper = Wrapper()) } func trigger() { From 3fb9a2a7a45ad96e3b9f0850bcbb7fc81449aabb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodr=C3=ADguez=20Troiti=C3=B1o?= Date: Wed, 5 Jun 2019 11:53:49 -0700 Subject: [PATCH 057/112] [windows] Fix Python tests in Windows. - Forward several environment variables to the test environment because Windows uses them to inform the processes about things like the number of processors and the architecture. - Normalize some literal Unix paths to be the same as the results in Windows, that will have forward slashes and the drive letter. - Skip some test that use build-script-impl and tests that check for files being executable (everything is executable in Windows). - Don't use the owner and group arguments for tar on Windows. - Hide the stderr output of which. In Windows it prints the full PATH in case of failures, which is disrupting. - Quote many paths in Windows in the output of build-script results. - Provide a version of mock-distcc that can be executed in Windows. The raw Python script cannot. - Change the expected results for clang/clang++ to the right values in Windows (clang-cl in both cases). --- test/lit.cfg | 8 +++++++ .../build_swift/tests/argparse/test_types.py | 21 ++++++++++++++--- .../tests/test_driver_arguments.py | 6 ++++- .../swift_build_support/tar.py | 2 +- .../swift_build_support/which.py | 3 ++- .../swift_build_support/tests/mock-distcc.cmd | 3 +++ .../tests/products/test_ninja.py | 14 ++++++++--- .../tests/test_arguments.py | 4 ++++ utils/swift_build_support/tests/test_cmake.py | 8 +++++-- .../tests/test_migration.py | 5 ++++ utils/swift_build_support/tests/test_shell.py | 17 ++++++++++---- utils/swift_build_support/tests/test_tar.py | 19 ++++++++++++--- .../tests/test_toolchain.py | 23 +++++++++++++++---- 13 files changed, 110 insertions(+), 23 deletions(-) create mode 100644 utils/swift_build_support/tests/mock-distcc.cmd diff --git a/test/lit.cfg b/test/lit.cfg index 99e0ba05be13c..a280be0cbef4c 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -878,6 +878,14 @@ if run_vendor == 'apple': elif run_os in ['windows-msvc']: lit_config.note('Testing Windows ' + config.variant_triple) + config.environment['NUMBER_OF_PROCESSORS'] = os.environ['NUMBER_OF_PROCESSORS'] + if 'PROCESSOR_ARCHITEW6432' in os.environ: + config.environment['PROCESSOR_ARCHITEW6432'] = os.environ['PROCESSOR_ARCHITEW6432'] + if 'PROCESSOR_ARCHITECTURE' in os.environ: + config.environment['PROCESSOR_ARCHITECTURE'] = os.environ['PROCESSOR_ARCHITECTURE'] + if 'PROCESSOR_IDENTIFIER' in os.environ: + config.environment['PROCESSOR_IDENTIFIER'] = os.environ['PROCESSOR_IDENTIFIER'] + config.environment['PYTHON_EXECUTABLE'] = sys.executable config.target_object_format = 'coff' config.target_shared_library_prefix = '' config.target_shared_library_suffix = '.dll' diff --git a/utils/build_swift/tests/argparse/test_types.py b/utils/build_swift/tests/argparse/test_types.py index 0faf180dada41..c9ed3a1aa2b15 100644 --- a/utils/build_swift/tests/argparse/test_types.py +++ b/utils/build_swift/tests/argparse/test_types.py @@ -8,6 +8,7 @@ import os.path +import platform from ..utils import TestCase from ...argparse import ArgumentTypeError, types @@ -139,13 +140,16 @@ def test_expands_path(self): path_type = types.PathType() path = path_type('/some/random/path/../') - self.assertEqual('/some/random', path) + self.assertEqual(self._platform_path('/some/random'), path) path = path_type('~/path/to/some/file.txt') - self.assertEqual(self.home_dir + '/path/to/some/file.txt', path) + self.assertEqual( + self._platform_path(self.home_dir + '/path/to/some/file.txt'), + path) path = path_type('~/path/to/some/../file.txt') - self.assertEqual(self.home_dir + '/path/to/file.txt', path) + self.assertEqual( + self._platform_path(self.home_dir + '/path/to/file.txt'), path) def test_assert_exists(self): path_type = types.PathType(assert_exists=True) @@ -155,9 +159,14 @@ def test_assert_exists(self): with self.assertRaises(ArgumentTypeError): path_type('/nonsensisal/path/') + + with self.assertRaises(ArgumentTypeError): path_type('~/not-a-real/path to a file') def test_assert_executable(self): + if platform.system() == 'Windows': + self.skipTest("All files are considered executable in Windows") + path_type = types.PathType(assert_executable=True) bash_path = '/bin/bash' @@ -168,6 +177,12 @@ def test_assert_executable(self): with self.assertRaises(ArgumentTypeError): path_type(__file__) + def _platform_path(self, path): + if platform.system() == 'Windows': + return os.path.abspath(os.path.normpath(path)) + else: + return path + class TestRegexType(TestCase): diff --git a/utils/build_swift/tests/test_driver_arguments.py b/utils/build_swift/tests/test_driver_arguments.py index fa9e5676f56ad..4da00251c1fd2 100644 --- a/utils/build_swift/tests/test_driver_arguments.py +++ b/utils/build_swift/tests/test_driver_arguments.py @@ -8,6 +8,7 @@ import os +import platform import sys import unittest from contextlib import contextmanager @@ -344,7 +345,10 @@ def generate_option_test(cls, option): def generate_preset_test(cls, preset_name, preset_args): def test(self): try: - self.parse_default_args(preset_args, check_impl_args=True) + # Windows cannot run build-script-impl to check the impl args. + is_windows = platform.system() == 'Windows' + self.parse_default_args(preset_args, + check_impl_args=not is_windows) except ParserError as e: self.fail('failed to parse preset "{}": {}'.format( preset_name, e)) diff --git a/utils/swift_build_support/swift_build_support/tar.py b/utils/swift_build_support/swift_build_support/tar.py index 19267aa49921b..15d29ee5d40b3 100644 --- a/utils/swift_build_support/swift_build_support/tar.py +++ b/utils/swift_build_support/swift_build_support/tar.py @@ -25,7 +25,7 @@ def tar(source, destination): # - We wish to explicitly set the owner and group of the archive. args = ['tar', '-c', '-z', '-f', destination] - if platform.system() != 'Darwin': + if platform.system() != 'Darwin' and platform.system() != 'Windows': args += ['--owner=0', '--group=0'] # Discard stderr output such as 'tar: Failed to open ...'. We'll detect diff --git a/utils/swift_build_support/swift_build_support/which.py b/utils/swift_build_support/swift_build_support/which.py index e602711857bc6..8b329cc95cc2b 100644 --- a/utils/swift_build_support/swift_build_support/which.py +++ b/utils/swift_build_support/swift_build_support/which.py @@ -35,7 +35,8 @@ def which(cmd): been backported to Python 2.7, which we support. """ out = shell.capture(['which', cmd], - dry_run=False, echo=False, optional=True) + dry_run=False, echo=False, + optional=True, stderr=shell.DEVNULL) if out is None: return None return out.rstrip() diff --git a/utils/swift_build_support/tests/mock-distcc.cmd b/utils/swift_build_support/tests/mock-distcc.cmd new file mode 100644 index 0000000000000..f851e7798e22b --- /dev/null +++ b/utils/swift_build_support/tests/mock-distcc.cmd @@ -0,0 +1,3 @@ +@ echo off +IF NOT DEFINED PYTHON_EXECUTABLE SET PYTHON_EXECUTABLE=python +"%PYTHON_EXECUTABLE%" "%~dp0\mock-distcc" %* diff --git a/utils/swift_build_support/tests/products/test_ninja.py b/utils/swift_build_support/tests/products/test_ninja.py index c80c05fb872ee..2c9845723a897 100644 --- a/utils/swift_build_support/tests/products/test_ninja.py +++ b/utils/swift_build_support/tests/products/test_ninja.py @@ -119,7 +119,15 @@ def test_build(self): + pushd {build_dir} + {expect_env}{python} configure.py --bootstrap + popd -""".format(source_dir=self.workspace.source_dir('ninja'), - build_dir=self.workspace.build_dir('build', 'ninja'), +""".format(source_dir=self._platform_quote( + self.workspace.source_dir('ninja')), + build_dir=self._platform_quote( + self.workspace.build_dir('build', 'ninja')), expect_env=expect_env, - python=sys.executable)) + python=self._platform_quote(sys.executable))) + + def _platform_quote(self, path): + if platform.system() == 'Windows': + return "'{}'".format(path) + else: + return path diff --git a/utils/swift_build_support/tests/test_arguments.py b/utils/swift_build_support/tests/test_arguments.py index 2c3cf0fdf2d76..2eaa922b75323 100644 --- a/utils/swift_build_support/tests/test_arguments.py +++ b/utils/swift_build_support/tests/test_arguments.py @@ -12,6 +12,7 @@ import argparse import os +import platform import sys import unittest try: @@ -85,6 +86,9 @@ def test_clang_compiler_version(self): "1..2") def test_executable(self): + if platform.system() == 'Windows': + self.skipTest('Every file is considered executable in Windows') + python = sys.executable self.assertTrue(os.path.isabs(argtype.executable(python))) diff --git a/utils/swift_build_support/tests/test_cmake.py b/utils/swift_build_support/tests/test_cmake.py index dae9828e9a39e..1fa3ebc75c1a5 100644 --- a/utils/swift_build_support/tests/test_cmake.py +++ b/utils/swift_build_support/tests/test_cmake.py @@ -9,6 +9,7 @@ # See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors import os +import platform import unittest from argparse import Namespace @@ -22,8 +23,11 @@ class CMakeTestCase(unittest.TestCase): def mock_distcc_path(self): """Return a path string of mock distcc executable """ - return os.path.join(os.path.dirname(__file__), - 'mock-distcc') + if platform.system() == 'Windows': + executable = 'mock-distcc.cmd' + else: + executable = 'mock-distcc' + return os.path.join(os.path.dirname(__file__), executable) def default_args(self): """Return new args object with default values diff --git a/utils/swift_build_support/tests/test_migration.py b/utils/swift_build_support/tests/test_migration.py index 4535306d197eb..87918e7c2eba4 100644 --- a/utils/swift_build_support/tests/test_migration.py +++ b/utils/swift_build_support/tests/test_migration.py @@ -10,6 +10,7 @@ import argparse import os +import platform import unittest from swift_build_support import migration @@ -54,6 +55,10 @@ def test_no_unknown_args(self): build_script_impl_args=[])) def test_check_impl_args(self): + if platform.system() == 'Windows': + self.skipTest("build-script-impl cannot run in Windows") + return + # Assuming file locations: # utils/swift_build_support/tests/test_migration.py # utils/build-script-impl diff --git a/utils/swift_build_support/tests/test_shell.py b/utils/swift_build_support/tests/test_shell.py index eb11a5da9cae9..431affba2ec81 100644 --- a/utils/swift_build_support/tests/test_shell.py +++ b/utils/swift_build_support/tests/test_shell.py @@ -11,6 +11,7 @@ import os import os.path +import platform import shutil import sys import tempfile @@ -61,7 +62,8 @@ def test_call(self): self.assertEqual(self.stdout.getvalue(), "") self.assertEqual(self.stderr.getvalue(), '''\ + cp {foo_file} {bar_file} -'''.format(foo_file=foo_file, bar_file=bar_file)) +'''.format(foo_file=self._platform_quote(foo_file), + bar_file=self._platform_quote(bar_file))) def test_capture(self): self.assertEqual(shell.capture(["echo", "hi"]), "hi\n") @@ -97,7 +99,7 @@ def test_rmtree(self): self.assertEqual(self.stderr.getvalue(), '''\ + mkdir -p {path} + rm -rf {path} -'''.format(path=path)) +'''.format(path=self._platform_quote(path))) def test_pushd(self): shell.dry_run = False @@ -138,7 +140,7 @@ def test_pushd(self): + pushd {tmpdir} + rm -rf foo + popd -'''.format(tmpdir=self.tmpdir)) +'''.format(tmpdir=self._platform_quote(self.tmpdir))) def test_dry_run(self): shell.dry_run = True @@ -167,6 +169,13 @@ def test_dry_run(self): + touch testfile + popd + rm -rf {tmpdir} -'''.format(foobar_dir=foobar_dir, tmpdir=self.tmpdir)) +'''.format(foobar_dir=self._platform_quote(foobar_dir), + tmpdir=self._platform_quote(self.tmpdir))) self.assertEqual(self.stderr.getvalue(), "") self.dry_run = False + + def _platform_quote(self, path): + if platform.system() == 'Windows': + return "'{}'".format(path) + else: + return path diff --git a/utils/swift_build_support/tests/test_tar.py b/utils/swift_build_support/tests/test_tar.py index 308ad8e3f8fd6..290a4179e4c78 100644 --- a/utils/swift_build_support/tests/test_tar.py +++ b/utils/swift_build_support/tests/test_tar.py @@ -36,24 +36,37 @@ def tearDown(self): def test_tar_this_file_succeeds(self): # `tar` complains about absolute paths, so use a relative path here. - source = os.path.relpath(__file__) + if platform.system() != 'Windows': + source = os.path.relpath(__file__) + else: + # Windows can use absolute paths, specially because the relative + # path might not exist because the file and the current directory + # might be in different drives. + source = __file__ _, destination = tempfile.mkstemp() tar(source=source, destination=destination) - if platform.system() == "Darwin": + if platform.system() == "Darwin" or platform.system() == 'Windows': expect = "+ tar -c -z -f {dest} {source}\n" else: expect = "+ tar -c -z -f {dest} --owner=0 --group=0 {source}\n" self.assertEqual(self.stdout.getvalue(), "") self.assertEqual(self.stderr.getvalue(), - expect.format(dest=destination, source=source)) + expect.format(dest=self._platform_quote(destination), + source=self._platform_quote(source))) def test_tar_nonexistent_file_raises(self): with self.assertRaises(SystemExit): tar(source='/path/to/something/that/surely/doesnt/exist', destination='/another/path/that/shouldnt/exist') + def _platform_quote(self, path): + if platform.system() == 'Windows': + return "'{}'".format(path) + else: + return path + if __name__ == '__main__': unittest.main() diff --git a/utils/swift_build_support/tests/test_toolchain.py b/utils/swift_build_support/tests/test_toolchain.py index 3269959c34352..4e34428bc745f 100644 --- a/utils/swift_build_support/tests/test_toolchain.py +++ b/utils/swift_build_support/tests/test_toolchain.py @@ -10,6 +10,7 @@ # See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors import os +import platform import unittest from swift_build_support import toolchain @@ -31,10 +32,10 @@ def test_clang_tools(self): self.assertTrue( os.path.isabs(tc.cc) and - os.path.basename(tc.cc).startswith('clang')) + os.path.basename(tc.cc).startswith(self._platform_cc_name())) self.assertTrue( os.path.isabs(tc.cxx) and - os.path.basename(tc.cxx).startswith('clang++')) + os.path.basename(tc.cxx).startswith(self._platform_cxx_name())) def test_llvm_tools(self): tc = host_toolchain() @@ -86,8 +87,8 @@ def test_tools_suffix_match(self): tc = host_toolchain() # CC and CXX must have consistent suffix - cc_suffix = get_suffix(tc.cc, 'clang') - cxx_suffix = get_suffix(tc.cxx, 'clang++') + cc_suffix = get_suffix(tc.cc, self._platform_cc_name()) + cxx_suffix = get_suffix(tc.cxx, self._platform_cxx_name()) self.assertEqual(cc_suffix, cxx_suffix) def test_tools_llvm_suffix(self): @@ -104,7 +105,7 @@ def test_tools_llvm_suffix(self): self.assertEqual(profdata_suffix, cov_suffix) # If we have suffixed clang, llvm tools must have the same suffix. - cc_suffix = get_suffix(tc.cc, 'clang') + cc_suffix = get_suffix(tc.cc, self._platform_cc_name()) if cc_suffix != '': if cov_suffix is not None: self.assertEqual(cc_suffix, cov_suffix) @@ -119,6 +120,18 @@ def test_toolchain_instances(self): toolchain.FreeBSD() toolchain.Cygwin() + def _platform_cc_name(self): + if platform.system() == 'Windows': + return 'clang-cl' + else: + return 'clang' + + def _platform_cxx_name(self): + if platform.system() == 'Windows': + return 'clang-cl' + else: + return 'clang++' + if __name__ == '__main__': unittest.main() From 3f9ae9111b3e2f890b7f753750e253d2e42d7a03 Mon Sep 17 00:00:00 2001 From: Mishal Shah Date: Thu, 6 Jun 2019 11:39:00 -0700 Subject: [PATCH 058/112] Update the Xcode version required for master branch to Xcode 11 beta --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 62e26b5ae2980..76f2490215d66 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Please make sure you use Python 2.x. Python 3.x is not supported currently. #### macOS -To build for macOS, you need [Xcode 10.2 beta](https://developer.apple.com/xcode/downloads/). +To build for macOS, you need [Xcode 11 beta](https://developer.apple.com/xcode/downloads/). 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. From c1087b9ab7a0d3610e89af84d408919bcc9cbc70 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 6 Jun 2019 11:56:49 -0700 Subject: [PATCH 059/112] [ConstraintSystem] Remove boolean flags from openGeneric/openFunctionType --- lib/Sema/CSRanking.cpp | 10 +++----- lib/Sema/CSSimplify.cpp | 3 +-- lib/Sema/ConstraintSystem.cpp | 43 +++++++++++++++++------------------ lib/Sema/ConstraintSystem.h | 11 +-------- 4 files changed, 26 insertions(+), 41 deletions(-) diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp index 41ebb81b970ab..d0e57049170d3 100644 --- a/lib/Sema/CSRanking.cpp +++ b/lib/Sema/CSRanking.cpp @@ -341,9 +341,7 @@ static bool isProtocolExtensionAsSpecializedAs(TypeChecker &tc, // the second protocol extension. ConstraintSystem cs(tc, dc1, None); OpenedTypeMap replacements; - cs.openGeneric(dc2, sig2, - /*skipProtocolSelfConstraint=*/false, - ConstraintLocatorBuilder(nullptr), replacements); + cs.openGeneric(dc2, sig2, ConstraintLocatorBuilder(nullptr), replacements); // Bind the 'Self' type from the first extension to the type parameter from // opening 'Self' of the second extension. @@ -511,13 +509,11 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc, OpenedTypeMap &replacements, ConstraintLocator *locator) -> Type { if (auto *funcType = type->getAs()) { - return cs.openFunctionType(funcType, locator, replacements, outerDC, - /*skipProtocolSelfConstraint=*/false); + return cs.openFunctionType(funcType, locator, replacements, outerDC); } cs.openGeneric(outerDC, innerDC->getGenericSignatureOfContext(), - /*skipProtocolSelfConstraint=*/false, locator, - replacements); + locator, replacements); return cs.openType(type, replacements); }; diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index fd459a73aac16..6158de36f6496 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -4883,8 +4883,7 @@ ConstraintSystem::simplifyOpaqueUnderlyingTypeConstraint(Type type1, Type type2, // corresponding to the underlying type should be the constraints on the // underlying return type. OpenedTypeMap replacements; - openGeneric(DC, opaque2->getBoundSignature(), - /*skip self*/ false, locator, replacements); + openGeneric(DC, opaque2->getBoundSignature(), locator, replacements); auto underlyingTyVar = openType(opaque2->getInterfaceType(), replacements); diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 2c8c93cff0516..45c8f2e68c84c 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -466,7 +466,7 @@ Type ConstraintSystem::openUnboundGenericType(UnboundGenericType *unbound, // Open up the generic type. openGeneric(unboundDecl->getDeclContext(), unboundDecl->getGenericSignature(), - /*skipProtocolSelfConstraint=*/false, locator, replacements); + locator, replacements); if (parentTy) { auto subs = parentTy->getContextSubstitutions( @@ -633,19 +633,15 @@ FunctionType *ConstraintSystem::openFunctionType( AnyFunctionType *funcType, ConstraintLocatorBuilder locator, OpenedTypeMap &replacements, - DeclContext *outerDC, - bool skipProtocolSelfConstraint, - bool skipGenericRequirements) { + DeclContext *outerDC) { if (auto *genericFn = funcType->getAs()) { auto *signature = genericFn->getGenericSignature(); openGenericParameters(outerDC, signature, replacements, locator); - if (!skipGenericRequirements) { - openGenericRequirements( - outerDC, signature, skipProtocolSelfConstraint, locator, - [&](Type type) -> Type { return openType(type, replacements); }); - } + openGenericRequirements( + outerDC, signature, /*skipProtocolSelfConstraint=*/false, locator, + [&](Type type) -> Type { return openType(type, replacements); }); funcType = genericFn->substGenericArgs( [&](Type type) { return openType(type, replacements); }); @@ -914,11 +910,9 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, OpenedTypeMap replacements; - auto openedType = openFunctionType( - func->getInterfaceType()->castTo(), - locator, replacements, - func->getDeclContext(), - /*skipProtocolSelfConstraint=*/false); + auto openedType = + openFunctionType(func->getInterfaceType()->castTo(), + locator, replacements, func->getDeclContext()); // If we opened up any type variables, record the replacements. recordOpenedTypes(locator, replacements); @@ -951,8 +945,7 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value, /*isCurriedInstanceReference=*/false, functionRefKind); auto openedType = openFunctionType(funcType, locator, replacements, - funcDecl->getDeclContext(), - /*skipProtocolSelfConstraint=*/false) + funcDecl->getDeclContext()) ->removeArgumentLabels(numLabelsToRemove); // If we opened up any type variables, record the replacements. @@ -1079,7 +1072,6 @@ static void bindArchetypesFromContext( void ConstraintSystem::openGeneric( DeclContext *outerDC, GenericSignature *sig, - bool skipProtocolSelfConstraint, ConstraintLocatorBuilder locator, OpenedTypeMap &replacements) { if (sig == nullptr) @@ -1089,7 +1081,7 @@ void ConstraintSystem::openGeneric( // Add the requirements as constraints. openGenericRequirements( - outerDC, sig, skipProtocolSelfConstraint, locator, + outerDC, sig, /*skipProtocolSelfConstraint=*/false, locator, [&](Type type) { return openType(type, replacements); }); } @@ -1304,10 +1296,17 @@ ConstraintSystem::getTypeOfMemberReference( // While opening member function type, let's delay opening requirements // to allow contextual types to affect the situation. - openedType = openFunctionType(funcType, locator, replacements, outerDC, - /*skipProtocolSelfConstraint=*/true, - /*skipGenericRequirements=*/true) - ->removeArgumentLabels(numRemovedArgumentLabels); + if (auto *genericFn = funcType->getAs()) { + openGenericParameters(outerDC, genericFn->getGenericSignature(), + replacements, locator); + + openedType = genericFn->substGenericArgs( + [&](Type type) { return openType(type, replacements); }); + } else { + openedType = funcType; + } + + openedType = openedType->removeArgumentLabels(numRemovedArgumentLabels); if (!outerDC->getSelfProtocolDecl()) { // Class methods returning Self as well as constructors get the diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index bf15ff05ac6af..393366d01c8f6 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -2371,25 +2371,16 @@ class ConstraintSystem { /// /// \param outerDC The generic context containing the declaration. /// - /// \param skipProtocolSelfConstraint Whether to skip the constraint on a - /// protocol's 'Self' type. - /// - /// \param skipGenericRequirements Whether to skip opening generic - /// requirements asscoiated with given function type. - /// /// \returns The opened type, or \c type if there are no archetypes in it. FunctionType *openFunctionType(AnyFunctionType *funcType, ConstraintLocatorBuilder locator, OpenedTypeMap &replacements, - DeclContext *outerDC, - bool skipProtocolSelfConstraint, - bool skipGenericRequirements = false); + DeclContext *outerDC); /// Open the generic parameter list and its requirements, /// creating type variables for each of the type parameters. void openGeneric(DeclContext *outerDC, GenericSignature *signature, - bool skipProtocolSelfConstraint, ConstraintLocatorBuilder locator, OpenedTypeMap &replacements); From 19a1e2c07d4744f23093f8c9655dc9fe1effa3ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodr=C3=ADguez=20Troiti=C3=B1o?= Date: Thu, 6 Jun 2019 13:09:15 -0700 Subject: [PATCH 060/112] [windows] Fix usage of strtof/d/ld function usage. The error conditions for underflow or overflow weren't being checked, which caused problems in some tests. --- stdlib/public/stubs/Stubs.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/stdlib/public/stubs/Stubs.cpp b/stdlib/public/stubs/Stubs.cpp index 1e6f5fb429420..55bada6a1db92 100644 --- a/stdlib/public/stubs/Stubs.cpp +++ b/stdlib/public/stubs/Stubs.cpp @@ -393,7 +393,12 @@ _swift_stdlib_strtoX_clocale_impl(const char *str, float *result) { } char *end; + _set_errno(0); *result = _strtof_l(str, &end, getCLocale()); + if (*result == HUGE_VALF || *result == -HUGE_VALF || *result == 0.0 || *result == -0.0) { + if (errno == ERANGE) + end = nullptr; + } return end; } @@ -406,7 +411,12 @@ _swift_stdlib_strtoX_clocale_impl(const char *str, double *result) { } char *end; + _set_errno(0); *result = _strtod_l(str, &end, getCLocale()); + if (*result == HUGE_VAL || *result == -HUGE_VAL || *result == 0.0 || *result == -0.0) { + if (errno == ERANGE) + end = nullptr; + } return end; } @@ -419,7 +429,12 @@ _swift_stdlib_strtoX_clocale_impl(const char *str, long double *res } char *end; + _set_errno(0); *result = _strtod_l(str, &end, getCLocale()); + if (*result == HUGE_VALL || *result == -HUGE_VALL || *result == 0.0 || *result == -0.0) { + if (errno == ERANGE) + end = nullptr; + } return end; } #endif From 9e8c0d0abf784373abcd8feb3bf3a92d34411e10 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Thu, 6 Jun 2019 08:23:45 -0700 Subject: [PATCH 061/112] Add a update-checkout scheme for people to test out stdlib_standalone. --- .../update-checkout-config.json | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/utils/update_checkout/update-checkout-config.json b/utils/update_checkout/update-checkout-config.json index ee2ab258ff208..f4d03895f01f8 100644 --- a/utils/update_checkout/update-checkout-config.json +++ b/utils/update_checkout/update-checkout-config.json @@ -325,27 +325,27 @@ "stdlib_standalone" : { "aliases": ["stdlib_standalone"], "repos": { - "llvm": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "clang": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "compiler-rt": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "llvm": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "clang": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "compiler-rt": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", "swift": "stdlib_standalone", - "lldb": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "lldb": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", "cmark": "master", - "llbuild": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swiftpm": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swift-syntax": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swift-stress-tester": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swift-corelibs-xctest": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swift-corelibs-foundation": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swift-corelibs-libdispatch": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swift-integration-tests": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swift-xcode-playground-support": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "llbuild": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swiftpm": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift-syntax": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift-stress-tester": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift-corelibs-xctest": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift-corelibs-foundation": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift-corelibs-libdispatch": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift-integration-tests": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "swift-xcode-playground-support": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", "ninja": "release", "icu": "release-61-1", - "clang-tools-extra": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "libcxx": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "indexstore-db": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "sourcekit-lsp": "tags/swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a" + "clang-tools-extra": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "libcxx": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "indexstore-db": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "sourcekit-lsp": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a" } } } From 9706668e0abce9220509c3e5a8b583e3ebde9867 Mon Sep 17 00:00:00 2001 From: Pavol Vaskovic Date: Fri, 7 Jun 2019 06:14:40 +0200 Subject: [PATCH 062/112] [benchmark] RandomIntegersLCG futureproofed Allow for future change in algorithm that generates random integers in range. --- benchmark/single-source/RandomValues.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/single-source/RandomValues.swift b/benchmark/single-source/RandomValues.swift index 34eaf83a36b17..6a5a5b4be2075 100644 --- a/benchmark/single-source/RandomValues.swift +++ b/benchmark/single-source/RandomValues.swift @@ -63,7 +63,7 @@ public func run_RandomIntegersLCG(_ N: Int) { for _ in 0 ..< 100_000 { x &+= Int64.random(in: 0...10_000, using: &generator) } - CheckResults(x == 498214315) + blackHole(x) } } From 36b2625c60888c162e751936b3adfee013fe1aa1 Mon Sep 17 00:00:00 2001 From: Sergej Jaskiewicz Date: Fri, 7 Jun 2019 12:09:55 +0300 Subject: [PATCH 063/112] [Parse] Add missing const qualifier to getSplitTokens() --- include/swift/Parse/Parser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index 3251f7dd7d3da..4622c9cd36b06 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -183,7 +183,7 @@ class Parser { bool allowTopLevelCode() const; - const std::vector &getSplitTokens() { return SplitTokens; } + const std::vector &getSplitTokens() const { return SplitTokens; } void markSplitToken(tok Kind, StringRef Txt); From 26918a816e91044ba721bb65a8095bc463d31c73 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Fri, 7 Jun 2019 07:37:24 -0700 Subject: [PATCH 064/112] [update-checkout] Update stdlib_standalone preset for the snapshot released last night. --- .../update-checkout-config.json | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/utils/update_checkout/update-checkout-config.json b/utils/update_checkout/update-checkout-config.json index f4d03895f01f8..e8b29a5c409e3 100644 --- a/utils/update_checkout/update-checkout-config.json +++ b/utils/update_checkout/update-checkout-config.json @@ -325,27 +325,27 @@ "stdlib_standalone" : { "aliases": ["stdlib_standalone"], "repos": { - "llvm": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "clang": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "compiler-rt": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "llvm": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", + "clang": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", + "compiler-rt": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", "swift": "stdlib_standalone", - "lldb": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "lldb": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", "cmark": "master", - "llbuild": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swiftpm": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swift-syntax": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swift-stress-tester": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swift-corelibs-xctest": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swift-corelibs-foundation": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swift-corelibs-libdispatch": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swift-integration-tests": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "swift-xcode-playground-support": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", + "llbuild": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", + "swiftpm": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", + "swift-syntax": "master", + "swift-stress-tester": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", + "swift-corelibs-xctest": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", + "swift-corelibs-foundation": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", + "swift-corelibs-libdispatch": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", + "swift-integration-tests": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", + "swift-xcode-playground-support": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", "ninja": "release", "icu": "release-61-1", - "clang-tools-extra": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "libcxx": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "indexstore-db": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a", - "sourcekit-lsp": "swift-DEVELOPMENT-SNAPSHOT-2019-06-02-a" + "clang-tools-extra": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", + "libcxx": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", + "indexstore-db": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a", + "sourcekit-lsp": "swift-DEVELOPMENT-SNAPSHOT-2019-06-06-a" } } } From aef830d4a4ceadfaac84771b8805d573c5016201 Mon Sep 17 00:00:00 2001 From: Davide Italiano Date: Fri, 7 Jun 2019 11:14:33 -0700 Subject: [PATCH 065/112] [GenEnum] Fix getBitMaskForNoPayloadElements. Based on a patch from Joe Groff. This is only triggered in lldb so I'll add a test there. --- lib/IRGen/GenEnum.cpp | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp index cfcb251c67228..83319f57df9ee 100644 --- a/lib/IRGen/GenEnum.cpp +++ b/lib/IRGen/GenEnum.cpp @@ -3224,11 +3224,31 @@ namespace { getBitMaskForNoPayloadElements() const override { // Use the extra inhabitants mask from the payload. auto &payloadTI = getFixedPayloadTypeInfo(); - ClusteredBitVector extraInhabitantsMask; + APInt extraInhabitantsMaskInt; + + // If we used extra inhabitants from the payload, then we can use the + // payload's mask to find the bits we need to test. + auto extraDiscriminatorBits = (~APInt(8, 0)); + if (payloadTI.getFixedSize().getValueInBits() != 0) + extraDiscriminatorBits = + extraDiscriminatorBits.zextOrTrunc( + payloadTI.getFixedSize().getValueInBits()); + if (getNumExtraInhabitantTagValues() > 0) { + extraInhabitantsMaskInt = payloadTI.getFixedExtraInhabitantMask(IGM); + // If we have more no-payload cases than extra inhabitants, also + // mask in up to four bytes for discriminators we generate using + // extra tag bits. + if (ExtraTagBitCount > 0) { + extraInhabitantsMaskInt |= extraDiscriminatorBits; + } + } else { + // If we only use extra tag bits, then we need that extra tag plus + // up to four bytes of discriminator. + extraInhabitantsMaskInt = extraDiscriminatorBits; + } + auto extraInhabitantsMask + = getBitVectorFromAPInt(extraInhabitantsMaskInt); - if (!payloadTI.isKnownEmpty(ResilienceExpansion::Maximal)) - extraInhabitantsMask = - getBitVectorFromAPInt(payloadTI.getFixedExtraInhabitantMask(IGM)); // Extend to include the extra tag bits, which are always significant. unsigned totalSize = cast(TI)->getFixedSize().getValueInBits(); From 851e67592511b9dd41baf896ebf555017c9b3aa3 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Fri, 7 Jun 2019 12:29:20 -0700 Subject: [PATCH 066/112] [standalone_stdlib] Do not test cmark when building standalone. --- utils/build-presets.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/build-presets.ini b/utils/build-presets.ini index 87954fe809c05..d3e895fcdc551 100644 --- a/utils/build-presets.ini +++ b/utils/build-presets.ini @@ -2037,6 +2037,7 @@ mixin-preset=buildbot_linux skip-build-llvm skip-build-cmark skip-build-benchmarks +skip-test-cmark # Then we inject two cmake arguments that cause us not to build tools and to # assume we are working with the host compiler. From f0e3a99f97775b2c22a6b6c5708770714199eb04 Mon Sep 17 00:00:00 2001 From: Kristaps Grinbergs Date: Fri, 7 Jun 2019 14:32:42 -0700 Subject: [PATCH 067/112] [Doc] [SR-10094] Add missing documentation for SE-0237 https://bugs.swift.org/browse/SR-10094 --- stdlib/public/core/Sequence.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/stdlib/public/core/Sequence.swift b/stdlib/public/core/Sequence.swift index 931959d9d0f52..b5677c46ffc88 100644 --- a/stdlib/public/core/Sequence.swift +++ b/stdlib/public/core/Sequence.swift @@ -363,6 +363,16 @@ public protocol Sequence { initializing ptr: UnsafeMutableBufferPointer ) -> (Iterator,UnsafeMutableBufferPointer.Index) + /// Call `body(p)`, where `p` is a pointer to the collection's + /// contiguous storage. If no such storage exists, it is + /// first created. If the collection does not support an internal + /// representation in a form of contiguous storage, `body` is not + /// called and `nil` is returned. + /// + /// A `Collection` that provides its own implementation of this method + /// must also guarantee that an equivalent buffer of its `SubSequence` + /// can be generated by advancing the pointer by the distance to the + /// slice's `startIndex`. func withContiguousStorageIfAvailable( _ body: (UnsafeBufferPointer) throws -> R ) rethrows -> R? From 50f04b73a00bf1cd080458f5ca7963cff795d715 Mon Sep 17 00:00:00 2001 From: kagemiku Date: Fri, 7 Jun 2019 15:48:43 -0700 Subject: [PATCH 068/112] Improve warning message for defer_stmt_at_block_end --- include/swift/AST/DiagnosticsSema.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index daeb29c70093a..1e31672b286ef 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -3150,7 +3150,7 @@ ERROR(jump_out_of_defer,none, (StringRef)) WARNING(defer_stmt_at_block_end,none, - "'defer' statement before end of scope always executes immediately; " + "'defer' statement at end of scope always executes immediately; " "replace with 'do' statement to silence this warning", ()) ERROR(return_invalid_outside_func,none, From f79eb3b8d034a2ccd734cbd26e1c4cb6272501ad Mon Sep 17 00:00:00 2001 From: Azoy Date: Fri, 7 Jun 2019 18:06:32 -0500 Subject: [PATCH 069/112] swift_demangle: update buffer size after copying --- stdlib/public/runtime/Demangle.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp index 10270ea5212c4..f5fc0152eaed2 100644 --- a/stdlib/public/runtime/Demangle.cpp +++ b/stdlib/public/runtime/Demangle.cpp @@ -666,13 +666,14 @@ char *swift_demangle(const char *mangledName, return strdup(result.c_str()); } - // Indicate a failure if the result does not fit and will be truncated - // and set the required outputBufferSize. + // Copy into the provided buffer. + _swift_strlcpy(outputBuffer, result.c_str(), *outputBufferSize); + + // Indicate a failure if the result did not fit and was truncated + // by setting the required outputBufferSize. if (*outputBufferSize < result.length() + 1) { *outputBufferSize = result.length() + 1; } - // Copy into the provided buffer. - _swift_strlcpy(outputBuffer, result.c_str(), *outputBufferSize); return outputBuffer; } From 78802be3e0e39e74b71e6a558dabf10a2925b967 Mon Sep 17 00:00:00 2001 From: Kelly Hutchison Date: Fri, 7 Jun 2019 17:34:23 -0700 Subject: [PATCH 070/112] SR-20 Update swift --help to explain multitool support ("swift build", etc.) --- lib/Driver/Driver.cpp | 14 ++++++++++++++ test/Driver/help.swift | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 1f588596411ee..38af6800759f3 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -3059,6 +3059,20 @@ void Driver::printHelp(bool ShowHidden) const { getOpts().PrintHelp(llvm::outs(), Name.c_str(), "Swift compiler", IncludedFlagsBitmask, ExcludedFlagsBitmask, /*ShowAllAliases*/false); + + // These strings match the descriptions found in the corresponding swiftpm + // help pages + if (driverKind == DriverKind::Interactive) { + llvm::outs() << "\nSEE ALSO - PACKAGE MANAGER COMMANDS: \n" + "\t\"swift build\" Build sources into binary products \n" + "\t\"swift package\" Perform operations on Swift packages \n" + "\t\"swift run\" Build and run an executable product \n" + "\t\"swift test\" Build and run tests \n"; + } else { + llvm::outs() << "\nSEE ALSO: swift build, swift run, swift package, " + "swift test \n"; + } + } bool OutputInfo::mightHaveExplicitPrimaryInputs( diff --git a/test/Driver/help.swift b/test/Driver/help.swift index 9fb89d421aefb..0e1142f09a881 100644 --- a/test/Driver/help.swift +++ b/test/Driver/help.swift @@ -21,3 +21,8 @@ // Options marked "help-hidden" should not show up here. // NEGATIVE-NOT: -parse-stdlib + +// CHECK-SWIFTC: SEE ALSO: swift build, swift run, swift package, swift test +// NEGATIVE-SWIFTC-NOT: SEE ALSO - PACKAGE MANAGER COMMANDS: +// CHECK-SWIFT: SEE ALSO - PACKAGE MANAGER COMMANDS: +// NEGATIVE-SWIFT-NOT: SEE ALSO: swift build, swift run, swift package, swift test From 9eb0ebe361f9aac42361fce5f3b8cb641db85243 Mon Sep 17 00:00:00 2001 From: Ray Fix Date: Fri, 7 Jun 2019 18:03:30 -0700 Subject: [PATCH 071/112] Fix for SR-10550, Help for -target option (#25311) --- include/swift/Option/Options.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index c6f32a0d6bb32..9d67e70a6069b 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -807,7 +807,7 @@ def resource_dir : Separate<["-"], "resource-dir">, def target : Separate<["-"], "target">, Flags<[FrontendOption, ModuleWrapOption, ModuleInterfaceOption]>, - HelpText<"Generate code for the given target">; + HelpText<"Generate code for the given target , such as x86_64-apple-macos10.9">, MetaVarName<"">; def target_legacy_spelling : Joined<["--"], "target=">, Flags<[FrontendOption]>, Alias; From 07e69409daa44a2d98f79d5b7b05c0e10e28f827 Mon Sep 17 00:00:00 2001 From: Tapan Thaker Date: Fri, 7 Jun 2019 19:07:50 -0700 Subject: [PATCH 072/112] [Diagnostics] Add a fix-it for misplaced throws in function types (#25306) Adds a diagnostic error for misplaced throws in function types. For e.g: ```swift let fn: () -> throws Void // expected-error{{'throws' may only occur before '->'}} {{12-12=throws }} {{15-22=}} ``` Resolves SR-10703. --- lib/Parse/ParseType.cpp | 9 ++++++++- test/Parse/errors.swift | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp index 4575200a176dd..492dcab0985f8 100644 --- a/lib/Parse/ParseType.cpp +++ b/lib/Parse/ParseType.cpp @@ -417,8 +417,15 @@ ParserResult Parser::parseType(Diag<> MessageID, if (Tok.is(tok::arrow)) { // Handle type-function if we have an arrow. SourceLoc arrowLoc = consumeToken(); + if (Tok.is(tok::kw_throws)) { + Diag<> DiagID = diag::throws_in_wrong_position; + diagnose(Tok.getLoc(), DiagID) + .fixItInsert(arrowLoc, "throws ") + .fixItRemove(Tok.getLoc()); + throwsLoc = consumeToken(); + } ParserResult SecondHalf = - parseType(diag::expected_type_function_result); + parseType(diag::expected_type_function_result); if (SecondHalf.hasCodeCompletion()) return makeParserCodeCompletionResult(); if (SecondHalf.isNull()) diff --git a/test/Parse/errors.swift b/test/Parse/errors.swift index 54506ab17f24f..a22d1185e7152 100644 --- a/test/Parse/errors.swift +++ b/test/Parse/errors.swift @@ -125,3 +125,5 @@ func fixitThrow2() throws { throw MSV.Foo var _: (Int) throw -> Int // expected-error{{expected throwing specifier; did you mean 'throws'?}} {{16-21=throws}} } + +let fn: () -> throws Void // expected-error{{'throws' may only occur before '->'}} {{12-12=throws }} {{15-22=}} From fbba1f7c2f1ae47e9aa9bc2ca53da24c99eb051f Mon Sep 17 00:00:00 2001 From: kagemiku Date: Fri, 7 Jun 2019 23:29:14 -0700 Subject: [PATCH 073/112] Fix tests for warning messages of defer_stmt_at_block_end --- test/SILGen/statements.swift | 4 ++-- test/SILOptimizer/definite_init_diagnostics_globals.swift | 2 +- test/SILOptimizer/diagnose_unreachable.swift | 2 +- test/Sema/diag_defer_block_end.swift | 4 ++-- test/stmt/statements.swift | 6 +++--- test/stmt/yield.swift | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/SILGen/statements.swift b/test/SILGen/statements.swift index 6c2dbce25ac51..c6f76169d467d 100644 --- a/test/SILGen/statements.swift +++ b/test/SILGen/statements.swift @@ -518,7 +518,7 @@ func defer_in_closure_in_generic(_ x: T) { // CHECK-LABEL: sil private [ossa] @$s10statements017defer_in_closure_C8_genericyyxlFyycfU_ : $@convention(thin) () -> () _ = { // CHECK-LABEL: sil private [ossa] @$s10statements017defer_in_closure_C8_genericyyxlFyycfU_6$deferL_yylF : $@convention(thin) () -> () - defer { generic_callee_1(T.self) } // expected-warning {{'defer' statement before end of scope always executes immediately}}{{5-10=do}} + defer { generic_callee_1(T.self) } // expected-warning {{'defer' statement at end of scope always executes immediately}}{{5-10=do}} } } @@ -531,7 +531,7 @@ func defer_mutable(_ x: Int) { // CHECK: function_ref @$s10statements13defer_mutableyySiF6$deferL_yyF : $@convention(thin) (@inout_aliasable Int) -> () // CHECK-NOT: [[BOX]] // CHECK: destroy_value [[BOX]] - defer { _ = x } // expected-warning {{'defer' statement before end of scope always executes immediately}}{{3-8=do}} + defer { _ = x } // expected-warning {{'defer' statement at end of scope always executes immediately}}{{3-8=do}} } protocol StaticFooProtocol { static func foo() } diff --git a/test/SILOptimizer/definite_init_diagnostics_globals.swift b/test/SILOptimizer/definite_init_diagnostics_globals.swift index 7b76c30c4f93f..331f1440d6e43 100644 --- a/test/SILOptimizer/definite_init_diagnostics_globals.swift +++ b/test/SILOptimizer/definite_init_diagnostics_globals.swift @@ -21,7 +21,7 @@ defer { print(y) } // expected-error {{constant 'y' used in defer before being i // Test top-level functions. func testFunc() { // expected-error {{variable 'x' used by function definition before being initialized}} - defer { print(x) } // expected-warning {{'defer' statement before end of scope always executes immediately}}{{3-8=do}} + defer { print(x) } // expected-warning {{'defer' statement at end of scope always executes immediately}}{{3-8=do}} } // Test top-level closures. diff --git a/test/SILOptimizer/diagnose_unreachable.swift b/test/SILOptimizer/diagnose_unreachable.swift index be8260068d6eb..76fc7dea87a16 100644 --- a/test/SILOptimizer/diagnose_unreachable.swift +++ b/test/SILOptimizer/diagnose_unreachable.swift @@ -328,7 +328,7 @@ func deferTryNoReturn() throws { } func noReturnInDefer() { - defer { // expected-warning {{'defer' statement before end of scope always executes immediately}}{{3-8=do}} + defer { // expected-warning {{'defer' statement at end of scope always executes immediately}}{{3-8=do}} _ = Lisp() die() // expected-note {{a call to a never-returning function}} die() // expected-warning {{will never be executed}} diff --git a/test/Sema/diag_defer_block_end.swift b/test/Sema/diag_defer_block_end.swift index 80f9cc69a9308..354e0a2e52e9e 100644 --- a/test/Sema/diag_defer_block_end.swift +++ b/test/Sema/diag_defer_block_end.swift @@ -3,14 +3,14 @@ let x = 1 let y = 2 if (x > y) { - defer { // expected-warning {{'defer' statement before end of scope always executes immediately}}{{5-10=do}} + defer { // expected-warning {{'defer' statement at end of scope always executes immediately}}{{5-10=do}} print("not so useful defer stmt.") } } func sr7307(_ value: Bool) { let negated = !value - defer { // expected-warning {{'defer' statement before end of scope always executes immediately}}{{5-10=do}} + defer { // expected-warning {{'defer' statement at end of scope always executes immediately}}{{5-10=do}} print("negated value is {negated}") } } diff --git a/test/stmt/statements.swift b/test/stmt/statements.swift index 5abe53d5fd487..7f8deac727c9f 100644 --- a/test/stmt/statements.swift +++ b/test/stmt/statements.swift @@ -350,9 +350,9 @@ func test_defer(_ a : Int) { // Not ok. while false { defer { break } } // expected-error {{'break' cannot transfer control out of a defer statement}} - // expected-warning@-1 {{'defer' statement before end of scope always executes immediately}}{{17-22=do}} + // expected-warning@-1 {{'defer' statement at end of scope always executes immediately}}{{17-22=do}} defer { return } // expected-error {{'return' cannot transfer control out of a defer statement}} - // expected-warning@-1 {{'defer' statement before end of scope always executes immediately}}{{3-8=do}} + // expected-warning@-1 {{'defer' statement at end of scope always executes immediately}}{{3-8=do}} } class SomeTestClass { @@ -360,7 +360,7 @@ class SomeTestClass { func method() { defer { x = 97 } // self. not required here! - // expected-warning@-1 {{'defer' statement before end of scope always executes immediately}}{{5-10=do}} + // expected-warning@-1 {{'defer' statement at end of scope always executes immediately}}{{5-10=do}} } } diff --git a/test/stmt/yield.swift b/test/stmt/yield.swift index 14a55eeddc06f..b4950e99a0f1f 100644 --- a/test/stmt/yield.swift +++ b/test/stmt/yield.swift @@ -82,7 +82,7 @@ func call_yield() { struct YieldInDefer { var property: String { _read { - defer { // expected-warning {{'defer' statement before end of scope always executes immediately}}{{7-12=do}} + defer { // expected-warning {{'defer' statement at end of scope always executes immediately}}{{7-12=do}} // FIXME: this recovery is terrible yield "" // expected-error@-1 {{expression resolves to an unused function}} From e273d0546046af357692efec0f0b30ba2d480679 Mon Sep 17 00:00:00 2001 From: Owen Voorhees Date: Sat, 25 May 2019 15:21:52 -0700 Subject: [PATCH 074/112] [Sema] Add notes to explain why Equatable/Hashable conformance couldn't be synthesized If a struct/enum cannot have Equatable/Hashable conformance automatically synthesized because a member's type is not Equatable/Hashable, add a note to the existing 'does not conform' diagnostic pointing out the type that blocked synthesis. --- include/swift/AST/DiagnosticsSema.def | 6 + .../DerivedConformanceEquatableHashable.cpp | 124 +++++++++++++++--- lib/Sema/DerivedConformances.cpp | 16 +++ lib/Sema/DerivedConformances.h | 28 ++++ lib/Sema/TypeCheckProtocol.cpp | 5 +- test/Sema/enum_conformance_synthesis.swift | 13 +- test/Sema/enum_equatable_conditional.swift | 4 +- test/Sema/struct_equatable_hashable.swift | 11 +- 8 files changed, 175 insertions(+), 32 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index c4f7ef1602c85..c484911401e72 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -2518,6 +2518,12 @@ NOTE(decodable_suggest_overriding_init_here,none, NOTE(codable_suggest_overriding_init_here,none, "did you mean to override 'init(from:)' and 'encode(to:)'?", ()) +NOTE(missing_member_type_conformance_prevents_synthesis, none, + "%select{associated value|stored property}0 type %1 does not conform to " + "protocol %2, preventing synthesized conformance " + "of %3 to %2", + (unsigned, Type, Type, Type)) + // Dynamic Self ERROR(dynamic_self_non_method,none, "%select{global|local}0 function cannot return 'Self'", (bool)) diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp index 56aa16303a8ca..62aefb68d2841 100644 --- a/lib/Sema/DerivedConformanceEquatableHashable.cpp +++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp @@ -32,15 +32,21 @@ using namespace swift; -/// Returns true if, for every element of the given enum, it either has no -/// associated values or all of them conform to a protocol. +enum NonconformingMemberKind { + AssociatedValue, + StoredProperty +}; + +/// Returns the ParamDecl for each associated value of the given enum whose type +/// does not conform to a protocol /// \p theEnum The enum whose elements and associated values should be checked. /// \p protocol The protocol being requested. -/// \return True if all associated values of all elements of the enum conform. -static bool allAssociatedValuesConformToProtocol(DeclContext *DC, - EnumDecl *theEnum, - ProtocolDecl *protocol) { +/// \return The ParamDecl of each associated value whose type does not conform. +static SmallVector +associatedValuesNotConformingToProtocol(DeclContext *DC, EnumDecl *theEnum, + ProtocolDecl *protocol) { auto lazyResolver = DC->getASTContext().getLazyResolver(); + SmallVector nonconformingAssociatedValues; for (auto elt : theEnum->getAllElements()) { if (!elt->hasInterfaceType()) lazyResolver->resolveDeclSignature(elt); @@ -53,38 +59,62 @@ static bool allAssociatedValuesConformToProtocol(DeclContext *DC, auto type = param->getInterfaceType(); if (!TypeChecker::conformsToProtocol(DC->mapTypeIntoContext(type), protocol, DC, None)) { - return false; + nonconformingAssociatedValues.push_back(param); } } } - return true; + return nonconformingAssociatedValues; } -/// Returns true if every stored property in the given struct conforms to the -/// protocol (or, vacuously, if it has no stored properties). -/// \p theStruct The struct whose stored properties should be checked. +/// Returns true if, for every element of the given enum, it either has no +/// associated values or all of them conform to a protocol. +/// \p theEnum The enum whose elements and associated values should be checked. /// \p protocol The protocol being requested. -/// \return True if all stored properties of the struct conform. -static bool allStoredPropertiesConformToProtocol(DeclContext *DC, - StructDecl *theStruct, +/// \return True if all associated values of all elements of the enum conform. +static bool allAssociatedValuesConformToProtocol(DeclContext *DC, + EnumDecl *theEnum, ProtocolDecl *protocol) { + return associatedValuesNotConformingToProtocol(DC, theEnum, protocol).empty(); +} + +/// Returns the VarDecl of each stored property in the given struct whose type +/// does not conform to a protocol. +/// \p theStruct The struct whose stored properties should be checked. +/// \p protocol The protocol being requested. +/// \return The VarDecl of each stored property whose type does not conform. +static SmallVector +storedPropertiesNotConformingToProtocol(DeclContext *DC, StructDecl *theStruct, + ProtocolDecl *protocol) { auto lazyResolver = DC->getASTContext().getLazyResolver(); auto storedProperties = - theStruct->getStoredProperties(/*skipInaccessible=*/true); + theStruct->getStoredProperties(/*skipInaccessible=*/true); + SmallVector nonconformingProperties; for (auto propertyDecl : storedProperties) { if (!propertyDecl->hasInterfaceType()) lazyResolver->resolveDeclSignature(propertyDecl); if (!propertyDecl->hasInterfaceType()) - return false; + nonconformingProperties.push_back(propertyDecl); auto type = propertyDecl->getValueInterfaceType(); - if (!TypeChecker::conformsToProtocol(DC->mapTypeIntoContext(type), - protocol, DC, None)) { - return false; + if (!TypeChecker::conformsToProtocol(DC->mapTypeIntoContext(type), protocol, + DC, None)) { + nonconformingProperties.push_back(propertyDecl); } } - return true; + return nonconformingProperties; +} + +/// Returns true if every stored property in the given struct conforms to the +/// protocol (or, vacuously, if it has no stored properties). +/// \p theStruct The struct whose stored properties should be checked. +/// \p protocol The protocol being requested. +/// \return True if all stored properties of the struct conform. +static bool allStoredPropertiesConformToProtocol(DeclContext *DC, + StructDecl *theStruct, + ProtocolDecl *protocol) { + return storedPropertiesNotConformingToProtocol(DC, theStruct, protocol) + .empty(); } /// Common preconditions for Equatable and Hashable. @@ -106,6 +136,39 @@ static bool canDeriveConformance(DeclContext *DC, return false; } +/// Diagnose failed conformance synthesis caused by a member type not conforming +/// to the same protocol +void diagnoseFailedDerivation(DeclContext *DC, NominalTypeDecl *nominal, + ProtocolDecl *protocol) { + ASTContext &ctx = DC->getASTContext(); + + if (auto *enumDecl = dyn_cast(nominal)) { + auto nonconformingAssociatedTypes = + associatedValuesNotConformingToProtocol(DC, enumDecl, protocol); + for (auto *typeToDiagnose : nonconformingAssociatedTypes) { + ctx.Diags.diagnose( + typeToDiagnose->getTypeLoc().getLoc(), + diag::missing_member_type_conformance_prevents_synthesis, + NonconformingMemberKind::AssociatedValue, + typeToDiagnose->getInterfaceType(), protocol->getDeclaredType(), + nominal->getDeclaredInterfaceType()); + } + } + + if (auto *structDecl = dyn_cast(nominal)) { + auto nonconformingStoredProperties = + storedPropertiesNotConformingToProtocol(DC, structDecl, protocol); + for (auto *propertyToDiagnose : nonconformingStoredProperties) { + ctx.Diags.diagnose( + propertyToDiagnose->getLoc(), + diag::missing_member_type_conformance_prevents_synthesis, + NonconformingMemberKind::StoredProperty, + propertyToDiagnose->getInterfaceType(), protocol->getDeclaredType(), + nominal->getDeclaredInterfaceType()); + } + } +} + /// Creates a named variable based on a prefix character and a numeric index. /// \p prefixChar The prefix character for the variable's name. /// \p index The numeric index to append to the variable's name. @@ -722,6 +785,13 @@ ValueDecl *DerivedConformance::deriveEquatable(ValueDecl *requirement) { return nullptr; } +void DerivedConformance::tryDiagnoseFailedEquatableDerivation( + DeclContext *DC, NominalTypeDecl *nominal) { + ASTContext &ctx = DC->getASTContext(); + auto *equatableProto = ctx.getProtocol(KnownProtocolKind::Equatable); + diagnoseFailedDerivation(DC, nominal, equatableProto); +} + /// Returns a new \c CallExpr representing /// /// hasher.combine(hashable) @@ -1184,6 +1254,13 @@ bool DerivedConformance::canDeriveHashable(NominalTypeDecl *type) { return true; } +void DerivedConformance::tryDiagnoseFailedHashableDerivation( + DeclContext *DC, NominalTypeDecl *nominal) { + ASTContext &ctx = DC->getASTContext(); + auto *hashableProto = ctx.getProtocol(KnownProtocolKind::Hashable); + diagnoseFailedDerivation(DC, nominal, hashableProto); +} + ValueDecl *DerivedConformance::deriveHashable(ValueDecl *requirement) { ASTContext &C = ConformanceDecl->getASTContext(); @@ -1217,6 +1294,13 @@ ValueDecl *DerivedConformance::deriveHashable(ValueDecl *requirement) { ConformanceDecl->diagnose(diag::type_does_not_conform, Nominal->getDeclaredType(), hashableProto->getDeclaredType()); + // Ideally, this would be diagnosed in + // ConformanceChecker::resolveWitnessViaLookup. That doesn't work for + // Hashable because DerivedConformance::canDeriveHashable returns true + // even if the conformance can't be derived. See the note there for + // details. + auto *dc = ConformanceDecl->getDeclContext(); + tryDiagnoseFailedHashableDerivation(dc, Nominal); return nullptr; } diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp index 5b66439ee4755..b62eebe28e707 100644 --- a/lib/Sema/DerivedConformances.cpp +++ b/lib/Sema/DerivedConformances.cpp @@ -137,6 +137,22 @@ bool DerivedConformance::derivesProtocolConformance(DeclContext *DC, return false; } +void DerivedConformance::tryDiagnoseFailedDerivation(DeclContext *DC, + NominalTypeDecl *nominal, + ProtocolDecl *protocol) { + auto knownProtocol = protocol->getKnownProtocolKind(); + if (!knownProtocol) + return; + + if (*knownProtocol == KnownProtocolKind::Equatable) { + tryDiagnoseFailedEquatableDerivation(DC, nominal); + } + + if (*knownProtocol == KnownProtocolKind::Hashable) { + tryDiagnoseFailedHashableDerivation(DC, nominal); + } +} + ValueDecl *DerivedConformance::getDerivableRequirement(TypeChecker &tc, NominalTypeDecl *nominal, ValueDecl *requirement) { diff --git a/lib/Sema/DerivedConformances.h b/lib/Sema/DerivedConformances.h index 33fa195cbc05b..e00f07dd0a228 100644 --- a/lib/Sema/DerivedConformances.h +++ b/lib/Sema/DerivedConformances.h @@ -69,6 +69,18 @@ class DerivedConformance { NominalTypeDecl *nominal, ProtocolDecl *protocol); + /// Diagnose problems, if any, preventing automatic derivation of protocol + /// requirements + /// + /// \param nominal The nominal type for which we would like to diagnose + /// derivation failures + /// + /// \param protocol The protocol with requirements we would like to diagnose + /// derivation failures for + static void tryDiagnoseFailedDerivation(DeclContext *DC, + NominalTypeDecl *nominal, + ProtocolDecl *protocol); + /// Determine the derivable requirement that would satisfy the given /// requirement, if there is one. /// @@ -128,6 +140,14 @@ class DerivedConformance { /// \returns the derived member, which will also be added to the type. ValueDecl *deriveEquatable(ValueDecl *requirement); + /// Diagnose problems, if any, preventing automatic derivation of Equatable + /// requirements + /// + /// \param nominal The nominal type for which we would like to diagnose + /// derivation failures + static void tryDiagnoseFailedEquatableDerivation(DeclContext *DC, + NominalTypeDecl *nominal); + /// Determine if a Hashable requirement can be derived for a type. /// /// This is implemented for enums without associated values or all-Hashable @@ -144,6 +164,14 @@ class DerivedConformance { /// \returns the derived member, which will also be added to the type. ValueDecl *deriveHashable(ValueDecl *requirement); + /// Diagnose problems, if any, preventing automatic derivation of Hashable + /// requirements + /// + /// \param nominal The nominal type for which we would like to diagnose + /// derivation failures + static void tryDiagnoseFailedHashableDerivation(DeclContext *DC, + NominalTypeDecl *nominal); + /// Derive a _BridgedNSError requirement for an @objc enum type. /// /// \returns the derived member, which will also be added to the type. diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 3777f578fe4de..c8119522e5437 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -3305,8 +3305,11 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) { // Save the missing requirement for later diagnosis. GlobalMissingWitnesses.insert(requirement); diagnoseOrDefer(requirement, true, - [requirement, matches](NormalProtocolConformance *conformance) { + [requirement, matches, nominal](NormalProtocolConformance *conformance) { auto dc = conformance->getDeclContext(); + auto *protocol = conformance->getProtocol(); + // Possibly diagnose reason for automatic derivation failure + DerivedConformance::tryDiagnoseFailedDerivation(dc, nominal, protocol); // Diagnose each of the matches. for (const auto &match : matches) diagnoseMatch(dc->getParentModule(), conformance, requirement, match); diff --git a/test/Sema/enum_conformance_synthesis.swift b/test/Sema/enum_conformance_synthesis.swift index fd710a702a777..ba0ef431a89a1 100644 --- a/test/Sema/enum_conformance_synthesis.swift +++ b/test/Sema/enum_conformance_synthesis.swift @@ -147,7 +147,8 @@ func enumWithHashablePayload() { // Enums with non-hashable payloads don't derive conformance. struct NotHashable {} enum EnumWithNonHashablePayload: Hashable { // expected-error 2 {{does not conform}} - case A(NotHashable) + case A(NotHashable) //expected-note {{associated value type 'NotHashable' does not conform to protocol 'Hashable', preventing synthesized conformance of 'EnumWithNonHashablePayload' to 'Hashable'}} + // expected-note@-1 {{associated value type 'NotHashable' does not conform to protocol 'Equatable', preventing synthesized conformance of 'EnumWithNonHashablePayload' to 'Equatable'}} } // Enums should be able to derive conformances based on the conformances of @@ -164,7 +165,7 @@ func genericHashable() { // But it should be an error if the generic argument doesn't have the necessary // constraints to satisfy the conditions for derivation. enum GenericNotHashable: Hashable { // expected-error 2 {{does not conform to protocol 'Hashable'}} - case A(T) + case A(T) //expected-note 2 {{associated value type 'T' does not conform to protocol 'Hashable', preventing synthesized conformance of 'GenericNotHashable' to 'Hashable'}} case B } func genericNotHashable() { @@ -228,7 +229,8 @@ extension FromOtherFile: CaseIterable {} // expected-error {{cannot be automatic // No explicit conformance and it cannot be derived. enum NotExplicitlyHashableAndCannotDerive { - case A(NotHashable) + case A(NotHashable) //expected-note {{associated value type 'NotHashable' does not conform to protocol 'Hashable', preventing synthesized conformance of 'NotExplicitlyHashableAndCannotDerive' to 'Hashable'}} + // expected-note@-1 {{associated value type 'NotHashable' does not conform to protocol 'Equatable', preventing synthesized conformance of 'NotExplicitlyHashableAndCannotDerive' to 'Equatable'}} } extension NotExplicitlyHashableAndCannotDerive : Hashable {} // expected-error 2 {{does not conform}} extension NotExplicitlyHashableAndCannotDerive : CaseIterable {} // expected-error {{does not conform}} @@ -282,7 +284,7 @@ case only([Int]) struct NotEquatable { } enum ArrayOfNotEquatables : Equatable { // expected-error{{type 'ArrayOfNotEquatables' does not conform to protocol 'Equatable'}} -case only([NotEquatable]) +case only([NotEquatable]) //expected-note {{associated value type '[NotEquatable]' does not conform to protocol 'Equatable', preventing synthesized conformance of 'ArrayOfNotEquatables' to 'Equatable'}} } // Conditional conformances should be able to be synthesized @@ -294,7 +296,8 @@ extension GenericDeriveExtension: Hashable where T: Hashable {} // Incorrectly/insufficiently conditional shouldn't work enum BadGenericDeriveExtension { - case A(T) + case A(T) //expected-note {{associated value type 'T' does not conform to protocol 'Hashable', preventing synthesized conformance of 'BadGenericDeriveExtension' to 'Hashable'}} + //expected-note@-1 {{associated value type 'T' does not conform to protocol 'Equatable', preventing synthesized conformance of 'BadGenericDeriveExtension' to 'Equatable'}} } extension BadGenericDeriveExtension: Equatable {} // expected-error@-1 {{type 'BadGenericDeriveExtension' does not conform to protocol 'Equatable'}} diff --git a/test/Sema/enum_equatable_conditional.swift b/test/Sema/enum_equatable_conditional.swift index 44c7061f93427..3d58dee1f4ad0 100644 --- a/test/Sema/enum_equatable_conditional.swift +++ b/test/Sema/enum_equatable_conditional.swift @@ -3,11 +3,11 @@ struct NotEquatable { } enum WithArrayOfNotEquatables : Equatable { // expected-error{{type 'WithArrayOfNotEquatables' does not conform to protocol 'Equatable'}} -case only([NotEquatable]) + case only([NotEquatable]) // expected-note{{associated value type '[NotEquatable]' does not conform to protocol 'Equatable', preventing synthesized conformance of 'WithArrayOfNotEquatables' to 'Equatable'}} } enum WithArrayOfNotEquatables2 : Equatable { // expected-error{{type 'WithArrayOfNotEquatables2' does not conform to protocol 'Equatable'}} -case only([T]) + case only([T]) // expected-note{{associated value type '[T]' does not conform to protocol 'Equatable', preventing synthesized conformance of 'WithArrayOfNotEquatables2' to 'Equatable'}} } diff --git a/test/Sema/struct_equatable_hashable.swift b/test/Sema/struct_equatable_hashable.swift index a5b80178815e5..a1e5a697a73cd 100644 --- a/test/Sema/struct_equatable_hashable.swift +++ b/test/Sema/struct_equatable_hashable.swift @@ -121,7 +121,8 @@ func structWithoutExplicitConformance() { // Structs with non-hashable/equatable stored properties don't derive conformance. struct NotHashable {} struct StructWithNonHashablePayload: Hashable { // expected-error 2 {{does not conform}} - let a: NotHashable + let a: NotHashable // expected-note {{stored property type 'NotHashable' does not conform to protocol 'Hashable', preventing synthesized conformance of 'StructWithNonHashablePayload' to 'Hashable'}} + // expected-note@-1 {{stored property type 'NotHashable' does not conform to protocol 'Equatable', preventing synthesized conformance of 'StructWithNonHashablePayload' to 'Equatable'}} } // ...but computed properties and static properties are not considered. @@ -151,7 +152,7 @@ func genericHashable() { // But it should be an error if the generic argument doesn't have the necessary // constraints to satisfy the conditions for derivation. struct GenericNotHashable: Hashable { // expected-error 2 {{does not conform to protocol 'Hashable'}} - let value: T + let value: T // expected-note 2 {{stored property type 'T' does not conform to protocol 'Hashable', preventing synthesized conformance of 'GenericNotHashable' to 'Hashable'}} } func genericNotHashable() { if GenericNotHashable(value: "a") == GenericNotHashable(value: "b") { } @@ -178,7 +179,8 @@ extension StructConformsAndImplementsInExtension : Equatable { // No explicit conformance and it cannot be derived. struct NotExplicitlyHashableAndCannotDerive { - let v: NotHashable + let v: NotHashable // expected-note {{stored property type 'NotHashable' does not conform to protocol 'Hashable', preventing synthesized conformance of 'NotExplicitlyHashableAndCannotDerive' to 'Hashable'}} + // expected-note@-1 {{stored property type 'NotHashable' does not conform to protocol 'Equatable', preventing synthesized conformance of 'NotExplicitlyHashableAndCannotDerive' to 'Equatable'}} } extension NotExplicitlyHashableAndCannotDerive : Hashable {} // expected-error 2 {{does not conform}} @@ -233,7 +235,8 @@ extension GenericDeriveExtension: Hashable where T: Hashable {} // Incorrectly/insufficiently conditional shouldn't work struct BadGenericDeriveExtension { - let value: T + let value: T // expected-note {{stored property type 'T' does not conform to protocol 'Hashable', preventing synthesized conformance of 'BadGenericDeriveExtension' to 'Hashable'}} +// expected-note@-1 {{stored property type 'T' does not conform to protocol 'Equatable', preventing synthesized conformance of 'BadGenericDeriveExtension' to 'Equatable'}} } extension BadGenericDeriveExtension: Equatable {} // expected-error@-1 {{type 'BadGenericDeriveExtension' does not conform to protocol 'Equatable'}} From 9bbb85323a41efec912c24d7586f5b7038726971 Mon Sep 17 00:00:00 2001 From: Azoy Date: Sun, 9 Jun 2019 13:54:10 -0500 Subject: [PATCH 075/112] add demangle truncate test --- test/stdlib/Runtime.swift.gyb | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/stdlib/Runtime.swift.gyb b/test/stdlib/Runtime.swift.gyb index d56899f6c087f..be95e620ee958 100644 --- a/test/stdlib/Runtime.swift.gyb +++ b/test/stdlib/Runtime.swift.gyb @@ -375,6 +375,37 @@ Runtime.test("demangleName") { expectEqual("Foobar", _stdlib_demangleName("$s13__lldb_expr_46FoobarCD")) } +Runtime.test("demangleTruncate") { + // Swift.Int requires 10 bytes to be fully demangled. + let buffer = UnsafeMutableBufferPointer.allocate(capacity: 10) + + defer { buffer.deallocate() } + + // Set last byte to a custom number, that way when we call swift_demangle + // the last byte should be unchanged rather than it being set to 0. + buffer[buffer.count - 1] = 16 + + // Only give 9 bytes though to exercise that swift_demangle doesn't write past + // the buffer. + var bufferSize = UInt(buffer.count - 1) + + let mangled = "$sSi" + + mangled.utf8CString.withUnsafeBufferPointer { + _ = _stdlib_demangleImpl( + mangledName: $0.baseAddress, + mangledNameLength: UInt($0.count - 1), + outputBuffer: buffer.baseAddress, + outputBufferSize: &bufferSize, + flags: 0 + ) + } + + expectEqual(String(cString: buffer.baseAddress!), "Swift.In") + expectEqual(bufferSize, 10) + expectEqual(buffer[buffer.count - 1], 16) +} + % for optionality in ['', '?']: Runtime.test("_stdlib_atomicCompareExchangeStrongPtr") { typealias IntPtr = UnsafeMutablePointer From d504f722c4e8ef1e786e9c8f0be048c613d2f62c Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Sun, 9 Jun 2019 14:46:43 -0700 Subject: [PATCH 076/112] test: simplify Windows configuration, categorise (NFC) Simplify the Windows MSVC runtime library flag calculation. Categorise the Darwin, android, Windows options. --- test/lit.site.cfg.in | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index 493fb5b20495e..6c6352e31c781 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -27,26 +27,28 @@ config.variant_triple = "@VARIANT_TRIPLE@" config.variant_sdk = "@VARIANT_SDK@" config.variant_suffix = "@VARIANT_SUFFIX@" config.swiftlib_dir = "@LIT_SWIFTLIB_DIR@" -config.swift_stdlib_msvc_runtime = None -if "@SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY@" == "MultiThreaded": - config.swift_stdlib_msvc_runtime = 'MT' -elif "@SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY@" == "MultiThreadedDebug": - config.swift_stdlib_msvc_runtime = 'MTd' -elif "@SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY@" == "MultiThreadedDLL": - config.swift_stdlib_msvc_runtime = 'MD' -elif "@SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY@" == "MultiThreadedDebugDLL": - config.swift_stdlib_msvc_runtime = 'MDd' -else: - assert(False) - config.swift_test_results_dir = \ lit_config.params.get("swift_test_results_dir", "@SWIFT_TEST_RESULTS_DIR@") + +config.coverage_mode = "@SWIFT_ANALYZE_CODE_COVERAGE@" +config.lldb_build_root = "@LLDB_BUILD_DIR@" + +# --- Darwin --- config.darwin_xcrun_toolchain = "@SWIFT_DARWIN_XCRUN_TOOLCHAIN@" + +# --- android --- config.android_ndk_path = "@SWIFT_ANDROID_NDK_PATH@" config.android_ndk_gcc_version = "@SWIFT_ANDROID_NDK_GCC_VERSION@" -config.coverage_mode = "@SWIFT_ANALYZE_CODE_COVERAGE@" -config.lldb_build_root = "@LLDB_BUILD_DIR@" +# --- Windows --- +msvc_runtime_flags = { + 'MultiThreaded': 'MT', + 'MultiThreadedDebug': 'MTd', + 'MultiThreadedDLL': 'MD', + 'MultiThreadedDebugDLL': 'MDd', +} +config.swift_stdlib_msvc_runtime = \ + msvc_runtime_flags["@SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY@"] # Please remember to handle empty strings and/or unset variables correctly. From 866f316e076b28c62caeb0e29460d18ddb220b79 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sat, 1 Jun 2019 01:00:16 -0400 Subject: [PATCH 077/112] SILOptimizer: Simplify dead method elimination We used to look at the vtable entry's linkage to determine if the vtable entry was dead, in case the vtable entry linkage was more visible than the method being overridden. This hack is no longer needed now that a method override more visible than its base introduces a new vtable entry. --- .../IPO/DeadFunctionElimination.cpp | 7 ++----- .../alive_method_with_thunk.swift | 20 +++++++++++-------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp index 56fa7718a3b32..a533cc5f7640e 100644 --- a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp +++ b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp @@ -535,13 +535,10 @@ class DeadFunctionElimination : FunctionLivenessComputation { SILFunction *F = entry.Implementation; auto *fd = getBase(cast(entry.Method.getDecl())); - if (// A conservative approach: if any of the overridden functions is - // visible externally, we mark the whole method as alive. - isPossiblyUsedExternally(entry.Linkage, Module->isWholeModule()) - // We also have to check the method declaration's access level. + if (// We also have to check the method declaration's access level. // Needed if it's a public base method declared in another // compilation unit (for this we have no SILFunction). - || isVisibleExternally(fd) + isVisibleExternally(fd) // Declarations are always accessible externally, so they are alive. || !F->isDefinition()) { MethodInfo *mi = getMethodInfo(fd, /*isWitnessTable*/ false); diff --git a/test/SILOptimizer/alive_method_with_thunk.swift b/test/SILOptimizer/alive_method_with_thunk.swift index 47b42dfd856ef..61209174ebcc7 100644 --- a/test/SILOptimizer/alive_method_with_thunk.swift +++ b/test/SILOptimizer/alive_method_with_thunk.swift @@ -7,18 +7,22 @@ public class BaseClass { } public class DerivedClass: BaseClass { - - // Don't eliminate this public method, which is called via a thunk + // This method is more visible than its override, so it gets a new + // vtable entry, and the base class vtable entry is replaced with a + // thunk that re-dispatches to the derived method. + // + // The base class method is dead, but the derived method is not. public override func doSomething(_ value: Double) -> Int { return 1 } } -// CHECK: sil_vtable BaseClass { -// CHECK: #BaseClass.doSomething!1: (BaseClass) -> (T) -> Int : @$s23alive_method_with_thunk9BaseClassC11doSomethingySixF // BaseClass.doSomething(_:) -// CHECK: } +// CHECK-LABEL: sil_vtable BaseClass { +// CHECK-NEXT: #BaseClass.deinit!deallocator.1: @$s23alive_method_with_thunk9BaseClassCfD +// CHECK-NEXT: } -// CHECK: sil_vtable DerivedClass { -// CHECK: #BaseClass.doSomething!1: (BaseClass) -> (T) -> Int : public @$s23alive_method_with_thunk12DerivedClassC11doSomethingySiSdFAA04BaseF0CADySixFTV [override] // vtable thunk for BaseClass.doSomething(_:) dispatching to DerivedClass.doSomething(_:) -// CHECK: } +// CHECK-LABEL: sil_vtable DerivedClass { +// CHECK-NEXT: #DerivedClass.doSomething!1: (DerivedClass) -> (Double) -> Int : @$s23alive_method_with_thunk12DerivedClassC11doSomethingySiSdF +// CHECK-NEXT: #DerivedClass.deinit!deallocator.1: @$s23alive_method_with_thunk12DerivedClassCfD +// CHECK-NEXT: } From f681cbe264b5ee18a6601a809ddca6f6f8410be3 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sat, 1 Jun 2019 01:26:20 -0400 Subject: [PATCH 078/112] SIL: Remove SILVTable::Entry::Linkage This field would store the linkage of the original method, if it was distinct from the linkage of a vtable thunk. It is no longer used. --- include/swift/SIL/SILVTable.h | 31 +++----- include/swift/Serialization/ModuleFormat.h | 2 +- lib/ParseSIL/ParseSIL.cpp | 6 +- lib/SIL/SILPrinter.cpp | 4 -- lib/SILGen/SILGenType.cpp | 21 +++--- lib/Serialization/DeserializeSIL.cpp | 13 +--- lib/Serialization/SILFormat.h | 1 - lib/Serialization/SerializeSIL.cpp | 1 - test/SIL/Parser/basic.sil | 10 ++- test/SILGen/Inputs/vtables_multifile_2.swift | 8 +-- test/SILGen/dynamic.swift | 4 +- test/SILGen/vtable_thunks.swift | 60 ++++++++-------- test/SILGen/vtable_thunks_reabstraction.swift | 70 +++++++++---------- test/SILGen/vtables_multifile.swift | 40 +++++------ 14 files changed, 118 insertions(+), 153 deletions(-) diff --git a/include/swift/SIL/SILVTable.h b/include/swift/SIL/SILVTable.h index ddc5ba36b6ef9..c266b762cf810 100644 --- a/include/swift/SIL/SILVTable.h +++ b/include/swift/SIL/SILVTable.h @@ -12,9 +12,14 @@ // // This file defines the SILVTable class, which is used to map dynamically // dispatchable class methods and properties to their concrete implementations -// for a dynamic type. This information is (FIXME will be) used by IRGen to lay -// out class vtables, and can be used by devirtualization passes to promote -// class_method instructions to static function_refs. +// for a dynamic type. This information is used by IRGen to emit class vtables, +// by the devirtualization pass to promote class_method instructions to static +// function_refs. +// +// Note that vtable layout itself is implemented in SILVTableLayout.h and is +// independent of the SILVTable; in general, for a class from another module we +// might not have a SILVTable to deserialize, and for a class in a different +// translation in the same module the SILVTable is not available either. // //===----------------------------------------------------------------------===// @@ -56,16 +61,10 @@ class SILVTable : public llvm::ilist_node, }; Entry() - : Implementation(nullptr), - TheKind(Kind::Normal), - Linkage(SILLinkage::Private) { } + : Implementation(nullptr), TheKind(Kind::Normal) { } - Entry(SILDeclRef Method, SILFunction *Implementation, - Kind TheKind, SILLinkage Linkage) - : Method(Method), - Implementation(Implementation), - TheKind(TheKind), - Linkage(Linkage) { } + Entry(SILDeclRef Method, SILFunction *Implementation, Kind TheKind) + : Method(Method), Implementation(Implementation), TheKind(TheKind) { } /// The declaration reference to the least-derived method visible through /// the class. @@ -76,14 +75,6 @@ class SILVTable : public llvm::ilist_node, /// The entry kind. Kind TheKind; - - /// The linkage of the implementing function. - /// - /// This is usually the same as - /// stripExternalFromLinkage(Implementation->getLinkage()) - /// except if Implementation is a thunk (which has private or shared - /// linkage). - SILLinkage Linkage; }; // Disallow copying into temporary objects. diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h index 35070cb974059..6a55dd8f46095 100644 --- a/include/swift/Serialization/ModuleFormat.h +++ b/include/swift/Serialization/ModuleFormat.h @@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 493; // dependency types for structs +const uint16_t SWIFTMODULE_VERSION_MINOR = 494; // remove linkage from SILVTable using DeclIDField = BCFixed<31>; diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp index 5bbf20002c2e8..5228d70a8bdba 100644 --- a/lib/ParseSIL/ParseSIL.cpp +++ b/lib/ParseSIL/ParseSIL.cpp @@ -5741,12 +5741,10 @@ bool SILParserTUState::parseSILVTable(Parser &P) { if (VTableState.parseSILDeclRef(Ref, true)) return true; SILFunction *Func = nullptr; - Optional Linkage = SILLinkage::Private; if (P.Tok.is(tok::kw_nil)) { P.consumeToken(); } else { if (P.parseToken(tok::colon, diag::expected_sil_vtable_colon) || - parseSILLinkage(Linkage, P) || P.parseToken(tok::at_sign, diag::expected_sil_function_name) || VTableState.parseSILIdentifier(FuncName, FuncLoc, diag::expected_sil_value_name)) @@ -5756,8 +5754,6 @@ bool SILParserTUState::parseSILVTable(Parser &P) { P.diagnose(FuncLoc, diag::sil_vtable_func_not_found, FuncName); return true; } - if (!Linkage) - Linkage = stripExternalFromLinkage(Func->getLinkage()); } auto Kind = SILVTable::Entry::Kind::Normal; @@ -5783,7 +5779,7 @@ bool SILParserTUState::parseSILVTable(Parser &P) { return true; } - vtableEntries.emplace_back(Ref, Func, Kind, Linkage.getValue()); + vtableEntries.emplace_back(Ref, Func, Kind); } while (P.Tok.isNot(tok::r_brace) && P.Tok.isNot(tok::eof)); } diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp index ffcfb69e67e4e..868d99ca8f15e 100644 --- a/lib/SIL/SILPrinter.cpp +++ b/lib/SIL/SILPrinter.cpp @@ -2791,10 +2791,6 @@ void SILVTable::print(llvm::raw_ostream &OS, bool Verbose) const { QualifiedSILTypeOptions); OS << " : "; } - if (entry.Linkage != - stripExternalFromLinkage(entry.Implementation->getLinkage())) { - OS << getLinkageString(entry.Linkage); - } OS << '@' << entry.Implementation->getName(); switch (entry.TheKind) { case SILVTable::Entry::Kind::Normal: diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp index ddc2852a3be21..27f1a5fd38207 100644 --- a/lib/SILGen/SILGenType.cpp +++ b/lib/SILGen/SILGenType.cpp @@ -75,7 +75,6 @@ SILGenModule::emitVTableMethod(ClassDecl *theClass, } SILFunction *implFn; - SILLinkage implLinkage; // If the member is dynamic, reference its dynamic dispatch thunk so that // it will be redispatched, funneling the method call through the runtime @@ -86,15 +85,13 @@ SILGenModule::emitVTableMethod(ClassDecl *theClass, if (usesObjCDynamicDispatch) { implFn = getDynamicThunk(derived, Types.getConstantInfo(derived).SILFnType); - implLinkage = SILLinkage::Public; } else { implFn = getFunction(derived, NotForDefinition); - implLinkage = stripExternalFromLinkage(implFn->getLinkage()); } // As a fast path, if there is no override, definitely no thunk is necessary. if (derived == base) - return SILVTable::Entry(base, implFn, implKind, implLinkage); + return SILVTable::Entry(base, implFn, implKind); // If the base method is less visible than the derived method, we need // a thunk. @@ -117,7 +114,7 @@ SILGenModule::emitVTableMethod(ClassDecl *theClass, M.Types.checkFunctionForABIDifferences(derivedInfo.SILFnType, overrideInfo.SILFnType) == TypeConverter::ABIDifference::Trivial) - return SILVTable::Entry(base, implFn, implKind, implLinkage); + return SILVTable::Entry(base, implFn, implKind); // Generate the thunk name. std::string name; @@ -137,7 +134,7 @@ SILGenModule::emitVTableMethod(ClassDecl *theClass, // If we already emitted this thunk, reuse it. if (auto existingThunk = M.lookUpFunction(name)) - return SILVTable::Entry(base, existingThunk, implKind, implLinkage); + return SILVTable::Entry(base, existingThunk, implKind); // Emit the thunk. SILLocation loc(derivedDecl); @@ -157,7 +154,7 @@ SILGenModule::emitVTableMethod(ClassDecl *theClass, baseLessVisibleThanDerived); emitLazyConformancesForFunction(thunk); - return SILVTable::Entry(base, thunk, implKind, implLinkage); + return SILVTable::Entry(base, thunk, implKind); } bool SILGenModule::requiresObjCMethodEntryPoint(FuncDecl *method) { @@ -232,17 +229,15 @@ class SILGenVTable : public SILVTableVisitor { auto *dtor = theClass->getDestructor(); SILDeclRef dtorRef(dtor, SILDeclRef::Kind::Deallocator); auto *dtorFn = SGM.getFunction(dtorRef, NotForDefinition); - vtableEntries.push_back({dtorRef, dtorFn, - SILVTable::Entry::Kind::Normal, - dtorFn->getLinkage()}); + vtableEntries.emplace_back(dtorRef, dtorFn, + SILVTable::Entry::Kind::Normal); } if (SGM.requiresIVarDestroyer(theClass)) { SILDeclRef dtorRef(theClass, SILDeclRef::Kind::IVarDestroyer); auto *dtorFn = SGM.getFunction(dtorRef, NotForDefinition); - vtableEntries.push_back({dtorRef, dtorFn, - SILVTable::Entry::Kind::Normal, - dtorFn->getLinkage()}); + vtableEntries.emplace_back(dtorRef, dtorFn, + SILVTable::Entry::Kind::Normal); } IsSerialized_t serialized = IsNotSerialized; diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 8f061ab49eb45..8ec5b6bc9460f 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -2733,17 +2733,8 @@ SILVTable *SILDeserializer::readVTable(DeclID VId) { "Content of Vtable should be in SIL_VTABLE_ENTRY."); ArrayRef ListOfValues; DeclID NameID; - unsigned RawLinkage; unsigned RawEntryKind; - VTableEntryLayout::readRecord(scratch, NameID, RawEntryKind, RawLinkage, ListOfValues); - - auto Linkage = fromStableSILLinkage(RawLinkage); - if (!Linkage) { - LLVM_DEBUG(llvm::dbgs() << "invalid linkage code " << RawLinkage - << " for VTable Entry\n"); - MF->error(); - return nullptr; - } + VTableEntryLayout::readRecord(scratch, NameID, RawEntryKind, ListOfValues); auto EntryKind = fromStableVTableEntryKind(RawEntryKind); @@ -2751,7 +2742,7 @@ SILVTable *SILDeserializer::readVTable(DeclID VId) { if (Func) { unsigned NextValueIndex = 0; vtableEntries.emplace_back(getSILDeclRef(MF, ListOfValues, NextValueIndex), - Func, EntryKind.getValue(), Linkage.getValue()); + Func, EntryKind.getValue()); } // Fetch the next record. diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h index 2b5facab492c0..a3acb30011af4 100644 --- a/lib/Serialization/SILFormat.h +++ b/lib/Serialization/SILFormat.h @@ -201,7 +201,6 @@ namespace sil_block { SIL_VTABLE_ENTRY, DeclIDField, // SILFunction name SILVTableEntryKindField, // Kind - SILLinkageField, // Linkage BCArray // SILDeclRef >; diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index 38d58fe0e78fd..a5cc2e677fe25 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -2245,7 +2245,6 @@ void SILSerializer::writeSILVTable(const SILVTable &vt) { // SILFunction name S.addUniquedStringRef(entry.Implementation->getName()), toStableVTableEntryKind(entry.TheKind), - toStableSILLinkage(entry.Linkage), ListOfValues); } } diff --git a/test/SIL/Parser/basic.sil b/test/SIL/Parser/basic.sil index 226ee669cd003..d6ac39c106135 100644 --- a/test/SIL/Parser/basic.sil +++ b/test/SIL/Parser/basic.sil @@ -1650,12 +1650,10 @@ bb0: } // CHECK-LABEL: sil_vtable Foo { -// CHECK: #Foo.subscript!getter.1: {{.*}} : hidden @Foo_subscript_getter -// CHECK: #Foo.subscript!setter.1: {{.*}} : @Foo_subscript_setter +// CHECK: #Foo.subscript!getter.1: {{.*}} : @Foo_subscript_getter +// CHECK: #Foo.subscript!setter.1: {{.*}} : @Foo_subscript_setter [override] // CHECK: } sil_vtable Foo { - // Override the linkage to check if it is parsed correctly. - #Foo.subscript!getter.1: hidden @Foo_subscript_getter - // The public linkage is the same as the function's linkage and should not be printed. - #Foo.subscript!setter.1: public @Foo_subscript_setter + #Foo.subscript!getter.1: @Foo_subscript_getter + #Foo.subscript!setter.1: @Foo_subscript_setter [override] } diff --git a/test/SILGen/Inputs/vtables_multifile_2.swift b/test/SILGen/Inputs/vtables_multifile_2.swift index c3cb24c52852f..1776233792d03 100644 --- a/test/SILGen/Inputs/vtables_multifile_2.swift +++ b/test/SILGen/Inputs/vtables_multifile_2.swift @@ -104,10 +104,10 @@ open class OtherDerived : Derived { // CHECK-NEXT: } // CHECK-LABEL: sil_vtable [serialized] OtherDerived { -// CHECK-NEXT: #Base.privateMethod1!1: (Base) -> () -> () : hidden @$s17vtables_multifile7DerivedC14privateMethod1yyFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyFTV [inherited] // vtable thunk for Base.privateMethod1() dispatching to Derived.privateMethod1() -// CHECK-NEXT: #Base.privateMethod2!1: (Base) -> (AnyObject) -> () : hidden @$s17vtables_multifile7DerivedC14privateMethod2yyyXlSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyyXlFTV [inherited] // vtable thunk for Base.privateMethod2(_:) dispatching to Derived.privateMethod2(_:) -// CHECK-NEXT: #Base.privateMethod3!1: (Base) -> (Int) -> () : hidden @$s17vtables_multifile7DerivedC14privateMethod3yySiSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyySiFTV [inherited] // vtable thunk for Base.privateMethod3(_:) dispatching to Derived.privateMethod3(_:) -// CHECK-NEXT: #Base.privateMethod4!1: (Base) -> (T) -> () : hidden @$s17vtables_multifile7DerivedC14privateMethod4yySiFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyxFTV [inherited] // vtable thunk for Base.privateMethod4(_:) dispatching to Derived.privateMethod4(_:) +// CHECK-NEXT: #Base.privateMethod1!1: (Base) -> () -> () : @$s17vtables_multifile7DerivedC14privateMethod1yyFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyFTV [inherited] // vtable thunk for Base.privateMethod1() dispatching to Derived.privateMethod1() +// CHECK-NEXT: #Base.privateMethod2!1: (Base) -> (AnyObject) -> () : @$s17vtables_multifile7DerivedC14privateMethod2yyyXlSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyyXlFTV [inherited] // vtable thunk for Base.privateMethod2(_:) dispatching to Derived.privateMethod2(_:) +// CHECK-NEXT: #Base.privateMethod3!1: (Base) -> (Int) -> () : @$s17vtables_multifile7DerivedC14privateMethod3yySiSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyySiFTV [inherited] // vtable thunk for Base.privateMethod3(_:) dispatching to Derived.privateMethod3(_:) +// CHECK-NEXT: #Base.privateMethod4!1: (Base) -> (T) -> () : @$s17vtables_multifile7DerivedC14privateMethod4yySiFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyxFTV [inherited] // vtable thunk for Base.privateMethod4(_:) dispatching to Derived.privateMethod4(_:) // CHECK-NEXT: #Base.init!allocator.1: (Base.Type) -> () -> Base : @$s17vtables_multifile12OtherDerivedCACycfC [override] // OtherDerived.__allocating_init() // CHECK-NEXT: #Derived.privateMethod1!1: (Derived) -> () -> () : @$s17vtables_multifile12OtherDerivedC14privateMethod1yyF [override] // OtherDerived.privateMethod1() // CHECK-NEXT: #Derived.privateMethod2!1: (Derived) -> (AnyObject?) -> () : @$s17vtables_multifile12OtherDerivedC14privateMethod2yyyXlSgF [override] // OtherDerived.privateMethod2(_:) diff --git a/test/SILGen/dynamic.swift b/test/SILGen/dynamic.swift index 9b20cc7276103..394c881e40158 100644 --- a/test/SILGen/dynamic.swift +++ b/test/SILGen/dynamic.swift @@ -546,7 +546,7 @@ public class ConcreteDerived : GenericBase { // Vtable uses a dynamic thunk for dynamic overrides // CHECK-LABEL: sil_vtable Subclass { -// CHECK: #Foo.overriddenByDynamic!1: {{.*}} : public @$s7dynamic8SubclassC19overriddenByDynamic{{[_0-9a-zA-Z]*}}FTD +// CHECK: #Foo.overriddenByDynamic!1: {{.*}} : @$s7dynamic8SubclassC19overriddenByDynamic{{[_0-9a-zA-Z]*}}FTD // CHECK: } // Check vtables for implicitly-inherited initializers @@ -575,7 +575,7 @@ public class ConcreteDerived : GenericBase { // Dynamic thunk + vtable re-abstraction // CHECK-LABEL: sil_vtable [serialized] ConcreteDerived { -// CHECK-NEXT: #GenericBase.method!1: (GenericBase) -> (T) -> () : public @$s7dynamic15ConcreteDerivedC6methodyySiFAA11GenericBaseCADyyxFTV [override] // vtable thunk for dynamic.GenericBase.method(A) -> () dispatching to dynamic.ConcreteDerived.method(Swift.Int) -> () +// CHECK-NEXT: #GenericBase.method!1: (GenericBase) -> (T) -> () : @$s7dynamic15ConcreteDerivedC6methodyySiFAA11GenericBaseCADyyxFTV [override] // vtable thunk for dynamic.GenericBase.method(A) -> () dispatching to dynamic.ConcreteDerived.method(Swift.Int) -> () // CHECK-NEXT: #GenericBase.init!allocator.1: (GenericBase.Type) -> () -> GenericBase : @$s7dynamic15ConcreteDerivedCACycfC [override] // CHECK-NEXT: #ConcreteDerived.deinit!deallocator.1: @$s7dynamic15ConcreteDerivedCfD // dynamic.ConcreteDerived.__deallocating_deinit // CHECK-NEXT: } diff --git a/test/SILGen/vtable_thunks.swift b/test/SILGen/vtable_thunks.swift index f19228f894caf..c4abc6481529e 100644 --- a/test/SILGen/vtable_thunks.swift +++ b/test/SILGen/vtable_thunks.swift @@ -248,60 +248,60 @@ class Noot : Aap { // CHECK: return [[OUTER]] // CHECK-LABEL: sil_vtable D { -// CHECK: #B.iuo!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.iuo!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV // CHECK: #B.f!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}F // CHECK: #B.f2!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}F // CHECK: #B.f3!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}F // CHECK: #B.f4!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}F -// CHECK: #B.g!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.g2!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.g3!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.g!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.g2!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.g3!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV // CHECK: #B.g4!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}F -// CHECK: #B.h!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.h2!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.h3!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.h!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.h2!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.h3!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV // CHECK: #B.h4!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}F -// CHECK: #B.i!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.i2!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.i3!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.i!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.i2!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.i3!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV // CHECK: #B.i4!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}F // CHECK-LABEL: sil_vtable E { -// CHECK: #B.iuo!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.iuo!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV // CHECK: #B.f!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}F // CHECK: #B.f2!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}F // CHECK: #B.f3!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}F // CHECK: #B.f4!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}F -// CHECK: #B.g!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.g2!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.g3!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.g!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.g2!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.g3!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV // CHECK: #B.g4!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}F -// CHECK: #B.h!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.h2!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.h3!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.h!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.h2!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.h3!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV // CHECK: #B.h4!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}F -// CHECK: #B.i!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.i2!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.i3!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.i!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.i2!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.i3!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV // CHECK: #B.i4!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}F // CHECK-LABEL: sil_vtable F { -// CHECK: #B.iuo!1: {{.*}} : hidden @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.iuo!1: {{.*}} : @$s13vtable_thunks1D{{[A-Z0-9a-z_]*}}FTV // CHECK: #B.f!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}F // CHECK: #B.f2!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}F // CHECK: #B.f3!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}F // CHECK: #B.f4!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}F -// CHECK: #B.g!1: {{.*}} : hidden @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.g2!1: {{.*}} : hidden @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.g3!1: {{.*}} : hidden @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.g!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.g2!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.g3!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV // CHECK: #B.g4!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}F -// CHECK: #B.h!1: {{.*}} : hidden @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.h2!1: {{.*}} : hidden @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.h3!1: {{.*}} : hidden @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.h!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.h2!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.h3!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV // CHECK: #B.h4!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}F -// CHECK: #B.i!1: {{.*}} : hidden @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.i2!1: {{.*}} : hidden @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV -// CHECK: #B.i3!1: {{.*}} : hidden @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.i!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.i2!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV +// CHECK: #B.i3!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}FTV // CHECK: #B.i4!1: {{.*}} : @$s13vtable_thunks1F{{[A-Z0-9a-z_]*}}F // CHECK-LABEL: sil_vtable NoThrowVariance { diff --git a/test/SILGen/vtable_thunks_reabstraction.swift b/test/SILGen/vtable_thunks_reabstraction.swift index 604f3a24656bf..5d029373b1561 100644 --- a/test/SILGen/vtable_thunks_reabstraction.swift +++ b/test/SILGen/vtable_thunks_reabstraction.swift @@ -190,7 +190,7 @@ class StillOpaque: Opaque { // CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : @$s27vtable_thunks_reabstraction6OpaqueC18variantOptionality1xxSgx_tF [inherited] // Opaque.variantOptionality(x:) // CHECK-NEXT: #Opaque.variantOptionalityMetatypes!1: (Opaque) -> (T.Type) -> T.Type? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityMetatypes1xxmSgxm_tF [inherited] // Opaque.variantOptionalityMetatypes(x:) // CHECK-NEXT: #Opaque.variantOptionalityFunctions!1: (Opaque) -> (@escaping (T) -> T) -> ((T) -> T)? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityFunctions1xxxcSgxxc_tF [inherited] // Opaque.variantOptionalityFunctions(x:) -// CHECK-NEXT: #Opaque.variantOptionalityTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T))? : hidden @$s27vtable_thunks_reabstraction11StillOpaqueC24variantOptionalityTuples1xx_xm_xxcttx_xm_xxcttSg_tFAA0E0CAdeFx_xm_xxctt_tFTV [override] // vtable thunk for Opaque.variantOptionalityTuples(x:) dispatching to StillOpaque.variantOptionalityTuples(x:) +// CHECK-NEXT: #Opaque.variantOptionalityTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T))? : @$s27vtable_thunks_reabstraction11StillOpaqueC24variantOptionalityTuples1xx_xm_xxcttx_xm_xxcttSg_tFAA0E0CAdeFx_xm_xxctt_tFTV [override] // vtable thunk for Opaque.variantOptionalityTuples(x:) dispatching to StillOpaque.variantOptionalityTuples(x:) // CHECK-NEXT: #Opaque.init!allocator.1: (Opaque.Type) -> () -> Opaque : @$s27vtable_thunks_reabstraction11StillOpaqueCACyxGycfC [override] // Tuple becomes more optional -- needs new vtable entry @@ -213,15 +213,15 @@ class ConcreteValue: Opaque { } // CHECK-LABEL: sil_vtable ConcreteValue { -// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : hidden @$s27vtable_thunks_reabstraction13ConcreteValueC8inAndOut1xAA1SVAG_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteValue.inAndOut(x:) -// CHECK-NEXT: #Opaque.inAndOutGeneric!1: (Opaque) -> (T, U) -> U : hidden @$s27vtable_thunks_reabstraction13ConcreteValueC15inAndOutGeneric1x1yxAA1SV_xtlFAA6OpaqueCAdeFqd__x_qd__tlFTV [override] // vtable thunk for Opaque.inAndOutGeneric(x:y:) dispatching to ConcreteValue.inAndOutGeneric(x:y:) -// CHECK-NEXT: #Opaque.inAndOutMetatypes!1: (Opaque) -> (T.Type) -> T.Type : hidden @$s27vtable_thunks_reabstraction13ConcreteValueC17inAndOutMetatypes1xAA1SVmAGm_tFAA6OpaqueCAdExmxm_tFTV [override] // vtable thunk for Opaque.inAndOutMetatypes(x:) dispatching to ConcreteValue.inAndOutMetatypes(x:) -// CHECK-NEXT: #Opaque.inAndOutFunctions!1: (Opaque) -> (@escaping (T) -> T) -> (T) -> T : hidden @$s27vtable_thunks_reabstraction13ConcreteValueC17inAndOutFunctions1xAA1SVAGcA2Gc_tFAA6OpaqueCAdExxcxxc_tFTV [override] // vtable thunk for Opaque.inAndOutFunctions(x:) dispatching to ConcreteValue.inAndOutFunctions(x:) -// CHECK-NEXT: #Opaque.inAndOutTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T)) : hidden @$s27vtable_thunks_reabstraction13ConcreteValueC14inAndOutTuples1xAA1SV_AGm_A2GcttAG_AGm_A2Gctt_tFAA6OpaqueCAdEx_xm_xxcttx_xm_xxctt_tFTV [override] // vtable thunk for Opaque.inAndOutTuples(x:) dispatching to ConcreteValue.inAndOutTuples(x:) -// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : hidden @$s27vtable_thunks_reabstraction13ConcreteValueC18variantOptionality1xAA1SVAGSg_tFAA6OpaqueCAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to ConcreteValue.variantOptionality(x:) -// CHECK-NEXT: #Opaque.variantOptionalityMetatypes!1: (Opaque) -> (T.Type) -> T.Type? : hidden @$s27vtable_thunks_reabstraction13ConcreteValueC27variantOptionalityMetatypes1xAA1SVmAGmSg_tFAA6OpaqueCAdExmSgxm_tFTV [override] // vtable thunk for Opaque.variantOptionalityMetatypes(x:) dispatching to ConcreteValue.variantOptionalityMetatypes(x:) -// CHECK-NEXT: #Opaque.variantOptionalityFunctions!1: (Opaque) -> (@escaping (T) -> T) -> ((T) -> T)? : hidden @$s27vtable_thunks_reabstraction13ConcreteValueC27variantOptionalityFunctions1xAA1SVAGcA2GcSg_tFAA6OpaqueCAdExxcSgxxc_tFTV [override] // vtable thunk for Opaque.variantOptionalityFunctions(x:) dispatching to ConcreteValue.variantOptionalityFunctions(x:) -// CHECK-NEXT: #Opaque.variantOptionalityTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T))? : hidden @$s27vtable_thunks_reabstraction13ConcreteValueC24variantOptionalityTuples1xAA1SV_AGm_A2GcttAG_AGm_A2GcttSg_tFAA6OpaqueCAdEx_xm_xxcttSgx_xm_xxctt_tFTV [override] // vtable thunk for Opaque.variantOptionalityTuples(x:) dispatching to ConcreteValue.variantOptionalityTuples(x:) +// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : @$s27vtable_thunks_reabstraction13ConcreteValueC8inAndOut1xAA1SVAG_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteValue.inAndOut(x:) +// CHECK-NEXT: #Opaque.inAndOutGeneric!1: (Opaque) -> (T, U) -> U : @$s27vtable_thunks_reabstraction13ConcreteValueC15inAndOutGeneric1x1yxAA1SV_xtlFAA6OpaqueCAdeFqd__x_qd__tlFTV [override] // vtable thunk for Opaque.inAndOutGeneric(x:y:) dispatching to ConcreteValue.inAndOutGeneric(x:y:) +// CHECK-NEXT: #Opaque.inAndOutMetatypes!1: (Opaque) -> (T.Type) -> T.Type : @$s27vtable_thunks_reabstraction13ConcreteValueC17inAndOutMetatypes1xAA1SVmAGm_tFAA6OpaqueCAdExmxm_tFTV [override] // vtable thunk for Opaque.inAndOutMetatypes(x:) dispatching to ConcreteValue.inAndOutMetatypes(x:) +// CHECK-NEXT: #Opaque.inAndOutFunctions!1: (Opaque) -> (@escaping (T) -> T) -> (T) -> T : @$s27vtable_thunks_reabstraction13ConcreteValueC17inAndOutFunctions1xAA1SVAGcA2Gc_tFAA6OpaqueCAdExxcxxc_tFTV [override] // vtable thunk for Opaque.inAndOutFunctions(x:) dispatching to ConcreteValue.inAndOutFunctions(x:) +// CHECK-NEXT: #Opaque.inAndOutTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T)) : @$s27vtable_thunks_reabstraction13ConcreteValueC14inAndOutTuples1xAA1SV_AGm_A2GcttAG_AGm_A2Gctt_tFAA6OpaqueCAdEx_xm_xxcttx_xm_xxctt_tFTV [override] // vtable thunk for Opaque.inAndOutTuples(x:) dispatching to ConcreteValue.inAndOutTuples(x:) +// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : @$s27vtable_thunks_reabstraction13ConcreteValueC18variantOptionality1xAA1SVAGSg_tFAA6OpaqueCAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to ConcreteValue.variantOptionality(x:) +// CHECK-NEXT: #Opaque.variantOptionalityMetatypes!1: (Opaque) -> (T.Type) -> T.Type? : @$s27vtable_thunks_reabstraction13ConcreteValueC27variantOptionalityMetatypes1xAA1SVmAGmSg_tFAA6OpaqueCAdExmSgxm_tFTV [override] // vtable thunk for Opaque.variantOptionalityMetatypes(x:) dispatching to ConcreteValue.variantOptionalityMetatypes(x:) +// CHECK-NEXT: #Opaque.variantOptionalityFunctions!1: (Opaque) -> (@escaping (T) -> T) -> ((T) -> T)? : @$s27vtable_thunks_reabstraction13ConcreteValueC27variantOptionalityFunctions1xAA1SVAGcA2GcSg_tFAA6OpaqueCAdExxcSgxxc_tFTV [override] // vtable thunk for Opaque.variantOptionalityFunctions(x:) dispatching to ConcreteValue.variantOptionalityFunctions(x:) +// CHECK-NEXT: #Opaque.variantOptionalityTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T))? : @$s27vtable_thunks_reabstraction13ConcreteValueC24variantOptionalityTuples1xAA1SV_AGm_A2GcttAG_AGm_A2GcttSg_tFAA6OpaqueCAdEx_xm_xxcttSgx_xm_xxctt_tFTV [override] // vtable thunk for Opaque.variantOptionalityTuples(x:) dispatching to ConcreteValue.variantOptionalityTuples(x:) // CHECK-NEXT: #Opaque.init!allocator.1: (Opaque.Type) -> () -> Opaque : @$s27vtable_thunks_reabstraction13ConcreteValueCACycfC [override] // Value types becoming more optional -- needs new vtable entry @@ -246,15 +246,15 @@ class ConcreteClass: Opaque { } // CHECK-LABEL: sil_vtable ConcreteClass { -// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : hidden @$s27vtable_thunks_reabstraction13ConcreteClassC8inAndOut1xAA1CCAG_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteClass.inAndOut(x:) +// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : @$s27vtable_thunks_reabstraction13ConcreteClassC8inAndOut1xAA1CCAG_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteClass.inAndOut(x:) // CHECK-NEXT: #Opaque.inAndOutGeneric!1: (Opaque) -> (T, U) -> U : @$s27vtable_thunks_reabstraction6OpaqueC15inAndOutGeneric1x1yqd__x_qd__tlF [inherited] // Opaque.inAndOutGeneric(x:y:) // CHECK-NEXT: #Opaque.inAndOutMetatypes!1: (Opaque) -> (T.Type) -> T.Type : @$s27vtable_thunks_reabstraction13ConcreteClassC17inAndOutMetatypes1xAA1CCmAGm_tF [override] // ConcreteClass.inAndOutMetatypes(x:) -// CHECK-NEXT: #Opaque.inAndOutFunctions!1: (Opaque) -> (@escaping (T) -> T) -> (T) -> T : hidden @$s27vtable_thunks_reabstraction13ConcreteClassC17inAndOutFunctions1xAA1CCAGcA2Gc_tFAA6OpaqueCAdExxcxxc_tFTV [override] // vtable thunk for Opaque.inAndOutFunctions(x:) dispatching to ConcreteClass.inAndOutFunctions(x:) -// CHECK-NEXT: #Opaque.inAndOutTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T)) : hidden @$s27vtable_thunks_reabstraction13ConcreteClassC14inAndOutTuples1xAA1CC_AGm_A2GcttAG_AGm_A2Gctt_tFAA6OpaqueCAdEx_xm_xxcttx_xm_xxctt_tFTV [override] // vtable thunk for Opaque.inAndOutTuples(x:) dispatching to ConcreteClass.inAndOutTuples(x:) -// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : hidden @$s27vtable_thunks_reabstraction13ConcreteClassC18variantOptionality1xAA1CCAGSg_tFAA6OpaqueCAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to ConcreteClass.variantOptionality(x:) +// CHECK-NEXT: #Opaque.inAndOutFunctions!1: (Opaque) -> (@escaping (T) -> T) -> (T) -> T : @$s27vtable_thunks_reabstraction13ConcreteClassC17inAndOutFunctions1xAA1CCAGcA2Gc_tFAA6OpaqueCAdExxcxxc_tFTV [override] // vtable thunk for Opaque.inAndOutFunctions(x:) dispatching to ConcreteClass.inAndOutFunctions(x:) +// CHECK-NEXT: #Opaque.inAndOutTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T)) : @$s27vtable_thunks_reabstraction13ConcreteClassC14inAndOutTuples1xAA1CC_AGm_A2GcttAG_AGm_A2Gctt_tFAA6OpaqueCAdEx_xm_xxcttx_xm_xxctt_tFTV [override] // vtable thunk for Opaque.inAndOutTuples(x:) dispatching to ConcreteClass.inAndOutTuples(x:) +// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : @$s27vtable_thunks_reabstraction13ConcreteClassC18variantOptionality1xAA1CCAGSg_tFAA6OpaqueCAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to ConcreteClass.variantOptionality(x:) // CHECK-NEXT: #Opaque.variantOptionalityMetatypes!1: (Opaque) -> (T.Type) -> T.Type? : @$s27vtable_thunks_reabstraction13ConcreteClassC27variantOptionalityMetatypes1xAA1CCmAGmSg_tF [override] // ConcreteClass.variantOptionalityMetatypes(x:) -// CHECK-NEXT: #Opaque.variantOptionalityFunctions!1: (Opaque) -> (@escaping (T) -> T) -> ((T) -> T)? : hidden @$s27vtable_thunks_reabstraction13ConcreteClassC27variantOptionalityFunctions1xAA1CCAGcA2GcSg_tFAA6OpaqueCAdExxcSgxxc_tFTV [override] // vtable thunk for Opaque.variantOptionalityFunctions(x:) dispatching to ConcreteClass.variantOptionalityFunctions(x:) -// CHECK-NEXT: #Opaque.variantOptionalityTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T))? : hidden @$s27vtable_thunks_reabstraction13ConcreteClassC24variantOptionalityTuples1xAA1CC_AGm_A2GcttAG_AGm_A2GcttSg_tFAA6OpaqueCAdEx_xm_xxcttSgx_xm_xxctt_tFTV [override] // vtable thunk for Opaque.variantOptionalityTuples(x:) dispatching to ConcreteClass.variantOptionalityTuples(x:) +// CHECK-NEXT: #Opaque.variantOptionalityFunctions!1: (Opaque) -> (@escaping (T) -> T) -> ((T) -> T)? : @$s27vtable_thunks_reabstraction13ConcreteClassC27variantOptionalityFunctions1xAA1CCAGcA2GcSg_tFAA6OpaqueCAdExxcSgxxc_tFTV [override] // vtable thunk for Opaque.variantOptionalityFunctions(x:) dispatching to ConcreteClass.variantOptionalityFunctions(x:) +// CHECK-NEXT: #Opaque.variantOptionalityTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T))? : @$s27vtable_thunks_reabstraction13ConcreteClassC24variantOptionalityTuples1xAA1CC_AGm_A2GcttAG_AGm_A2GcttSg_tFAA6OpaqueCAdEx_xm_xxcttSgx_xm_xxctt_tFTV [override] // vtable thunk for Opaque.variantOptionalityTuples(x:) dispatching to ConcreteClass.variantOptionalityTuples(x:) // CHECK-NEXT: #Opaque.init!allocator.1: (Opaque.Type) -> () -> Opaque : @$s27vtable_thunks_reabstraction13ConcreteClassCACycfC [override] // Class references are ABI-compatible with optional class references, and @@ -275,12 +275,12 @@ class ConcreteClassVariance: Opaque { } // CHECK-LABEL: sil_vtable ConcreteClassVariance { -// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : hidden @$s27vtable_thunks_reabstraction21ConcreteClassVarianceC8inAndOut1xAA1DCAA1BC_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteClassVariance.inAndOut(x:) +// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : @$s27vtable_thunks_reabstraction21ConcreteClassVarianceC8inAndOut1xAA1DCAA1BC_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteClassVariance.inAndOut(x:) // CHECK-NEXT: #Opaque.inAndOutGeneric!1: (Opaque) -> (T, U) -> U : @$s27vtable_thunks_reabstraction6OpaqueC15inAndOutGeneric1x1yqd__x_qd__tlF [inherited] // Opaque.inAndOutGeneric(x:y:) // CHECK-NEXT: #Opaque.inAndOutMetatypes!1: (Opaque) -> (T.Type) -> T.Type : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutMetatypes1xxmxm_tF [inherited] // Opaque.inAndOutMetatypes(x:) // CHECK-NEXT: #Opaque.inAndOutFunctions!1: (Opaque) -> (@escaping (T) -> T) -> (T) -> T : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutFunctions1xxxcxxc_tF [inherited] // Opaque.inAndOutFunctions(x:) // CHECK-NEXT: #Opaque.inAndOutTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T)) : @$s27vtable_thunks_reabstraction6OpaqueC14inAndOutTuples1xx_xm_xxcttx_xm_xxctt_tF [inherited] // Opaque.inAndOutTuples(x:) -// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : hidden @$s27vtable_thunks_reabstraction21ConcreteClassVarianceC18variantOptionality1xAA1DCAA1BCSg_tFAA6OpaqueCAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to ConcreteClassVariance.variantOptionality(x:) +// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : @$s27vtable_thunks_reabstraction21ConcreteClassVarianceC18variantOptionality1xAA1DCAA1BCSg_tFAA6OpaqueCAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to ConcreteClassVariance.variantOptionality(x:) // CHECK-NEXT: #Opaque.variantOptionalityMetatypes!1: (Opaque) -> (T.Type) -> T.Type? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityMetatypes1xxmSgxm_tF [inherited] // Opaque.variantOptionalityMetatypes(x:) // CHECK-NEXT: #Opaque.variantOptionalityFunctions!1: (Opaque) -> (@escaping (T) -> T) -> ((T) -> T)? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityFunctions1xxxcSgxxc_tF [inherited] // Opaque.variantOptionalityFunctions(x:) // CHECK-NEXT: #Opaque.variantOptionalityTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T))? : @$s27vtable_thunks_reabstraction6OpaqueC24variantOptionalityTuples1xx_xm_xxcttSgx_xm_xxctt_tF [inherited] // Opaque.variantOptionalityTuples(x:) @@ -298,12 +298,12 @@ class OpaqueTuple: Opaque<(U, U)> { } // CHECK-LABEL: sil_vtable OpaqueTuple { -// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : hidden @$s27vtable_thunks_reabstraction11OpaqueTupleC8inAndOut1xx_xtx_xt_tFAA0D0CAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to OpaqueTuple.inAndOut(x:) +// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : @$s27vtable_thunks_reabstraction11OpaqueTupleC8inAndOut1xx_xtx_xt_tFAA0D0CAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to OpaqueTuple.inAndOut(x:) // CHECK-NEXT: #Opaque.inAndOutGeneric!1: (Opaque) -> (T, U) -> U : @$s27vtable_thunks_reabstraction6OpaqueC15inAndOutGeneric1x1yqd__x_qd__tlF [inherited] // Opaque.inAndOutGeneric(x:y:) // CHECK-NEXT: #Opaque.inAndOutMetatypes!1: (Opaque) -> (T.Type) -> T.Type : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutMetatypes1xxmxm_tF [inherited] // Opaque.inAndOutMetatypes(x:) // CHECK-NEXT: #Opaque.inAndOutFunctions!1: (Opaque) -> (@escaping (T) -> T) -> (T) -> T : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutFunctions1xxxcxxc_tF [inherited] // Opaque.inAndOutFunctions(x:) // CHECK-NEXT: #Opaque.inAndOutTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T)) : @$s27vtable_thunks_reabstraction6OpaqueC14inAndOutTuples1xx_xm_xxcttx_xm_xxctt_tF [inherited] // Opaque.inAndOutTuples(x:) -// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : hidden @$s27vtable_thunks_reabstraction11OpaqueTupleC18variantOptionality1xx_xtx_xtSg_tFAA0D0CAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to OpaqueTuple.variantOptionality(x:) +// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : @$s27vtable_thunks_reabstraction11OpaqueTupleC18variantOptionality1xx_xtx_xtSg_tFAA0D0CAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to OpaqueTuple.variantOptionality(x:) // CHECK-NEXT: #Opaque.variantOptionalityMetatypes!1: (Opaque) -> (T.Type) -> T.Type? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityMetatypes1xxmSgxm_tF [inherited] // Opaque.variantOptionalityMetatypes(x:) // CHECK-NEXT: #Opaque.variantOptionalityFunctions!1: (Opaque) -> (@escaping (T) -> T) -> ((T) -> T)? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityFunctions1xxxcSgxxc_tF [inherited] // Opaque.variantOptionalityFunctions(x:) // CHECK-NEXT: #Opaque.variantOptionalityTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T))? : @$s27vtable_thunks_reabstraction6OpaqueC24variantOptionalityTuples1xx_xm_xxcttSgx_xm_xxctt_tF [inherited] // Opaque.variantOptionalityTuples(x:) @@ -322,12 +322,12 @@ class ConcreteTuple: Opaque<(S, S)> { } // CHECK-LABEL: sil_vtable ConcreteTuple { -// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : hidden @$s27vtable_thunks_reabstraction13ConcreteTupleC8inAndOut1xAA1SV_AGtAG_AGt_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteTuple.inAndOut(x:) +// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : @$s27vtable_thunks_reabstraction13ConcreteTupleC8inAndOut1xAA1SV_AGtAG_AGt_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteTuple.inAndOut(x:) // CHECK-NEXT: #Opaque.inAndOutGeneric!1: (Opaque) -> (T, U) -> U : @$s27vtable_thunks_reabstraction6OpaqueC15inAndOutGeneric1x1yqd__x_qd__tlF [inherited] // Opaque.inAndOutGeneric(x:y:) // CHECK-NEXT: #Opaque.inAndOutMetatypes!1: (Opaque) -> (T.Type) -> T.Type : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutMetatypes1xxmxm_tF [inherited] // Opaque.inAndOutMetatypes(x:) // CHECK-NEXT: #Opaque.inAndOutFunctions!1: (Opaque) -> (@escaping (T) -> T) -> (T) -> T : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutFunctions1xxxcxxc_tF [inherited] // Opaque.inAndOutFunctions(x:) // CHECK-NEXT: #Opaque.inAndOutTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T)) : @$s27vtable_thunks_reabstraction6OpaqueC14inAndOutTuples1xx_xm_xxcttx_xm_xxctt_tF [inherited] // Opaque.inAndOutTuples(x:) -// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : hidden @$s27vtable_thunks_reabstraction13ConcreteTupleC18variantOptionality1xAA1SV_AGtAG_AGtSg_tFAA6OpaqueCAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to ConcreteTuple.variantOptionality(x:) +// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : @$s27vtable_thunks_reabstraction13ConcreteTupleC18variantOptionality1xAA1SV_AGtAG_AGtSg_tFAA6OpaqueCAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to ConcreteTuple.variantOptionality(x:) // CHECK-NEXT: #Opaque.variantOptionalityMetatypes!1: (Opaque) -> (T.Type) -> T.Type? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityMetatypes1xxmSgxm_tF [inherited] // Opaque.variantOptionalityMetatypes(x:) // CHECK-NEXT: #Opaque.variantOptionalityFunctions!1: (Opaque) -> (@escaping (T) -> T) -> ((T) -> T)? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityFunctions1xxxcSgxxc_tF [inherited] // Opaque.variantOptionalityFunctions(x:) // CHECK-NEXT: #Opaque.variantOptionalityTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T))? : @$s27vtable_thunks_reabstraction6OpaqueC24variantOptionalityTuples1xx_xm_xxcttSgx_xm_xxctt_tF [inherited] // Opaque.variantOptionalityTuples(x:) @@ -346,12 +346,12 @@ class OpaqueFunction: Opaque<(U) -> V> { } // CHECK-LABEL: sil_vtable OpaqueFunction { -// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : hidden @$s27vtable_thunks_reabstraction14OpaqueFunctionC8inAndOut1xq_xcq_xc_tFAA0D0CAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to OpaqueFunction.inAndOut(x:) +// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : @$s27vtable_thunks_reabstraction14OpaqueFunctionC8inAndOut1xq_xcq_xc_tFAA0D0CAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to OpaqueFunction.inAndOut(x:) // CHECK-NEXT: #Opaque.inAndOutGeneric!1: (Opaque) -> (T, U) -> U : @$s27vtable_thunks_reabstraction6OpaqueC15inAndOutGeneric1x1yqd__x_qd__tlF [inherited] // Opaque.inAndOutGeneric(x:y:) // CHECK-NEXT: #Opaque.inAndOutMetatypes!1: (Opaque) -> (T.Type) -> T.Type : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutMetatypes1xxmxm_tF [inherited] // Opaque.inAndOutMetatypes(x:) // CHECK-NEXT: #Opaque.inAndOutFunctions!1: (Opaque) -> (@escaping (T) -> T) -> (T) -> T : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutFunctions1xxxcxxc_tF [inherited] // Opaque.inAndOutFunctions(x:) // CHECK-NEXT: #Opaque.inAndOutTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T)) : @$s27vtable_thunks_reabstraction6OpaqueC14inAndOutTuples1xx_xm_xxcttx_xm_xxctt_tF [inherited] // Opaque.inAndOutTuples(x:) -// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : hidden @$s27vtable_thunks_reabstraction14OpaqueFunctionC18variantOptionality1xq_xcq_xcSg_tFAA0D0CAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to OpaqueFunction.variantOptionality(x:) +// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : @$s27vtable_thunks_reabstraction14OpaqueFunctionC18variantOptionality1xq_xcq_xcSg_tFAA0D0CAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to OpaqueFunction.variantOptionality(x:) // CHECK-NEXT: #Opaque.variantOptionalityMetatypes!1: (Opaque) -> (T.Type) -> T.Type? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityMetatypes1xxmSgxm_tF [inherited] // Opaque.variantOptionalityMetatypes(x:) // CHECK-NEXT: #Opaque.variantOptionalityFunctions!1: (Opaque) -> (@escaping (T) -> T) -> ((T) -> T)? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityFunctions1xxxcSgxxc_tF [inherited] // Opaque.variantOptionalityFunctions(x:) // CHECK-NEXT: #Opaque.variantOptionalityTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T))? : @$s27vtable_thunks_reabstraction6OpaqueC24variantOptionalityTuples1xx_xm_xxcttSgx_xm_xxctt_tF [inherited] // Opaque.variantOptionalityTuples(x:) @@ -370,12 +370,12 @@ class ConcreteFunction: Opaque<(S) -> S> { } // CHECK-LABEL: sil_vtable ConcreteFunction { -// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : hidden @$s27vtable_thunks_reabstraction16ConcreteFunctionC8inAndOut1xAA1SVAGcA2Gc_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteFunction.inAndOut(x:) +// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : @$s27vtable_thunks_reabstraction16ConcreteFunctionC8inAndOut1xAA1SVAGcA2Gc_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteFunction.inAndOut(x:) // CHECK-NEXT: #Opaque.inAndOutGeneric!1: (Opaque) -> (T, U) -> U : @$s27vtable_thunks_reabstraction6OpaqueC15inAndOutGeneric1x1yqd__x_qd__tlF [inherited] // Opaque.inAndOutGeneric(x:y:) // CHECK-NEXT: #Opaque.inAndOutMetatypes!1: (Opaque) -> (T.Type) -> T.Type : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutMetatypes1xxmxm_tF [inherited] // Opaque.inAndOutMetatypes(x:) // CHECK-NEXT: #Opaque.inAndOutFunctions!1: (Opaque) -> (@escaping (T) -> T) -> (T) -> T : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutFunctions1xxxcxxc_tF [inherited] // Opaque.inAndOutFunctions(x:) // CHECK-NEXT: #Opaque.inAndOutTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T)) : @$s27vtable_thunks_reabstraction6OpaqueC14inAndOutTuples1xx_xm_xxcttx_xm_xxctt_tF [inherited] // Opaque.inAndOutTuples(x:) -// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : hidden @$s27vtable_thunks_reabstraction16ConcreteFunctionC18variantOptionality1xAA1SVAGcA2GcSg_tFAA6OpaqueCAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to ConcreteFunction.variantOptionality(x:) +// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : @$s27vtable_thunks_reabstraction16ConcreteFunctionC18variantOptionality1xAA1SVAGcA2GcSg_tFAA6OpaqueCAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to ConcreteFunction.variantOptionality(x:) // CHECK-NEXT: #Opaque.variantOptionalityMetatypes!1: (Opaque) -> (T.Type) -> T.Type? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityMetatypes1xxmSgxm_tF [inherited] // Opaque.variantOptionalityMetatypes(x:) // CHECK-NEXT: #Opaque.variantOptionalityFunctions!1: (Opaque) -> (@escaping (T) -> T) -> ((T) -> T)? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityFunctions1xxxcSgxxc_tF [inherited] // Opaque.variantOptionalityFunctions(x:) // CHECK-NEXT: #Opaque.variantOptionalityTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T))? : @$s27vtable_thunks_reabstraction6OpaqueC24variantOptionalityTuples1xx_xm_xxcttSgx_xm_xxctt_tF [inherited] // Opaque.variantOptionalityTuples(x:) @@ -394,12 +394,12 @@ class OpaqueMetatype: Opaque { } // CHECK-LABEL: sil_vtable OpaqueMetatype { -// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : hidden @$s27vtable_thunks_reabstraction14OpaqueMetatypeC8inAndOut1xxmxm_tFAA0D0CAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to OpaqueMetatype.inAndOut(x:) +// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : @$s27vtable_thunks_reabstraction14OpaqueMetatypeC8inAndOut1xxmxm_tFAA0D0CAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to OpaqueMetatype.inAndOut(x:) // CHECK-NEXT: #Opaque.inAndOutGeneric!1: (Opaque) -> (T, U) -> U : @$s27vtable_thunks_reabstraction6OpaqueC15inAndOutGeneric1x1yqd__x_qd__tlF [inherited] // Opaque.inAndOutGeneric(x:y:) // CHECK-NEXT: #Opaque.inAndOutMetatypes!1: (Opaque) -> (T.Type) -> T.Type : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutMetatypes1xxmxm_tF [inherited] // Opaque.inAndOutMetatypes(x:) // CHECK-NEXT: #Opaque.inAndOutFunctions!1: (Opaque) -> (@escaping (T) -> T) -> (T) -> T : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutFunctions1xxxcxxc_tF [inherited] // Opaque.inAndOutFunctions(x:) // CHECK-NEXT: #Opaque.inAndOutTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T)) : @$s27vtable_thunks_reabstraction6OpaqueC14inAndOutTuples1xx_xm_xxcttx_xm_xxctt_tF [inherited] // Opaque.inAndOutTuples(x:) -// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : hidden @$s27vtable_thunks_reabstraction14OpaqueMetatypeC18variantOptionality1xxmxmSg_tFAA0D0CAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to OpaqueMetatype.variantOptionality(x:) +// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : @$s27vtable_thunks_reabstraction14OpaqueMetatypeC18variantOptionality1xxmxmSg_tFAA0D0CAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to OpaqueMetatype.variantOptionality(x:) // CHECK-NEXT: #Opaque.variantOptionalityMetatypes!1: (Opaque) -> (T.Type) -> T.Type? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityMetatypes1xxmSgxm_tF [inherited] // Opaque.variantOptionalityMetatypes(x:) // CHECK-NEXT: #Opaque.variantOptionalityFunctions!1: (Opaque) -> (@escaping (T) -> T) -> ((T) -> T)? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityFunctions1xxxcSgxxc_tF [inherited] // Opaque.variantOptionalityFunctions(x:) // CHECK-NEXT: #Opaque.variantOptionalityTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T))? : @$s27vtable_thunks_reabstraction6OpaqueC24variantOptionalityTuples1xx_xm_xxcttSgx_xm_xxctt_tF [inherited] // Opaque.variantOptionalityTuples(x:) @@ -418,12 +418,12 @@ class ConcreteValueMetatype: Opaque { } // CHECK-LABEL: sil_vtable ConcreteValueMetatype { -// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : hidden @$s27vtable_thunks_reabstraction21ConcreteValueMetatypeC8inAndOut1xAA1SVmAGm_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteValueMetatype.inAndOut(x:) +// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : @$s27vtable_thunks_reabstraction21ConcreteValueMetatypeC8inAndOut1xAA1SVmAGm_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteValueMetatype.inAndOut(x:) // CHECK-NEXT: #Opaque.inAndOutGeneric!1: (Opaque) -> (T, U) -> U : @$s27vtable_thunks_reabstraction6OpaqueC15inAndOutGeneric1x1yqd__x_qd__tlF [inherited] // Opaque.inAndOutGeneric(x:y:) // CHECK-NEXT: #Opaque.inAndOutMetatypes!1: (Opaque) -> (T.Type) -> T.Type : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutMetatypes1xxmxm_tF [inherited] // Opaque.inAndOutMetatypes(x:) // CHECK-NEXT: #Opaque.inAndOutFunctions!1: (Opaque) -> (@escaping (T) -> T) -> (T) -> T : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutFunctions1xxxcxxc_tF [inherited] // Opaque.inAndOutFunctions(x:) // CHECK-NEXT: #Opaque.inAndOutTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T)) : @$s27vtable_thunks_reabstraction6OpaqueC14inAndOutTuples1xx_xm_xxcttx_xm_xxctt_tF [inherited] // Opaque.inAndOutTuples(x:) -// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : hidden @$s27vtable_thunks_reabstraction21ConcreteValueMetatypeC18variantOptionality1xAA1SVmAGmSg_tFAA6OpaqueCAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to ConcreteValueMetatype.variantOptionality(x:) +// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : @$s27vtable_thunks_reabstraction21ConcreteValueMetatypeC18variantOptionality1xAA1SVmAGmSg_tFAA6OpaqueCAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to ConcreteValueMetatype.variantOptionality(x:) // CHECK-NEXT: #Opaque.variantOptionalityMetatypes!1: (Opaque) -> (T.Type) -> T.Type? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityMetatypes1xxmSgxm_tF [inherited] // Opaque.variantOptionalityMetatypes(x:) // CHECK-NEXT: #Opaque.variantOptionalityFunctions!1: (Opaque) -> (@escaping (T) -> T) -> ((T) -> T)? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityFunctions1xxxcSgxxc_tF [inherited] // Opaque.variantOptionalityFunctions(x:) // CHECK-NEXT: #Opaque.variantOptionalityTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T))? : @$s27vtable_thunks_reabstraction6OpaqueC24variantOptionalityTuples1xx_xm_xxcttSgx_xm_xxctt_tF [inherited] // Opaque.variantOptionalityTuples(x:) @@ -442,12 +442,12 @@ class ConcreteClassMetatype: Opaque { } // CHECK-LABEL: sil_vtable ConcreteClassMetatype { -// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : hidden @$s27vtable_thunks_reabstraction21ConcreteClassMetatypeC8inAndOut1xAA1CCmAGm_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteClassMetatype.inAndOut(x:) +// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : @$s27vtable_thunks_reabstraction21ConcreteClassMetatypeC8inAndOut1xAA1CCmAGm_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteClassMetatype.inAndOut(x:) // CHECK-NEXT: #Opaque.inAndOutGeneric!1: (Opaque) -> (T, U) -> U : @$s27vtable_thunks_reabstraction6OpaqueC15inAndOutGeneric1x1yqd__x_qd__tlF [inherited] // Opaque.inAndOutGeneric(x:y:) // CHECK-NEXT: #Opaque.inAndOutMetatypes!1: (Opaque) -> (T.Type) -> T.Type : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutMetatypes1xxmxm_tF [inherited] // Opaque.inAndOutMetatypes(x:) // CHECK-NEXT: #Opaque.inAndOutFunctions!1: (Opaque) -> (@escaping (T) -> T) -> (T) -> T : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutFunctions1xxxcxxc_tF [inherited] // Opaque.inAndOutFunctions(x:) // CHECK-NEXT: #Opaque.inAndOutTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T)) : @$s27vtable_thunks_reabstraction6OpaqueC14inAndOutTuples1xx_xm_xxcttx_xm_xxctt_tF [inherited] // Opaque.inAndOutTuples(x:) -// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : hidden @$s27vtable_thunks_reabstraction21ConcreteClassMetatypeC18variantOptionality1xAA1CCmAGmSg_tFAA6OpaqueCAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to ConcreteClassMetatype.variantOptionality(x:) +// CHECK-NEXT: #Opaque.variantOptionality!1: (Opaque) -> (T) -> T? : @$s27vtable_thunks_reabstraction21ConcreteClassMetatypeC18variantOptionality1xAA1CCmAGmSg_tFAA6OpaqueCAdExSgx_tFTV [override] // vtable thunk for Opaque.variantOptionality(x:) dispatching to ConcreteClassMetatype.variantOptionality(x:) // CHECK-NEXT: #Opaque.variantOptionalityMetatypes!1: (Opaque) -> (T.Type) -> T.Type? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityMetatypes1xxmSgxm_tF [inherited] // Opaque.variantOptionalityMetatypes(x:) // CHECK-NEXT: #Opaque.variantOptionalityFunctions!1: (Opaque) -> (@escaping (T) -> T) -> ((T) -> T)? : @$s27vtable_thunks_reabstraction6OpaqueC27variantOptionalityFunctions1xxxcSgxxc_tF [inherited] // Opaque.variantOptionalityFunctions(x:) // CHECK-NEXT: #Opaque.variantOptionalityTuples!1: (Opaque) -> ((T, (T.Type, (T) -> T))) -> (T, (T.Type, (T) -> T))? : @$s27vtable_thunks_reabstraction6OpaqueC24variantOptionalityTuples1xx_xm_xxcttSgx_xm_xxctt_tF [inherited] // Opaque.variantOptionalityTuples(x:) @@ -466,7 +466,7 @@ class ConcreteOptional: Opaque { } // CHECK-LABEL: sil_vtable ConcreteOptional { -// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : hidden @$s27vtable_thunks_reabstraction16ConcreteOptionalC8inAndOut1xAA1SVSgAH_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteOptional.inAndOut(x:) +// CHECK-NEXT: #Opaque.inAndOut!1: (Opaque) -> (T) -> T : @$s27vtable_thunks_reabstraction16ConcreteOptionalC8inAndOut1xAA1SVSgAH_tFAA6OpaqueCAdExx_tFTV [override] // vtable thunk for Opaque.inAndOut(x:) dispatching to ConcreteOptional.inAndOut(x:) // CHECK-NEXT: #Opaque.inAndOutGeneric!1: (Opaque) -> (T, U) -> U : @$s27vtable_thunks_reabstraction6OpaqueC15inAndOutGeneric1x1yqd__x_qd__tlF [inherited] // Opaque.inAndOutGeneric(x:y:) // CHECK-NEXT: #Opaque.inAndOutMetatypes!1: (Opaque) -> (T.Type) -> T.Type : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutMetatypes1xxmxm_tF [inherited] // Opaque.inAndOutMetatypes(x:) // CHECK-NEXT: #Opaque.inAndOutFunctions!1: (Opaque) -> (@escaping (T) -> T) -> (T) -> T : @$s27vtable_thunks_reabstraction6OpaqueC17inAndOutFunctions1xxxcxxc_tF [inherited] // Opaque.inAndOutFunctions(x:) @@ -502,8 +502,8 @@ class ConcreteSub : GenericBase { } // CHECK-LABEL: sil_vtable ConcreteSub { -// CHECK-NEXT: #GenericBase.doStuff!1: (GenericBase) -> (T, U) -> () : hidden @$s27vtable_thunks_reabstraction11ConcreteSubC7doStuff1t1uySi_xtlFAA11GenericBaseCAdeFyx_qd__tlFTV [override] // vtable thunk for GenericBase.doStuff(t:u:) dispatching to ConcreteSub.doStuff(t:u:) -// CHECK-NEXT: #GenericBase.init!allocator.1: (GenericBase.Type) -> (T, U) -> GenericBase : hidden @$s27vtable_thunks_reabstraction11ConcreteSubC1t1uACSi_xtclufCAA11GenericBaseCAdeGyxGx_qd__tclufCTV [override] +// CHECK-NEXT: #GenericBase.doStuff!1: (GenericBase) -> (T, U) -> () : @$s27vtable_thunks_reabstraction11ConcreteSubC7doStuff1t1uySi_xtlFAA11GenericBaseCAdeFyx_qd__tlFTV [override] // vtable thunk for GenericBase.doStuff(t:u:) dispatching to ConcreteSub.doStuff(t:u:) +// CHECK-NEXT: #GenericBase.init!allocator.1: (GenericBase.Type) -> (T, U) -> GenericBase : @$s27vtable_thunks_reabstraction11ConcreteSubC1t1uACSi_xtclufCAA11GenericBaseCAdeGyxGx_qd__tclufCTV [override] // CHECK-NEXT: #ConcreteSub.deinit!deallocator.1: @$s27vtable_thunks_reabstraction11ConcreteSubCfD // ConcreteSub.__deallocating_deinit // CHECK-NEXT: } diff --git a/test/SILGen/vtables_multifile.swift b/test/SILGen/vtables_multifile.swift index 15aebbfe0aac0..9437412215301 100644 --- a/test/SILGen/vtables_multifile.swift +++ b/test/SILGen/vtables_multifile.swift @@ -159,10 +159,10 @@ open class MostDerived : MoreDerived { // -- // CHECK-LABEL: sil_vtable [serialized] Derived { -// CHECK-NEXT: #Base.privateMethod1!1: (Base) -> () -> () : hidden @$s17vtables_multifile7DerivedC14privateMethod1yyFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyFTV [override] // vtable thunk for Base.privateMethod1() dispatching to Derived.privateMethod1() -// CHECK-NEXT: #Base.privateMethod2!1: (Base) -> (AnyObject) -> () : hidden @$s17vtables_multifile7DerivedC14privateMethod2yyyXlSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyyXlFTV [override] // vtable thunk for Base.privateMethod2(_:) dispatching to Derived.privateMethod2(_:) -// CHECK-NEXT: #Base.privateMethod3!1: (Base) -> (Int) -> () : hidden @$s17vtables_multifile7DerivedC14privateMethod3yySiSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyySiFTV [override] // vtable thunk for Base.privateMethod3(_:) dispatching to Derived.privateMethod3(_:) -// CHECK-NEXT: #Base.privateMethod4!1: (Base) -> (T) -> () : hidden @$s17vtables_multifile7DerivedC14privateMethod4yySiFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyxFTV [override] // vtable thunk for Base.privateMethod4(_:) dispatching to Derived.privateMethod4(_:) +// CHECK-NEXT: #Base.privateMethod1!1: (Base) -> () -> () : @$s17vtables_multifile7DerivedC14privateMethod1yyFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyFTV [override] // vtable thunk for Base.privateMethod1() dispatching to Derived.privateMethod1() +// CHECK-NEXT: #Base.privateMethod2!1: (Base) -> (AnyObject) -> () : @$s17vtables_multifile7DerivedC14privateMethod2yyyXlSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyyXlFTV [override] // vtable thunk for Base.privateMethod2(_:) dispatching to Derived.privateMethod2(_:) +// CHECK-NEXT: #Base.privateMethod3!1: (Base) -> (Int) -> () : @$s17vtables_multifile7DerivedC14privateMethod3yySiSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyySiFTV [override] // vtable thunk for Base.privateMethod3(_:) dispatching to Derived.privateMethod3(_:) +// CHECK-NEXT: #Base.privateMethod4!1: (Base) -> (T) -> () : @$s17vtables_multifile7DerivedC14privateMethod4yySiFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyxFTV [override] // vtable thunk for Base.privateMethod4(_:) dispatching to Derived.privateMethod4(_:) // CHECK-NEXT: #Base.init!allocator.1: (Base.Type) -> () -> Base : @$s17vtables_multifile7DerivedCACycfC [override] // Derived.__allocating_init() // CHECK-NEXT: #Derived.privateMethod1!1: (Derived) -> () -> () : @$s17vtables_multifile7DerivedC14privateMethod1yyF // Derived.privateMethod1() // CHECK-NEXT: #Derived.privateMethod2!1: (Derived) -> (AnyObject?) -> () : @$s17vtables_multifile7DerivedC14privateMethod2yyyXlSgF // Derived.privateMethod2(_:) @@ -176,15 +176,15 @@ open class MostDerived : MoreDerived { // -- // CHECK-LABEL: sil_vtable [serialized] MoreDerived { -// CHECK-NEXT: #Base.privateMethod1!1: (Base) -> () -> () : public @$s17vtables_multifile11MoreDerivedC14privateMethod1yyFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyFTV [override] // vtable thunk for Base.privateMethod1() dispatching to MoreDerived.privateMethod1() -// CHECK-NEXT: #Base.privateMethod2!1: (Base) -> (AnyObject) -> () : public @$s17vtables_multifile11MoreDerivedC14privateMethod2yyyXlSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyyXlFTV [override] // vtable thunk for Base.privateMethod2(_:) dispatching to MoreDerived.privateMethod2(_:) -// CHECK-NEXT: #Base.privateMethod3!1: (Base) -> (Int) -> () : public @$s17vtables_multifile11MoreDerivedC14privateMethod3yySiSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyySiFTV [override] // vtable thunk for Base.privateMethod3(_:) dispatching to MoreDerived.privateMethod3(_:) -// CHECK-NEXT: #Base.privateMethod4!1: (Base) -> (T) -> () : public @$s17vtables_multifile11MoreDerivedC14privateMethod4yySiFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyxFTV [override] // vtable thunk for Base.privateMethod4(_:) dispatching to MoreDerived.privateMethod4(_:) +// CHECK-NEXT: #Base.privateMethod1!1: (Base) -> () -> () : @$s17vtables_multifile11MoreDerivedC14privateMethod1yyFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyFTV [override] // vtable thunk for Base.privateMethod1() dispatching to MoreDerived.privateMethod1() +// CHECK-NEXT: #Base.privateMethod2!1: (Base) -> (AnyObject) -> () : @$s17vtables_multifile11MoreDerivedC14privateMethod2yyyXlSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyyXlFTV [override] // vtable thunk for Base.privateMethod2(_:) dispatching to MoreDerived.privateMethod2(_:) +// CHECK-NEXT: #Base.privateMethod3!1: (Base) -> (Int) -> () : @$s17vtables_multifile11MoreDerivedC14privateMethod3yySiSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyySiFTV [override] // vtable thunk for Base.privateMethod3(_:) dispatching to MoreDerived.privateMethod3(_:) +// CHECK-NEXT: #Base.privateMethod4!1: (Base) -> (T) -> () : @$s17vtables_multifile11MoreDerivedC14privateMethod4yySiFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyxFTV [override] // vtable thunk for Base.privateMethod4(_:) dispatching to MoreDerived.privateMethod4(_:) // CHECK-NEXT: #Base.init!allocator.1: (Base.Type) -> () -> Base : @$s17vtables_multifile11MoreDerivedCACycfC [override] // MoreDerived.__allocating_init() -// CHECK-NEXT: #Derived.privateMethod1!1: (Derived) -> () -> () : public @$s17vtables_multifile11MoreDerivedC14privateMethod1yyFAA0D0CADyyFTV [override] // vtable thunk for Derived.privateMethod1() dispatching to MoreDerived.privateMethod1() -// CHECK-NEXT: #Derived.privateMethod2!1: (Derived) -> (AnyObject?) -> () : public @$s17vtables_multifile11MoreDerivedC14privateMethod2yyyXlSgFAA0D0CADyyAEFTV [override] // vtable thunk for Derived.privateMethod2(_:) dispatching to MoreDerived.privateMethod2(_:) -// CHECK-NEXT: #Derived.privateMethod3!1: (Derived) -> (Int?) -> () : public @$s17vtables_multifile11MoreDerivedC14privateMethod3yySiSgFAA0D0CADyyAEFTV [override] // vtable thunk for Derived.privateMethod3(_:) dispatching to MoreDerived.privateMethod3(_:) -// CHECK-NEXT: #Derived.privateMethod4!1: (Derived) -> (Int) -> () : public @$s17vtables_multifile11MoreDerivedC14privateMethod4yySiFAA0D0CADyySiFTV [override] // vtable thunk for Derived.privateMethod4(_:) dispatching to MoreDerived.privateMethod4(_:) +// CHECK-NEXT: #Derived.privateMethod1!1: (Derived) -> () -> () : @$s17vtables_multifile11MoreDerivedC14privateMethod1yyFAA0D0CADyyFTV [override] // vtable thunk for Derived.privateMethod1() dispatching to MoreDerived.privateMethod1() +// CHECK-NEXT: #Derived.privateMethod2!1: (Derived) -> (AnyObject?) -> () : @$s17vtables_multifile11MoreDerivedC14privateMethod2yyyXlSgFAA0D0CADyyAEFTV [override] // vtable thunk for Derived.privateMethod2(_:) dispatching to MoreDerived.privateMethod2(_:) +// CHECK-NEXT: #Derived.privateMethod3!1: (Derived) -> (Int?) -> () : @$s17vtables_multifile11MoreDerivedC14privateMethod3yySiSgFAA0D0CADyyAEFTV [override] // vtable thunk for Derived.privateMethod3(_:) dispatching to MoreDerived.privateMethod3(_:) +// CHECK-NEXT: #Derived.privateMethod4!1: (Derived) -> (Int) -> () : @$s17vtables_multifile11MoreDerivedC14privateMethod4yySiFAA0D0CADyySiFTV [override] // vtable thunk for Derived.privateMethod4(_:) dispatching to MoreDerived.privateMethod4(_:) // CHECK-NEXT: #MoreDerived.privateMethod1!1: (MoreDerived) -> () -> () : @$s17vtables_multifile11MoreDerivedC14privateMethod1yyF // MoreDerived.privateMethod1() // CHECK-NEXT: #MoreDerived.privateMethod2!1: (MoreDerived) -> (AnyObject?) -> () : @$s17vtables_multifile11MoreDerivedC14privateMethod2yyyXlSgF // MoreDerived.privateMethod2(_:) // CHECK-NEXT: #MoreDerived.privateMethod3!1: (MoreDerived) -> (Int?) -> () : @$s17vtables_multifile11MoreDerivedC14privateMethod3yySiSgF // MoreDerived.privateMethod3(_:) @@ -197,15 +197,15 @@ open class MostDerived : MoreDerived { // -- // CHECK-LABEL: sil_vtable [serialized] MostDerived { -// CHECK-NEXT: #Base.privateMethod1!1: (Base) -> () -> () : public @$s17vtables_multifile11MostDerivedC14privateMethod1yyFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyFTV [override] // vtable thunk for Base.privateMethod1() dispatching to MostDerived.privateMethod1() -// CHECK-NEXT: #Base.privateMethod2!1: (Base) -> (AnyObject) -> () : public @$s17vtables_multifile11MostDerivedC14privateMethod2yyyXlSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyyXlFTV [override] // vtable thunk for Base.privateMethod2(_:) dispatching to MostDerived.privateMethod2(_:) -// CHECK-NEXT: #Base.privateMethod3!1: (Base) -> (Int) -> () : public @$s17vtables_multifile11MostDerivedC14privateMethod3yySiSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyySiFTV [override] // vtable thunk for Base.privateMethod3(_:) dispatching to MostDerived.privateMethod3(_:) -// CHECK-NEXT: #Base.privateMethod4!1: (Base) -> (T) -> () : public @$s17vtables_multifile11MostDerivedC14privateMethod4yySiFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyxFTV [override] // vtable thunk for Base.privateMethod4(_:) dispatching to MostDerived.privateMethod4(_:) +// CHECK-NEXT: #Base.privateMethod1!1: (Base) -> () -> () : @$s17vtables_multifile11MostDerivedC14privateMethod1yyFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyFTV [override] // vtable thunk for Base.privateMethod1() dispatching to MostDerived.privateMethod1() +// CHECK-NEXT: #Base.privateMethod2!1: (Base) -> (AnyObject) -> () : @$s17vtables_multifile11MostDerivedC14privateMethod2yyyXlSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyyXlFTV [override] // vtable thunk for Base.privateMethod2(_:) dispatching to MostDerived.privateMethod2(_:) +// CHECK-NEXT: #Base.privateMethod3!1: (Base) -> (Int) -> () : @$s17vtables_multifile11MostDerivedC14privateMethod3yySiSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyySiFTV [override] // vtable thunk for Base.privateMethod3(_:) dispatching to MostDerived.privateMethod3(_:) +// CHECK-NEXT: #Base.privateMethod4!1: (Base) -> (T) -> () : @$s17vtables_multifile11MostDerivedC14privateMethod4yySiFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyxFTV [override] // vtable thunk for Base.privateMethod4(_:) dispatching to MostDerived.privateMethod4(_:) // CHECK-NEXT: #Base.init!allocator.1: (Base.Type) -> () -> Base : @$s17vtables_multifile11MostDerivedCACycfC [override] // MostDerived.__allocating_init() -// CHECK-NEXT: #Derived.privateMethod1!1: (Derived) -> () -> () : public @$s17vtables_multifile11MostDerivedC14privateMethod1yyFAA0D0CADyyFTV [override] // vtable thunk for Derived.privateMethod1() dispatching to MostDerived.privateMethod1() -// CHECK-NEXT: #Derived.privateMethod2!1: (Derived) -> (AnyObject?) -> () : public @$s17vtables_multifile11MostDerivedC14privateMethod2yyyXlSgFAA0D0CADyyAEFTV [override] // vtable thunk for Derived.privateMethod2(_:) dispatching to MostDerived.privateMethod2(_:) -// CHECK-NEXT: #Derived.privateMethod3!1: (Derived) -> (Int?) -> () : public @$s17vtables_multifile11MostDerivedC14privateMethod3yySiSgFAA0D0CADyyAEFTV [override] // vtable thunk for Derived.privateMethod3(_:) dispatching to MostDerived.privateMethod3(_:) -// CHECK-NEXT: #Derived.privateMethod4!1: (Derived) -> (Int) -> () : public @$s17vtables_multifile11MostDerivedC14privateMethod4yySiFAA0D0CADyySiFTV [override] // vtable thunk for Derived.privateMethod4(_:) dispatching to MostDerived.privateMethod4(_:) +// CHECK-NEXT: #Derived.privateMethod1!1: (Derived) -> () -> () : @$s17vtables_multifile11MostDerivedC14privateMethod1yyFAA0D0CADyyFTV [override] // vtable thunk for Derived.privateMethod1() dispatching to MostDerived.privateMethod1() +// CHECK-NEXT: #Derived.privateMethod2!1: (Derived) -> (AnyObject?) -> () : @$s17vtables_multifile11MostDerivedC14privateMethod2yyyXlSgFAA0D0CADyyAEFTV [override] // vtable thunk for Derived.privateMethod2(_:) dispatching to MostDerived.privateMethod2(_:) +// CHECK-NEXT: #Derived.privateMethod3!1: (Derived) -> (Int?) -> () : @$s17vtables_multifile11MostDerivedC14privateMethod3yySiSgFAA0D0CADyyAEFTV [override] // vtable thunk for Derived.privateMethod3(_:) dispatching to MostDerived.privateMethod3(_:) +// CHECK-NEXT: #Derived.privateMethod4!1: (Derived) -> (Int) -> () : @$s17vtables_multifile11MostDerivedC14privateMethod4yySiFAA0D0CADyySiFTV [override] // vtable thunk for Derived.privateMethod4(_:) dispatching to MostDerived.privateMethod4(_:) // CHECK-NEXT: #MoreDerived.privateMethod1!1: (MoreDerived) -> () -> () : @$s17vtables_multifile11MostDerivedC14privateMethod1yyF [override] // MostDerived.privateMethod1() // CHECK-NEXT: #MoreDerived.privateMethod2!1: (MoreDerived) -> (AnyObject?) -> () : @$s17vtables_multifile11MostDerivedC14privateMethod2yyyXlSgF [override] // MostDerived.privateMethod2(_:) // CHECK-NEXT: #MoreDerived.privateMethod3!1: (MoreDerived) -> (Int?) -> () : @$s17vtables_multifile11MostDerivedC14privateMethod3yySiSgF [override] // MostDerived.privateMethod3(_:) From cf0405c7f17679b423afd69678874b6b3b7bdc41 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Sat, 8 Jun 2019 14:47:37 -0700 Subject: [PATCH 079/112] [clf] Simplify the double diamond lifetime extension for escaping swift funcs -> noescape blocks. Specifically, when we optimize conversions such as: Optional<@escaping () -> ()> -> Optional<@noescape () -> ()> -> Optional<@noescape @convention(block) () -> ()> previously we were lifetime extending over the @noescape lifetime barrier by making a copy and then putting a mark_dependence from the copy onto the original value. This was just a quick way to tell the ownership verifier that the copy was tied to the other value and thus should not be eliminated. The correctness of the actual lifetime extension comes from the optimizer being conservative around rr insts. This commit instead changes our optimization to borrow the copied optional value, extract the payload, and use that instead. --- include/swift/SIL/SILBuilder.h | 7 ++ .../Mandatory/ClosureLifetimeFixup.cpp | 111 ++++++++++++----- test/SILOptimizer/closure-lifetime-fixup.sil | 117 ++++++++++++++++++ .../definite-init-convert-to-escape.swift | 4 +- 4 files changed, 209 insertions(+), 30 deletions(-) create mode 100644 test/SILOptimizer/closure-lifetime-fixup.sil diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h index b0db1ef85a488..8606c30408240 100644 --- a/include/swift/SIL/SILBuilder.h +++ b/include/swift/SIL/SILBuilder.h @@ -1279,6 +1279,13 @@ class SILBuilder { return createUncheckedEnumData(Loc, Operand, Element, EltType); } + /// Return unchecked_enum_data %Operand, #Optional.some. + SILValue emitExtractOptionalPayloadOperation(SILLocation Loc, + SILValue Operand) { + auto *Decl = F->getASTContext().getOptionalSomeDecl(); + return createUncheckedEnumData(Loc, Operand, Decl); + } + UncheckedTakeEnumDataAddrInst * createUncheckedTakeEnumDataAddr(SILLocation Loc, SILValue Operand, EnumElementDecl *Element, SILType Ty) { diff --git a/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp b/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp index 4fe4f56d0e7ce..cc00c8c79b2c1 100644 --- a/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp +++ b/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp @@ -35,6 +35,17 @@ llvm::cl::opt DisableConvertEscapeToNoEscapeSwitchEnumPeephole( using namespace swift; +/// Given an optional diamond, return the bottom of the diamond. +/// +/// That is given that sei is in bb0, +/// +/// /---> bb1 ---\ +/// / \ +/// bb0 ---> bb3 +/// \ / +/// \---> bb2 ---/ +/// +/// this routine will return bb3. static SILBasicBlock *getOptionalDiamondSuccessor(SwitchEnumInst *sei) { auto numSuccs = sei->getNumSuccessors(); if (numSuccs != 2) @@ -434,25 +445,53 @@ static bool tryExtendLifetimeToLastUse( return false; } -/// Ensure the lifetime of the closure accross an +/// Ensure the lifetime of the closure across a two step optional conversion +/// from: +/// +/// optional<@escaping () -> ()> +/// +/// to: +/// +/// optional<@noescape () -> ()> +/// +/// to: /// -/// optional<@escaping () -> ()> to /// optional<@noescape @convention(block) () -> ()> /// -/// conversion and its use. +/// and all uses of the block. The pattern that we are looking for is: /// -/// The pattern this is looking for -/// switch_enum %closure -/// / \ -/// convert_escape_to_noescape nil -/// switch_enum +/// switch_enum %optional_closure (1) /// / \ -/// convertToBlock nil +/// %trivial_closure = CVT %closure nil (2) +/// \ / +/// switch_enum %optional_trivial_closure (3) +/// / \ +/// %b = convertToBlock %trivial_closure nil (4) /// \ / -/// (%convertOptionalBlock :) -/// We will insert a copy_value of the original %closure before the two -/// diamonds. And a destroy of %closure at the last destroy of -/// %convertOptionalBlock. +/// ... uses of %optional_block ... +/// destroy_value %optional_block +/// +/// where CVT is convert_escape_to_no_escape [not_guaranteed]. We assume that +/// the %optional_block is going through a conversion sequence in SILGen meaning +/// that we should only have a single destroy of the optional block. +/// +/// NOTE: There is a *lifetime gap* during the usage of the trivial_closure! +/// This means we must be careful when lifetime extending. We can only assume +/// that the underlying closure is alive immediately at the CVT. So to perform +/// our lifetime extend, we do the following: +/// +/// 1. We copy and borrow optional_closure, right before the switch_enum in +/// (1). +/// +/// 2. We rewrite the convert_escape_to_no_escape guaranteed to use the copy +/// instead. +/// +/// 3. To make sure that even after ossa is complete, we do not move any +/// destroys above the convert_escape_to_no_escape by putting a mark_dependence +/// on %closure +/// +/// 4. We insert an end_borrow, destroy for the copy at the destroy of the +/// optional block. static bool trySwitchEnumPeephole(ConvertEscapeToNoEscapeInst *cvt) { auto *blockArg = dyn_cast(cvt->getOperand()); if (!blockArg) @@ -478,7 +517,8 @@ static bool trySwitchEnumPeephole(ConvertEscapeToNoEscapeInst *cvt) { if (diamondSucc2->getNumArguments() != 1) return false; - // Look for the last and only destroy. + // Look for the last and only destroy of the diamond succ 2's argument. This + // is going to be the place where we destroy the lifetime extending copy. SILInstruction *onlyDestroy = [&]() -> SILInstruction * { SILInstruction *lastDestroy = nullptr; for (auto *use : diamondSucc2->getArgument(0)->getUses()) { @@ -497,15 +537,27 @@ static bool trySwitchEnumPeephole(ConvertEscapeToNoEscapeInst *cvt) { // Extend the lifetime. auto loc = RegularLocation::getAutoGeneratedLocation(); - auto *copy = SILBuilderWithScope(switchEnum1) - .createCopyValue(loc, switchEnum1->getOperand()); + SILValue copy, borrow; + std::tie(copy, borrow) = ([&]() -> std::pair { + SILBuilderWithScope builder(switchEnum1); + auto copy = builder.emitCopyValueOperation(loc, switchEnum1->getOperand()); + auto borrow = builder.emitBeginBorrowOperation(loc, copy); + return {copy, borrow}; + })(); // end std::tie(copy, borrow). + + { + SILBuilderWithScope builder(cvt); + auto value = builder.emitExtractOptionalPayloadOperation(loc, borrow); + cvt->setOperand(value); + cvt->setLifetimeGuaranteed(); + } - cvt->setLifetimeGuaranteed(); - auto *mdi = SILBuilderWithScope(cvt).createMarkDependence( - loc, cvt->getOperand(), copy); - cvt->setOperand(mdi); + { + SILBuilderWithScope builder(onlyDestroy); + builder.emitEndBorrowOperation(loc, borrow); + builder.emitDestroyValueOperation(loc, copy); + } - SILBuilderWithScope(onlyDestroy).createDestroyValue(loc, copy); return true; } @@ -757,7 +809,9 @@ static bool fixupClosureLifetimes(SILFunction &fn, bool &checkStackNesting, // Handle, copy_block_without_escaping instructions. if (auto *cb = dyn_cast(inst)) { - changed |= fixupCopyBlockWithoutEscaping(cb, modifiedCFG); + if (fixupCopyBlockWithoutEscaping(cb, modifiedCFG)) { + changed = true; + } continue; } @@ -768,14 +822,15 @@ static bool fixupClosureLifetimes(SILFunction &fn, bool &checkStackNesting, continue; // First try to peephole a known pattern. - if (!DisableConvertEscapeToNoEscapeSwitchEnumPeephole && - trySwitchEnumPeephole(cvt)) { - changed |= true; - continue; + if (!DisableConvertEscapeToNoEscapeSwitchEnumPeephole) { + if (trySwitchEnumPeephole(cvt)) { + changed = true; + continue; + } } if (tryExtendLifetimeToLastUse(cvt, memoizedQueries, i)) { - changed |= true; + changed = true; checkStackNesting = true; continue; } @@ -783,7 +838,7 @@ static bool fixupClosureLifetimes(SILFunction &fn, bool &checkStackNesting, // Otherwise, extend the lifetime of the operand to the end of the // function. extendLifetimeToEndOfFunction(fn, cvt); - changed |= true; + changed = true; } } return changed; diff --git a/test/SILOptimizer/closure-lifetime-fixup.sil b/test/SILOptimizer/closure-lifetime-fixup.sil new file mode 100644 index 0000000000000..c56dcda769988 --- /dev/null +++ b/test/SILOptimizer/closure-lifetime-fixup.sil @@ -0,0 +1,117 @@ +// RUN: %target-sil-opt -closure-lifetime-fixup %s | %FileCheck %s + +sil_stage raw + +import Swift +import Builtin +import SwiftShims + +class FakeNSString {} + +sil @$sSSSgIgg_AAIegg_TR : $@convention(thin) (@guaranteed Optional, @noescape @callee_guaranteed (@guaranteed Optional) -> ()) -> () +sil @noescapeBlock3 : $@convention(c) (Optional<@convention(block) @noescape (Optional) -> ()>, Optional<@convention(block) @noescape (Optional) -> ()>, Optional) -> () +sil @$sSS10FoundationE19_bridgeToObjectiveCSo8FakeNSStringCyF : $@convention(method) (@guaranteed String) -> @owned FakeNSString +sil @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String +sil @$sSSSgIegg_So8FakeNSStringCSgIyBy_TR : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed (@guaranteed Optional) -> (), Optional) -> () + +// Just make sure that we perform the optimization and do not trigger the ownership verifier. +// +// CHECK-LABEL: sil [ossa] @test1 : $@convention(thin) (@guaranteed Optional<@callee_guaranteed (@guaranteed Optional) -> ()>, @guaranteed Optional<@callee_guaranteed (@guaranteed Optional) -> ()>) -> () { +// CHECK-NOT: convert_escape_to_noescape [not_guaranteed] +// CHECK: } // end sil function 'test1' +sil [ossa] @test1 : $@convention(thin) (@guaranteed Optional<@callee_guaranteed (@guaranteed Optional) -> ()>, @guaranteed Optional<@callee_guaranteed (@guaranteed Optional) -> ()>) -> () { +bb0(%0 : @guaranteed $Optional<@callee_guaranteed (@guaranteed Optional) -> ()>, %1 : @guaranteed $Optional<@callee_guaranteed (@guaranteed Optional) -> ()>): + %2 = copy_value %0 : $Optional<@callee_guaranteed (@guaranteed Optional) -> ()> + switch_enum %2 : $Optional<@callee_guaranteed (@guaranteed Optional) -> ()>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb12 + +bb1(%4 : @owned $@callee_guaranteed (@guaranteed Optional) -> ()): + %5 = convert_escape_to_noescape [not_guaranteed] %4 : $@callee_guaranteed (@guaranteed Optional) -> () to $@noescape @callee_guaranteed (@guaranteed Optional) -> () + %6 = enum $Optional<@noescape @callee_guaranteed (@guaranteed Optional) -> ()>, #Optional.some!enumelt.1, %5 : $@noescape @callee_guaranteed (@guaranteed Optional) -> () + destroy_value %4 : $@callee_guaranteed (@guaranteed Optional) -> () + br bb2(%6 : $Optional<@noescape @callee_guaranteed (@guaranteed Optional) -> ()>) + +bb2(%9 : $Optional<@noescape @callee_guaranteed (@guaranteed Optional) -> ()>): + switch_enum %9 : $Optional<@noescape @callee_guaranteed (@guaranteed Optional) -> ()>, case #Optional.some!enumelt.1: bb3, case #Optional.none!enumelt: bb4 + +bb3(%11 : $@noescape @callee_guaranteed (@guaranteed Optional) -> ()): + %12 = function_ref @$sSSSgIgg_AAIegg_TR : $@convention(thin) (@guaranteed Optional, @noescape @callee_guaranteed (@guaranteed Optional) -> ()) -> () + %13 = partial_apply [callee_guaranteed] %12(%11) : $@convention(thin) (@guaranteed Optional, @noescape @callee_guaranteed (@guaranteed Optional) -> ()) -> () + %14 = mark_dependence %13 : $@callee_guaranteed (@guaranteed Optional) -> () on %11 : $@noescape @callee_guaranteed (@guaranteed Optional) -> () + %15 = copy_value %14 : $@callee_guaranteed (@guaranteed Optional) -> () + %16 = alloc_stack $@block_storage @callee_guaranteed (@guaranteed Optional) -> () + %17 = project_block_storage %16 : $*@block_storage @callee_guaranteed (@guaranteed Optional) -> () + store %15 to [init] %17 : $*@callee_guaranteed (@guaranteed Optional) -> () + %19 = function_ref @$sSSSgIegg_So8FakeNSStringCSgIyBy_TR : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed (@guaranteed Optional) -> (), Optional) -> () + %20 = init_block_storage_header %16 : $*@block_storage @callee_guaranteed (@guaranteed Optional) -> (), invoke %19 : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed (@guaranteed Optional) -> (), Optional) -> (), type $@convention(block) @noescape (Optional) -> () + %21 = copy_block_without_escaping %20 : $@convention(block) @noescape (Optional) -> () withoutEscaping %14 : $@callee_guaranteed (@guaranteed Optional) -> () + %22 = enum $Optional<@convention(block) @noescape (Optional) -> ()>, #Optional.some!enumelt.1, %21 : $@convention(block) @noescape (Optional) -> () + destroy_addr %17 : $*@callee_guaranteed (@guaranteed Optional) -> () + dealloc_stack %16 : $*@block_storage @callee_guaranteed (@guaranteed Optional) -> () + br bb5(%22 : $Optional<@convention(block) @noescape (Optional) -> ()>) + +bb4: + %26 = enum $Optional<@convention(block) @noescape (Optional) -> ()>, #Optional.none!enumelt + br bb5(%26 : $Optional<@convention(block) @noescape (Optional) -> ()>) + +bb5(%28 : @owned $Optional<@convention(block) @noescape (Optional) -> ()>): + %29 = copy_value %1 : $Optional<@callee_guaranteed (@guaranteed Optional) -> ()> + switch_enum %29 : $Optional<@callee_guaranteed (@guaranteed Optional) -> ()>, case #Optional.some!enumelt.1: bb6, case #Optional.none!enumelt: bb11 + +bb6(%31 : @owned $@callee_guaranteed (@guaranteed Optional) -> ()): + %32 = convert_escape_to_noescape [not_guaranteed] %31 : $@callee_guaranteed (@guaranteed Optional) -> () to $@noescape @callee_guaranteed (@guaranteed Optional) -> () + %33 = enum $Optional<@noescape @callee_guaranteed (@guaranteed Optional) -> ()>, #Optional.some!enumelt.1, %32 : $@noescape @callee_guaranteed (@guaranteed Optional) -> () + destroy_value %31 : $@callee_guaranteed (@guaranteed Optional) -> () + br bb7(%33 : $Optional<@noescape @callee_guaranteed (@guaranteed Optional) -> ()>) + +bb7(%36 : $Optional<@noescape @callee_guaranteed (@guaranteed Optional) -> ()>): + switch_enum %36 : $Optional<@noescape @callee_guaranteed (@guaranteed Optional) -> ()>, case #Optional.some!enumelt.1: bb8, case #Optional.none!enumelt: bb9 + +bb8(%38 : $@noescape @callee_guaranteed (@guaranteed Optional) -> ()): + %39 = function_ref @$sSSSgIgg_AAIegg_TR : $@convention(thin) (@guaranteed Optional, @noescape @callee_guaranteed (@guaranteed Optional) -> ()) -> () + %40 = partial_apply [callee_guaranteed] %39(%38) : $@convention(thin) (@guaranteed Optional, @noescape @callee_guaranteed (@guaranteed Optional) -> ()) -> () + %41 = mark_dependence %40 : $@callee_guaranteed (@guaranteed Optional) -> () on %38 : $@noescape @callee_guaranteed (@guaranteed Optional) -> () + %42 = copy_value %41 : $@callee_guaranteed (@guaranteed Optional) -> () + %43 = alloc_stack $@block_storage @callee_guaranteed (@guaranteed Optional) -> () + %44 = project_block_storage %43 : $*@block_storage @callee_guaranteed (@guaranteed Optional) -> () + store %42 to [init] %44 : $*@callee_guaranteed (@guaranteed Optional) -> () + %46 = function_ref @$sSSSgIegg_So8FakeNSStringCSgIyBy_TR : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed (@guaranteed Optional) -> (), Optional) -> () + %47 = init_block_storage_header %43 : $*@block_storage @callee_guaranteed (@guaranteed Optional) -> (), invoke %46 : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed (@guaranteed Optional) -> (), Optional) -> (), type $@convention(block) @noescape (Optional) -> () + %48 = copy_block_without_escaping %47 : $@convention(block) @noescape (Optional) -> () withoutEscaping %41 : $@callee_guaranteed (@guaranteed Optional) -> () + %49 = enum $Optional<@convention(block) @noescape (Optional) -> ()>, #Optional.some!enumelt.1, %48 : $@convention(block) @noescape (Optional) -> () + destroy_addr %44 : $*@callee_guaranteed (@guaranteed Optional) -> () + dealloc_stack %43 : $*@block_storage @callee_guaranteed (@guaranteed Optional) -> () + br bb10(%49 : $Optional<@convention(block) @noescape (Optional) -> ()>) + +bb9: + %53 = enum $Optional<@convention(block) @noescape (Optional) -> ()>, #Optional.none!enumelt + br bb10(%53 : $Optional<@convention(block) @noescape (Optional) -> ()>) + +bb10(%55 : @owned $Optional<@convention(block) @noescape (Optional) -> ()>): + %56 = string_literal utf8 "Foobar" + %57 = integer_literal $Builtin.Word, 6 + %58 = integer_literal $Builtin.Int1, -1 + %59 = metatype $@thin String.Type + %60 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String + %61 = apply %60(%56, %57, %58, %59) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String + %62 = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8FakeNSStringCyF : $@convention(method) (@guaranteed String) -> @owned FakeNSString + %63 = begin_borrow %61 : $String + %64 = apply %62(%63) : $@convention(method) (@guaranteed String) -> @owned FakeNSString + end_borrow %63 : $String + %66 = enum $Optional, #Optional.some!enumelt.1, %64 : $FakeNSString + destroy_value %61 : $String + %68 = function_ref @noescapeBlock3 : $@convention(c) (Optional<@convention(block) @noescape (Optional) -> ()>, Optional<@convention(block) @noescape (Optional) -> ()>, Optional) -> () + %69 = apply %68(%28, %55, %66) : $@convention(c) (Optional<@convention(block) @noescape (Optional) -> ()>, Optional<@convention(block) @noescape (Optional) -> ()>, Optional) -> () + destroy_value %66 : $Optional + destroy_value %55 : $Optional<@convention(block) @noescape (Optional) -> ()> + destroy_value %28 : $Optional<@convention(block) @noescape (Optional) -> ()> + %73 = tuple () + return %73 : $() + +bb11: + %75 = enum $Optional<@noescape @callee_guaranteed (@guaranteed Optional) -> ()>, #Optional.none!enumelt + br bb7(%75 : $Optional<@noescape @callee_guaranteed (@guaranteed Optional) -> ()>) + +bb12: + %77 = enum $Optional<@noescape @callee_guaranteed (@guaranteed Optional) -> ()>, #Optional.none!enumelt + br bb2(%77 : $Optional<@noescape @callee_guaranteed (@guaranteed Optional) -> ()>) +} diff --git a/test/SILOptimizer/definite-init-convert-to-escape.swift b/test/SILOptimizer/definite-init-convert-to-escape.swift index 26eacb35976a0..3271ecaad87e6 100644 --- a/test/SILOptimizer/definite-init-convert-to-escape.swift +++ b/test/SILOptimizer/definite-init-convert-to-escape.swift @@ -46,8 +46,8 @@ public func returnOptionalEscape() -> (() ->())? // CHECK: switch_enum [[V1]] : $Optional<{{.*}}>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]] // // CHECK: [[SOME_BB]]([[V2:%.*]] : $@callee_guaranteed () -> ()): -// CHECK: [[CVT_MARK_DEP:%.*]] = mark_dependence [[V2]] : $@callee_guaranteed () -> () on [[V1]] -// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[CVT_MARK_DEP]] +// CHECK: [[V1_UNWRAPPED:%.*]] = unchecked_enum_data [[V1]] +// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[V1_UNWRAPPED]] // CHECK: [[SOME:%.*]] = enum $Optional<{{.*}}>, #Optional.some!enumelt.1, [[CVT]] // CHECK: strong_release [[V2]] // CHECK: br [[NEXT_BB:bb[0-9]+]]([[SOME]] : From 4b5a85a34dfa04678d80871f148ade42f130fc68 Mon Sep 17 00:00:00 2001 From: "Steve (Numerics) Canon" Date: Mon, 10 Jun 2019 11:50:36 -0400 Subject: [PATCH 080/112] Fix a bug in root and add a test case for it. For odd roots of negative values, we need to take the root of the *magnitude* of the number to avoid a NaN from the platform's implementation of `pow`, then restore the sign afterwards. We had the basic logic in place already, but were missing the step of taking the magnitude first. Also modified a test case to find this error. --- stdlib/public/core/MathFunctions.swift.gyb | 2 +- test/stdlib/MathFunctions.swift.gyb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/public/core/MathFunctions.swift.gyb b/stdlib/public/core/MathFunctions.swift.gyb index 790539c69507d..d2244b20c1627 100644 --- a/stdlib/public/core/MathFunctions.swift.gyb +++ b/stdlib/public/core/MathFunctions.swift.gyb @@ -95,7 +95,7 @@ extension ${Self}: ElementaryFunctions { guard x >= 0 || n % 2 != 0 else { return .nan } // TODO: this implementation isn't quite right for n so large that // the conversion to `${Self}` rounds. - return ${Self}(signOf: x, magnitudeOf: pow(x, 1/${Self}(n))) + return ${Self}(signOf: x, magnitudeOf: pow(x.magnitude, 1/${Self}(n))) } @_alwaysEmitIntoClient diff --git a/test/stdlib/MathFunctions.swift.gyb b/test/stdlib/MathFunctions.swift.gyb index 11c63d056e9d1..b784db418a09e 100644 --- a/test/stdlib/MathFunctions.swift.gyb +++ b/test/stdlib/MathFunctions.swift.gyb @@ -72,7 +72,7 @@ internal extension ElementaryFunctions where Self: BinaryFloatingPoint { expectEqualWithTolerance(-1.415037499278843818546261056052183491, Self.log2(0.375)) expectEqualWithTolerance(0.3184537311185346158102472135905995955, Self.log1p(0.375)) expectEqualWithTolerance(-0.425968732272281148346188780918363771, Self.log10(0.375)) - expectEqualWithTolerance(0.7211247851537041911608191553900547941, Self.root(0.375, 3)) + expectEqualWithTolerance(-0.7211247851537041911608191553900547941, Self.root(-0.375, 3)) expectEqualWithTolerance(0.6123724356957945245493210186764728479, Self.sqrt(0.375)) expectEqualWithTolerance(0.54171335479545025876069682133938570, Self.pow(0.375, 0.625)) expectEqualWithTolerance(-0.052734375, Self.pow(-0.375, 3)) From bd6fa67f39c135bebb1ebc25006bd6f0d05ade38 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Mon, 10 Jun 2019 08:52:20 -0700 Subject: [PATCH 081/112] Fix generic class constraint keypath --- lib/IRGen/GenKeyPath.cpp | 9 ++++++--- test/IRGen/keypaths.sil | 12 ++++++++++++ test/Interpreter/keypath.swift | 22 +++++++++++++++++++++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp index db240198c8f74..555ce43d44a9a 100644 --- a/lib/IRGen/GenKeyPath.cpp +++ b/lib/IRGen/GenKeyPath.cpp @@ -777,11 +777,14 @@ emitKeyPathComponent(IRGenModule &IGM, assert(currentBaseTy->getClassOrBoundGenericClass() == propertyBaseDecl); loweredClassTy = IGM.getLoweredType(AbstractionPattern::getOpaque(), currentBaseTy); - - auto loweredBaseContextTy = SILType::getPrimitiveObjectType( + + auto loweredBaseContextTy = + SILType::getPrimitiveObjectType(loweredClassTy.getASTType()); + if (!loweredClassTy.getASTType()->hasArchetype()) + loweredBaseContextTy = SILType::getPrimitiveObjectType( GenericEnvironment::mapTypeIntoContext(genericEnv, loweredClassTy.getASTType()) - ->getCanonicalType()); + ->getCanonicalType()); switch (getClassFieldAccess(IGM, loweredBaseContextTy, property)) { case FieldAccess::ConstantDirect: { diff --git a/test/IRGen/keypaths.sil b/test/IRGen/keypaths.sil index dd232e87ed240..926dcbc0f8d73 100644 --- a/test/IRGen/keypaths.sil +++ b/test/IRGen/keypaths.sil @@ -553,6 +553,11 @@ entry: return undef : $() } +public class GC2 { + public final var x: T + public var y: String +} + sil @class_constrainted : $@convention(thin) () -> () { bb0: %k = keypath $KeyPath, <τ_0_0 where τ_0_0 : C> (root $τ_0_0; stored_property #C.y : $String) @@ -560,6 +565,13 @@ bb0: return %t : $() } +sil @generic_class_constrainted : $@convention(thin) > () -> () { +bb0: + %k = keypath $KeyPath, <τ_0_0, τ_0_1 where τ_0_1 : GC2<τ_0_0>> (root $τ_0_1; stored_property #GC2.y : $String) + %t = tuple () + return %t : $() +} + sil @s_get : $@convention(thin) (@in_guaranteed A, UnsafeRawPointer) -> @out B sil @s_set : $@convention(thin) (@in_guaranteed B, @in_guaranteed A, UnsafeRawPointer) -> () sil @s_equals : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool diff --git a/test/Interpreter/keypath.swift b/test/Interpreter/keypath.swift index bd39a73cedca5..a1e0c78552235 100644 --- a/test/Interpreter/keypath.swift +++ b/test/Interpreter/keypath.swift @@ -1,4 +1,4 @@ -// RUN: %target-run-simple-swift +// RUN: %target-run-simple-swift | %FileCheck %s // REQUIRES: executable_test class MyLabel { @@ -24,5 +24,25 @@ extension Container where V: Controller { return useKeyPath(\.label) } } + // CHECK: label print(Container(Controller()).test()) + +public class GenericController { + init(_ u: U) { + self.u = u + } + + var u : U + fileprivate let label = MyLabel() +} + +public func generic_class_constrainted_keypath(_ c: V) where V : GenericController { + let kp = \V.label + print(kp) + print(c[keyPath: kp].text) +} + +// CHECK: Swift.KeyPath, main.MyLabel> +// CHECK: label +generic_class_constrainted_keypath(GenericController(5)) From 9cba37f39c46377215a4ea73c1d2905403d49b32 Mon Sep 17 00:00:00 2001 From: Phill Farrugia Date: Mon, 10 Jun 2019 09:58:21 -0700 Subject: [PATCH 082/112] Apply Override Fixit to Variable Declarations --- lib/Sema/TypeCheckDeclOverride.cpp | 17 +++++++++-------- test/attr/attr_override.swift | 5 +++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index 9c010bb64cc66..f391e37d007af 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -1634,18 +1634,19 @@ static bool checkSingleOverride(ValueDecl *override, ValueDecl *base) { overrideRequiresKeyword(base) != OverrideRequiresKeyword::Never && !override->isImplicit() && override->getDeclContext()->getParentSourceFile()) { - // FIXME: rdar://16320042 - For properties, we don't have a useful - // location for the 'var' token. Instead of emitting a bogus fixit, only - // emit the fixit for 'func's. auto theDiag = overrideRequiresKeyword(base) == OverrideRequiresKeyword::Always ? diag::missing_override : diag::missing_override_warn; - if (!isa(override)) - diags.diagnose(override, theDiag) - .fixItInsert(override->getStartLoc(), "override "); - else - diags.diagnose(override, theDiag); + + auto diagLoc = override->getStartLoc(); + // If dynamic cast to VarDecl succeeds, use the location of its parent + // pattern binding which will return the VarLoc. + if (auto VD = dyn_cast(override)) { + diagLoc = VD->getParentPatternBinding()->getLoc(); + } + + diags.diagnose(override, theDiag).fixItInsert(diagLoc, "override "); diags.diagnose(base, diag::overridden_here); } diff --git a/test/attr/attr_override.swift b/test/attr/attr_override.swift index c9b051ee4377d..7210c576fb8d6 100644 --- a/test/attr/attr_override.swift +++ b/test/attr/attr_override.swift @@ -29,6 +29,7 @@ class A { var v1: Int { return 5 } var v2: Int { return 5 } // expected-note{{overridden declaration is here}} + internal var v21: Int { return 5 } // expected-note{{overridden declaration is here}} var v4: String { return "hello" }// expected-note{{attempt to override property here}} var v5: A { return self } var v6: A { return self } @@ -93,9 +94,9 @@ class B : A { override func f0() { } func f1() { } // expected-error{{overriding declaration requires an 'override' keyword}}{{3-3=override }} override func f2() { } // expected-error{{method does not override any method from its superclass}} - override var v1: Int { return 5 } - var v2: Int { return 5 } // expected-error{{overriding declaration requires an 'override' keyword}} + var v2: Int { return 5 } // expected-error{{overriding declaration requires an 'override' keyword}}{{3-3=override }} + internal var v21: Int { return 5 } // expected-error{{overriding declaration requires an 'override' keyword}}{{12-12=override }} override var v3: Int { return 5 } // expected-error{{property does not override any property from its superclass}} override var v4: Int { return 5 } // expected-error{{property 'v4' with type 'Int' cannot override a property with type 'String'}} From 12c7cead9d4fa2739b00bffa85b687a35db73b6c Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 10 Jun 2019 12:25:06 -0700 Subject: [PATCH 083/112] test: make the StdlibUnittest.Common pass on Windows This adjusts the paths in the test to support the Linux and Windows path separators. Loosen the test to accept the interleaved stdout output on Windows. --- validation-test/StdlibUnittest/Common.swift | 32 +++++++++++---------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/validation-test/StdlibUnittest/Common.swift b/validation-test/StdlibUnittest/Common.swift index aeefc52375aa1..f233d92bc79f0 100644 --- a/validation-test/StdlibUnittest/Common.swift +++ b/validation-test/StdlibUnittest/Common.swift @@ -353,7 +353,7 @@ TestSuiteWithSetUp.test("passes") { // CHECK: [ RUN ] TestSuiteWithSetUp.fails // CHECK: stdout>>> setUp -// CHECK-NEXT: stdout>>> check failed at {{.*}}/StdlibUnittest/Common.swift, line +// CHECK-NEXT: stdout>>> check failed at {{.*}}{{[/\\]}}StdlibUnittest{{[/\\]}}Common.swift, line // CHECK: stdout>>> test body // CHECK: [ FAIL ] TestSuiteWithSetUp.fails TestSuiteWithSetUp.test("fails") { @@ -366,7 +366,7 @@ TestSuiteWithSetUp.test("fails") { // CHECK: [ OK ] TestSuiteWithSetUp.passesFails/parameterized/0 // CHECK: [ RUN ] TestSuiteWithSetUp.passesFails/parameterized/1 // CHECK: stdout>>> setUp -// CHECK-NEXT: stdout>>> check failed at {{.*}}/StdlibUnittest/Common.swift, line +// CHECK-NEXT: stdout>>> check failed at {{.*}}{{[/\\]}}StdlibUnittest{{[/\\]}}Common.swift, line // CHECK: stdout>>> test body // CHECK: [ FAIL ] TestSuiteWithSetUp.passesFails/parameterized/1 TestSuiteWithSetUp.test("passesFails/parameterized") @@ -398,7 +398,7 @@ TestSuiteWithTearDown.test("passes") { // CHECK: [ RUN ] TestSuiteWithTearDown.fails // CHECK: stdout>>> test body // CHECK: stdout>>> tearDown -// CHECK-NEXT: stdout>>> check failed at {{.*}}/StdlibUnittest/Common.swift, line +// CHECK-NEXT: stdout>>> check failed at {{.*}}{{[/\\]}}StdlibUnittest{{[/\\]}}Common.swift, line // CHECK: [ FAIL ] TestSuiteWithTearDown.fails TestSuiteWithTearDown.test("fails") { print("test body") @@ -412,7 +412,7 @@ TestSuiteWithTearDown.test("fails") { // CHECK: [ RUN ] TestSuiteWithTearDown.passesFails/parameterized/1 // CHECK: stdout>>> test body // CHECK: stdout>>> tearDown -// CHECK-NEXT: stdout>>> check failed at {{.*}}/StdlibUnittest/Common.swift, line +// CHECK-NEXT: stdout>>> check failed at {{.*}}{{[/\\]}}StdlibUnittest{{[/\\]}}Common.swift, line // CHECK: [ FAIL ] TestSuiteWithTearDown.passesFails/parameterized/1 TestSuiteWithTearDown.test("passesFails/parameterized") .forEach(in: [1010, 2020]) { @@ -437,7 +437,7 @@ AssertionsTestSuite.test("expectFailure/Pass") { } } // CHECK: [ RUN ] Assertions.expectFailure/Pass -// CHECK-NEXT: stdout>>> check failed at {{.*}}/StdlibUnittest/Common.swift, line +// CHECK-NEXT: stdout>>> check failed at {{.*}}{{[/\\]}}StdlibUnittest{{[/\\]}}Common.swift, line // CHECK: stdout>>> expected: 1 (of type Swift.Int) // CHECK: stdout>>> actual: 2 (of type Swift.Int) // CHECK: [ OK ] Assertions.expectFailure/Pass @@ -451,7 +451,7 @@ AssertionsTestSuite.test("expectFailure/UXPass") } } // CHECK: [ RUN ] Assertions.expectFailure/UXPass ({{X}}FAIL: [Custom(reason: test)]) -// CHECK-NEXT: stdout>>> check failed at {{.*}}/StdlibUnittest/Common.swift, line +// CHECK-NEXT: stdout>>> check failed at {{.*}}{{[/\\]}}StdlibUnittest{{[/\\]}}Common.swift, line // CHECK: stdout>>> expected: 1 (of type Swift.Int) // CHECK: stdout>>> actual: 2 (of type Swift.Int) // CHECK: [ UXPASS ] Assertions.expectFailure/UXPass @@ -462,7 +462,7 @@ AssertionsTestSuite.test("expectFailure/Fail") { } } // CHECK: [ RUN ] Assertions.expectFailure/Fail -// CHECK-NEXT: stdout>>> check failed at {{.*}}/StdlibUnittest/Common.swift, line +// CHECK-NEXT: stdout>>> check failed at {{.*}}{{[/\\]}}StdlibUnittest{{[/\\]}}Common.swift, line // CHECK: stdout>>> expected: true // CHECK: stdout>>> running `body` should produce an expected failure // CHECK: [ FAIL ] Assertions.expectFailure/Fail @@ -475,7 +475,7 @@ AssertionsTestSuite.test("expectFailure/XFail") } } // CHECK: [ RUN ] Assertions.expectFailure/XFail ({{X}}FAIL: [Custom(reason: test)]) -// CHECK-NEXT: stdout>>> check failed at {{.*}}/StdlibUnittest/Common.swift, line +// CHECK-NEXT: stdout>>> check failed at {{.*}}{{[/\\]}}StdlibUnittest{{[/\\]}}Common.swift, line // CHECK: stdout>>> expected: true // CHECK: stdout>>> running `body` should produce an expected failure // CHECK: [ XFAIL ] Assertions.expectFailure/XFail @@ -488,10 +488,10 @@ AssertionsTestSuite.test("expectFailure/AfterFailure/Fail") { } } // CHECK: [ RUN ] Assertions.expectFailure/AfterFailure/Fail -// CHECK-NEXT: stdout>>> check failed at {{.*}}/StdlibUnittest/Common.swift, line +// CHECK-NEXT: stdout>>> check failed at {{.*}}{{[/\\]}}StdlibUnittest{{[/\\]}}Common.swift, line // CHECK: stdout>>> expected: 1 (of type Swift.Int) // CHECK: stdout>>> actual: 2 (of type Swift.Int) -// CHECK: stdout>>> check failed at {{.*}}/StdlibUnittest/Common.swift, line +// CHECK: stdout>>> check failed at {{.*}}{{[/\\]}}StdlibUnittest{{[/\\]}}Common.swift, line // CHECK: stdout>>> expected: 3 (of type Swift.Int) // CHECK: stdout>>> actual: 4 (of type Swift.Int) // CHECK: [ FAIL ] Assertions.expectFailure/AfterFailure/Fail @@ -506,10 +506,10 @@ AssertionsTestSuite.test("expectFailure/AfterFailure/XFail") } } // CHECK: [ RUN ] Assertions.expectFailure/AfterFailure/XFail ({{X}}FAIL: [Custom(reason: test)]) -// CHECK-NEXT: stdout>>> check failed at {{.*}}/StdlibUnittest/Common.swift, line +// CHECK-NEXT: stdout>>> check failed at {{.*}}{{[/\\]}}StdlibUnittest{{[/\\]}}Common.swift, line // CHECK: stdout>>> expected: 1 (of type Swift.Int) // CHECK: stdout>>> actual: 2 (of type Swift.Int) -// CHECK: stdout>>> check failed at {{.*}}/StdlibUnittest/Common.swift, line +// CHECK: stdout>>> check failed at {{.*}}{{[/\\]}}StdlibUnittest{{[/\\]}}Common.swift, line // CHECK: stdout>>> expected: 3 (of type Swift.Int) // CHECK: stdout>>> actual: 4 (of type Swift.Int) // CHECK: [ XFAIL ] Assertions.expectFailure/AfterFailure/XFail @@ -518,7 +518,7 @@ AssertionsTestSuite.test("expectUnreachable") { expectUnreachable() } // CHECK: [ RUN ] Assertions.expectUnreachable -// CHECK-NEXT: stdout>>> check failed at {{.*}}/StdlibUnittest/Common.swift, line +// CHECK-NEXT: stdout>>> check failed at {{.*}}{{[/\\]}}StdlibUnittest{{[/\\]}}Common.swift, line // CHECK: stdout>>> this code should not be executed // CHECK: [ FAIL ] Assertions.expectUnreachable @@ -582,7 +582,8 @@ AssertionsTestSuite.test("expectTrapping(_: Bound, in: RangeProtocol)") { expectTrapping(0, in: 1..<10) } // CHECK: [ RUN ] Assertions.expectTrapping(_: Bound, in: RangeProtocol) -// CHECK-NEXT: stdout>>> check failed at {{.*}}.swift, line [[@LINE-3]] +// stderr>>> CRASHED: SIGABRT +// CHECK: stdout>>> check failed at {{.*}}.swift, line [[@LINE-4]] // CHECK: stdout>>> 0 in 1..<10{{$}} // CHECK: the test crashed unexpectedly // CHECK: [ FAIL ] Assertions.expectTrapping(_: Bound, in: RangeProtocol) @@ -591,7 +592,8 @@ AssertionsTestSuite.test("expectTrapping(_: RangeProtocol, in: RangeProtocol)") expectTrapping(0..<5, in: 1..<10) } // CHECK: [ RUN ] Assertions.expectTrapping(_: RangeProtocol, in: RangeProtocol) -// CHECK-NEXT: stdout>>> check failed at {{.*}}.swift, line [[@LINE-3]] +// stderr>>> CRASHED: SIGABRT +// CHECK: stdout>>> check failed at {{.*}}.swift, line [[@LINE-4]] // CHECK: stdout>>> 0..<5 in 1..<10{{$}} // CHECK: the test crashed unexpectedly // CHECK: [ FAIL ] Assertions.expectTrapping(_: RangeProtocol, in: RangeProtocol) From 6fd332d62ca1152cdf3175934f6d82f322b3b232 Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Tue, 4 Jun 2019 13:28:50 -0700 Subject: [PATCH 084/112] Doc-serialization: skip declarations with double-underscore as name prefix Double-underscored names suggest the symbols aren't supposed to be used by framework clients. This patch excludes the doc-comments of these symbols in swiftdoc files. rdar://51468650 --- include/swift/AST/ParameterList.h | 3 +- lib/AST/Decl.cpp | 26 +++++++++--------- lib/Serialization/SerializeDoc.cpp | 35 ++++++++++++++++++++++-- test/Serialization/comments-hidden.swift | 23 ++++++++++++++++ 4 files changed, 71 insertions(+), 16 deletions(-) diff --git a/include/swift/AST/ParameterList.h b/include/swift/AST/ParameterList.h index 8e5cb39e8e810..7fd7dfac1e426 100644 --- a/include/swift/AST/ParameterList.h +++ b/include/swift/AST/ParameterList.h @@ -97,7 +97,8 @@ class alignas(ParamDecl *) ParameterList final : const ParamDecl *operator[](unsigned i) const { return get(i); } ParamDecl *&operator[](unsigned i) { return get(i); } - + bool hasInternalParameter(StringRef prefix) const; + /// Change the DeclContext of any contained parameters to the specified /// DeclContext. void setDeclContextOfParamDecls(DeclContext *DC); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 99a2860b0f7d0..8442aed667986 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -531,6 +531,17 @@ bool AbstractFunctionDecl::isTransparent() const { return false; } +bool ParameterList::hasInternalParameter(StringRef Prefix) const { + for (auto param : *this) { + if (param->hasName() && param->getNameStr().startswith(Prefix)) + return true; + auto argName = param->getArgumentName(); + if (!argName.empty() && argName.str().startswith(Prefix)) + return true; + } + return false; +} + bool Decl::isPrivateStdlibDecl(bool treatNonBuiltinProtocolsAsPublic) const { const Decl *D = this; if (auto ExtD = dyn_cast(D)) { @@ -552,26 +563,15 @@ bool Decl::isPrivateStdlibDecl(bool treatNonBuiltinProtocolsAsPublic) const { FU->getKind() != FileUnitKind::SerializedAST) return false; - auto hasInternalParameter = [](const ParameterList *params) -> bool { - for (auto param : *params) { - if (param->hasName() && param->getNameStr().startswith("_")) - return true; - auto argName = param->getArgumentName(); - if (!argName.empty() && argName.str().startswith("_")) - return true; - } - return false; - }; - if (auto AFD = dyn_cast(D)) { // If it's a function with a parameter with leading underscore, it's a // private function. - if (hasInternalParameter(AFD->getParameters())) + if (AFD->getParameters()->hasInternalParameter("_")) return true; } if (auto SubscriptD = dyn_cast(D)) { - if (hasInternalParameter(SubscriptD->getIndices())) + if (SubscriptD->getIndices()->hasInternalParameter("_")) return true; } diff --git a/lib/Serialization/SerializeDoc.cpp b/lib/Serialization/SerializeDoc.cpp index b42ea9ad00974..0b18ba500f8ed 100644 --- a/lib/Serialization/SerializeDoc.cpp +++ b/lib/Serialization/SerializeDoc.cpp @@ -17,6 +17,7 @@ #include "swift/AST/ASTWalker.h" #include "swift/AST/DiagnosticsCommon.h" #include "swift/AST/Module.h" +#include "swift/AST/ParameterList.h" #include "swift/AST/USRGeneration.h" #include "swift/Basic/SourceManager.h" #include "llvm/Support/DJB.h" @@ -354,7 +355,7 @@ static void writeDeclCommentTable( DeclGroupNameContext &GroupContext; unsigned SourceOrder; - DeclCommentTableWriter(DeclGroupNameContext &GroupContext) : + DeclCommentTableWriter(DeclGroupNameContext &GroupContext): GroupContext(GroupContext) {} void resetSourceOrder() { @@ -367,7 +368,7 @@ static void writeDeclCommentTable( return StringRef(Mem, String.size()); } - bool shouldSerializeDoc(Decl *D) { + bool shouldIncludeDecl(Decl *D) { if (auto *VD = dyn_cast(D)) { // Skip the decl if it's not visible to clients. The use of // getEffectiveAccess is unusual here; we want to take the testability @@ -377,7 +378,35 @@ static void writeDeclCommentTable( if (VD->getEffectiveAccess() < swift::AccessLevel::Public) return false; } + // Exclude decls with double-underscored names, either in arguments or + // base names. + StringRef Prefix = "__"; + if (auto *ED = dyn_cast(D)) { + return shouldIncludeDecl(ED->getExtendedNominal()); + } + if (auto AFD = dyn_cast(D)) { + // If it's a function with a parameter with leading double underscore, + // it's a private function. + if (AFD->getParameters()->hasInternalParameter(Prefix)) + return false; + } + + if (auto SubscriptD = dyn_cast(D)) { + if (SubscriptD->getIndices()->hasInternalParameter(Prefix)) + return false; + } + if (auto *VD = dyn_cast(D)) { + auto Name = VD->getBaseName(); + if (!Name.isSpecial() && + Name.getIdentifier().str().startswith(Prefix)) { + return false; + } + } + return true; + } + + bool shouldSerializeDoc(Decl *D) { // When building the stdlib we intend to serialize unusual comments. // This situation is represented by GroupContext.isEnable(). In that // case, we perform more serialization to keep track of source order. @@ -409,6 +438,8 @@ static void writeDeclCommentTable( } bool walkToDeclPre(Decl *D) override { + if (!shouldIncludeDecl(D)) + return false; if (!shouldSerializeDoc(D)) return true; if (auto *ED = dyn_cast(D)) { diff --git a/test/Serialization/comments-hidden.swift b/test/Serialization/comments-hidden.swift index b24e6d378b4bd..e4b6580df0c78 100644 --- a/test/Serialization/comments-hidden.swift +++ b/test/Serialization/comments-hidden.swift @@ -18,10 +18,29 @@ public class PublicClass { /// Public Function Documentation public func f_public() { } + /// Public Init Documentation + public init(_ name: String) {} + /// Public Subscript Documentation + public subscript(_ name: String) -> Int { return 0 } /// Internal Function Documentation NotForNormal internal func f_internal() { } /// Private Function Documentation NotForNormal NotForTesting private func f_private() { } + /// Public Filter Function Documentation NotForNormal NotForTesting + public func __UnderscoredPublic() {} + /// Public Filter Init Documentation NotForNormal NotForTesting + public init(__label name: String) {} + /// Public Filter Subscript Documentation NotForNormal NotForFiltering + public subscript(__label name: String) -> Int { return 0 } + /// Public Filter Init Documentation NotForNormal NotForTesting + public init(label __name: String) {} + /// Public Filter Subscript Documentation NotForNormal NotForTesting + public subscript(label __name: String) -> Int { return 0 } +} + +public extension PublicClass { + /// Public Filter Operator Documentation NotForNormal NotForTesting + static func -=(__lhs: inout PublicClass, __rhs: PublicClass) {} } /// InternalClass Documentation NotForNormal @@ -42,10 +61,14 @@ private class PrivateClass { // NORMAL-NEGATIVE-NOT: NotForTesting // NORMAL: PublicClass Documentation // NORMAL: Public Function Documentation +// NORMAL: Public Init Documentation +// NORMAL: Public Subscript Documentation // TESTING-NEGATIVE-NOT: NotForTesting // TESTING: PublicClass Documentation // TESTING: Public Function Documentation +// TESTINH: Public Init Documentation +// TESTING: Public Subscript Documentation // TESTING: Internal Function Documentation // TESTING: InternalClass Documentation // TESTING: Internal Function Documentation From fe32ba1a8657da03ed0b8c1e777bd5cf29f58726 Mon Sep 17 00:00:00 2001 From: John Holdsworth Date: Mon, 10 Jun 2019 22:12:24 +0100 Subject: [PATCH 085/112] Add missing newlines --- lib/SIL/SILUndef.cpp | 2 +- lib/SILGen/SILGenLazyConformance.cpp | 2 +- lib/SILOptimizer/Utils/Devirtualize.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/SIL/SILUndef.cpp b/lib/SIL/SILUndef.cpp index 414ee1ab23308..ab2166051a9fa 100644 --- a/lib/SIL/SILUndef.cpp +++ b/lib/SIL/SILUndef.cpp @@ -35,4 +35,4 @@ SILUndef *SILUndef::get(SILType ty, SILModule &m, ValueOwnershipKind ownershipKi SILUndef *SILUndef::get(SILType ty, const SILFunction &f) { auto ownershipKind = getOwnershipKindForUndef(ty, f); return SILUndef::get(ty, f.getModule(), ownershipKind); -} \ No newline at end of file +} diff --git a/lib/SILGen/SILGenLazyConformance.cpp b/lib/SILGen/SILGenLazyConformance.cpp index 36d241d5d2990..fb614e615a9d1 100644 --- a/lib/SILGen/SILGenLazyConformance.cpp +++ b/lib/SILGen/SILGenLazyConformance.cpp @@ -359,4 +359,4 @@ void SILGenModule::emitLazyConformancesForType(NominalTypeDecl *NTD) { useConformancesFromType(reqt.getSecondType()->getCanonicalType()); } } -} \ No newline at end of file +} diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp index 89df5f54f2547..67eb27e2afcfe 100644 --- a/lib/SILOptimizer/Utils/Devirtualize.cpp +++ b/lib/SILOptimizer/Utils/Devirtualize.cpp @@ -1218,4 +1218,4 @@ bool swift::canDevirtualizeApply(FullApplySite AI, ClassHierarchyAnalysis *CHA) } return false; -} \ No newline at end of file +} From 2a76bcb032fef973f6239d1ab6dda5e4c0f2d3e3 Mon Sep 17 00:00:00 2001 From: Gwen Mittertreiner Date: Mon, 10 Jun 2019 14:12:31 -0700 Subject: [PATCH 086/112] Add WinSDK constants to get Symlink Information Added FSCTL_GET_REPARSE_POINT, FSCTL_SET_REPARSE_POINT, FSCTL_DELETE_REPARSE_POINT to allow manipulation of reparse points via DeviceIoControl --- stdlib/public/Windows/WinSDK.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stdlib/public/Windows/WinSDK.swift b/stdlib/public/Windows/WinSDK.swift index 19c01ad81f501..75bbd45b24ccc 100644 --- a/stdlib/public/Windows/WinSDK.swift +++ b/stdlib/public/Windows/WinSDK.swift @@ -36,6 +36,11 @@ public let INVALID_HANDLE_VALUE: HANDLE = HANDLE(bitPattern: -1)! public let FOF_NO_UI: FILEOP_FLAGS = FILEOP_FLAGS(FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR) +// winioctl.h +public let FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4 +public let FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8 +public let FSCTL_DELETE_REPARSE_POINT: DWORD = 0x900ac + // WinSock2.h public let INVALID_SOCKET: SOCKET = SOCKET(bitPattern: -1) public let FIONBIO: Int32 = Int32(bitPattern: 0x8004667e) From 105e4ad592b4a462b03e68136b2d8e39ff40ab8e Mon Sep 17 00:00:00 2001 From: Julian Lettner Date: Mon, 13 May 2019 17:14:12 -0700 Subject: [PATCH 087/112] [TSan] Add positive test for TSan + Dispatch on Linux 1) Enable tests that use `import Dispatch` on Linux. Add substitution `%import-libdispatch` that needs to be used for all cross-platform tests (i.e., tests that are intended to be run on other platforms than Darwin) that do `import Dispatch` or enable thread sanitizer. 2) Make sure as many existing Dispatch and TSan tests as possible run on Linux. Mark tests that would require substantial work with `UNSUPPORTED: OS=linux-gnu`. 3) Add integration-style Swift test that shows that TSan finds a simple race when using `Dispatch.async` incorrectly. A more complete test suite for TSan's libdispatch support lives on the LLVM/compiler-rt side. rdar://problem/49177535 --- test/ClangImporter/Dispatch_test.swift | 1 + test/IRGen/tsan-attributes.swift | 5 +- test/IRGen/tsan_coroutines.swift | 7 ++- test/Profiler/instrprof_tsan.swift | 4 +- test/Runtime/lazy_witness_table_cycle.swift | 2 +- test/SILGen/tsan_instrumentation.swift | 6 +-- test/Sanitizers/tsan-emptyarraystorage.swift | 1 + test/Sanitizers/tsan-libdispatch.swift | 43 +++++++++++++++ .../tsan-norace-block-release.swift | 22 ++++---- .../tsan-norace-deinit-run-time.swift | 23 ++++---- test/Sanitizers/tsan.swift | 2 +- test/lit.cfg | 53 ++++++++++--------- test/stdlib/Dispatch.swift | 1 + test/stdlib/DispatchData.swift | 7 +-- test/stdlib/DispatchDeprecationMacOS.swift | 3 +- test/stdlib/DispatchDeprecationWatchOS.swift | 3 +- test/stdlib/DispatchRenames.swift | 2 +- test/stdlib/DispatchTypes.swift | 1 + .../weak-reference-racetests-dispatch.swift | 3 +- .../Sanitizers/tsan-ignores-arc-locks.swift | 2 +- validation-test/Sanitizers/tsan-inout.swift | 22 ++++++-- .../Sanitizers/tsan-type-metadata.swift | 3 +- .../Sanitizers/witness_table_lookup.swift | 2 +- 23 files changed, 143 insertions(+), 75 deletions(-) create mode 100644 test/Sanitizers/tsan-libdispatch.swift diff --git a/test/ClangImporter/Dispatch_test.swift b/test/ClangImporter/Dispatch_test.swift index e444d88ac03a4..3d32ca879c0f4 100644 --- a/test/ClangImporter/Dispatch_test.swift +++ b/test/ClangImporter/Dispatch_test.swift @@ -1,6 +1,7 @@ // RUN: %target-typecheck-verify-swift // REQUIRES: libdispatch +// UNSUPPORTED: OS=linux-gnu import Dispatch diff --git a/test/IRGen/tsan-attributes.swift b/test/IRGen/tsan-attributes.swift index 823cc5bcd859c..74b652b0a6e5c 100644 --- a/test/IRGen/tsan-attributes.swift +++ b/test/IRGen/tsan-attributes.swift @@ -2,9 +2,8 @@ // RUN: %target-swift-frontend -emit-ir -sanitize=thread %s | %FileCheck %s -check-prefix=TSAN -// TSan is currently only supported on 64 bit mac and simulators. -// (We do not test the simulators here.) -// REQUIRES: CPU=x86_64, OS=macosx +// TSan is only supported on 64 bit. +// REQUIRES: PTRSIZE=64 // TSAN: define {{.*}} @"$s4main4testyyF"() [[DEFAULT_ATTRS:#[0-9]+]] public func test() { diff --git a/test/IRGen/tsan_coroutines.swift b/test/IRGen/tsan_coroutines.swift index 5cb2a921d9f6c..5c0b053fcd13b 100644 --- a/test/IRGen/tsan_coroutines.swift +++ b/test/IRGen/tsan_coroutines.swift @@ -1,9 +1,8 @@ // This test case used to crash when tsan ran before co-routine lowering. // RUN: %target-swift-frontend -emit-ir -sanitize=thread %s | %FileCheck %s -// TSan is currently only supported on 64 bit mac and simulators. -// (We do not test the simulators here.) -// REQUIRES: CPU=x86_64, OS=macosx +// TSan is only supported on 64 bit. +// REQUIRES: PTRSIZE=64 public class C { } @@ -23,7 +22,7 @@ extension Foobar { } // We used to crash emitting the subscript function. - // CHECK: define swiftcc { i8*, %T15tsan_coroutines1CC* } @"$s15tsan_coroutines6FoobarVyAA1CCAC5IndexVcir" + // CHECK: define{{( dllexport| protected)?}} swiftcc { i8*, %T15tsan_coroutines1CC* } @"$s15tsan_coroutines6FoobarVyAA1CCAC5IndexVcir" @_borrowed public subscript(position: Index) -> C { return things.values[position.myIndex] diff --git a/test/Profiler/instrprof_tsan.swift b/test/Profiler/instrprof_tsan.swift index c0f5311cc24ab..e3b373f75c219 100644 --- a/test/Profiler/instrprof_tsan.swift +++ b/test/Profiler/instrprof_tsan.swift @@ -1,7 +1,7 @@ // RUN: %target-swift-frontend -emit-ir -profile-generate -sanitize=thread %s | %FileCheck %s -// REQUIRES: OS=macosx -// REQUIRES: CPU=x86_64 +// TSan is only supported on 64 bit. +// REQUIRES: PTRSIZE=64 // CHECK: define {{.*}}empty // CHECK-NOT: load{{.*}}empty diff --git a/test/Runtime/lazy_witness_table_cycle.swift b/test/Runtime/lazy_witness_table_cycle.swift index 05bd44924a08b..552ba07c0e943 100644 --- a/test/Runtime/lazy_witness_table_cycle.swift +++ b/test/Runtime/lazy_witness_table_cycle.swift @@ -1,6 +1,6 @@ // RUN: %target-run-simple-swift // REQUIRES: executable_test -// REQUIRES: objc_interop +// REQUIRES: foundation // SR-5958 import Foundation diff --git a/test/SILGen/tsan_instrumentation.swift b/test/SILGen/tsan_instrumentation.swift index 1ce041a9aa7f4..bb42410873195 100644 --- a/test/SILGen/tsan_instrumentation.swift +++ b/test/SILGen/tsan_instrumentation.swift @@ -1,9 +1,7 @@ // RUN: %target-swift-emit-silgen -sanitize=thread %s | %FileCheck %s -// REQUIRES: tsan_runtime -// FIXME: This should be covered by "tsan_runtime"; older versions of Apple OSs -// don't support TSan. -// UNSUPPORTED: remote_run +// TSan is only supported on 64 bit. +// REQUIRES: PTRSIZE=64 func takesInout(_ p: inout Int) { } func takesInout(_ p: inout MyStruct) { } diff --git a/test/Sanitizers/tsan-emptyarraystorage.swift b/test/Sanitizers/tsan-emptyarraystorage.swift index 808b9e3c1ae3d..2a694791fe2fa 100644 --- a/test/Sanitizers/tsan-emptyarraystorage.swift +++ b/test/Sanitizers/tsan-emptyarraystorage.swift @@ -3,6 +3,7 @@ // RUN: %target-run %t_tsan-binary 2>&1 | %FileCheck %s // REQUIRES: executable_test // REQUIRES: tsan_runtime +// REQUIRES: foundation // UNSUPPORTED: OS=tvos // FIXME: This should be covered by "tsan_runtime"; older versions of Apple OSs diff --git a/test/Sanitizers/tsan-libdispatch.swift b/test/Sanitizers/tsan-libdispatch.swift new file mode 100644 index 0000000000000..0cc5489ba7dfb --- /dev/null +++ b/test/Sanitizers/tsan-libdispatch.swift @@ -0,0 +1,43 @@ +// RUN: %target-swiftc_driver %s -g -sanitize=thread %import-libdispatch -o %t_tsan-binary +// RUN: %target-codesign %t_tsan-binary +// RUN: not env %env-TSAN_OPTIONS=abort_on_error=0 %target-run %t_tsan-binary 2>&1 | %FileCheck %s +// REQUIRES: executable_test +// REQUIRES: tsan_runtime +// UNSUPPORTED: OS=tvos + +// FIXME: This should be covered by "tsan_runtime"; older versions of Apple OSs +// don't support TSan. +// UNSUPPORTED: remote_run + +// Test ThreadSanitizer execution end-to-end with libdispatch. + +import Dispatch + +let sync1 = DispatchSemaphore(value: 0) +let sync2 = DispatchSemaphore(value: 0) +let finish = DispatchSemaphore(value: 0) + +let q = DispatchQueue(label: "q", attributes: .concurrent) + +var racy = 1 + +q.async { + sync1.wait() + sync2.signal() + racy = 2 + finish.signal() +} +q.async { + sync1.signal() + sync2.wait() + racy = 3 + finish.signal() +} + +finish.wait() +finish.wait() + +print("Done!") + +// CHECK: ThreadSanitizer: data race +// CHECK: Done! diff --git a/test/Sanitizers/tsan-norace-block-release.swift b/test/Sanitizers/tsan-norace-block-release.swift index 10c639609f003..9a77ee65d2d8c 100644 --- a/test/Sanitizers/tsan-norace-block-release.swift +++ b/test/Sanitizers/tsan-norace-block-release.swift @@ -1,8 +1,7 @@ -// RUN: %target-swiftc_driver %s -g -sanitize=thread -target %sanitizers-target-triple -o %t_tsan-binary +// RUN: %target-swiftc_driver %s -g -sanitize=thread %import-libdispatch -target %sanitizers-target-triple -o %t_tsan-binary // RUN: %target-codesign %t_tsan-binary -// RUN: env %env-TSAN_OPTIONS=abort_on_error=0:ignore_interceptors_accesses=1 %target-run %t_tsan-binary 2>&1 | %FileCheck %s +// RUN: env %env-TSAN_OPTIONS=abort_on_error=0:ignore_interceptors_accesses=1 %target-run %t_tsan-binary 2>&1 | %FileCheck %s --implicit-check-not='ThreadSanitizer' // REQUIRES: executable_test -// REQUIRES: objc_interop // REQUIRES: tsan_runtime // FIXME: This should be covered by "tsan_runtime"; older versions of Apple OSs @@ -10,17 +9,23 @@ // UNSUPPORTED: remote_run // Test that we do not report a race on block release operation. -import Foundation - -public class Sad : NSObject { +import Dispatch +#if canImport(Darwin) + import Darwin +#elseif canImport(Glibc) + import Glibc +#else +#error("Unsupported platform") +#endif + +public class Sad { private var _source: DispatchSourceTimer? - public override init() { + public init() { _source = DispatchSource.makeTimerSource() // If this line is commented out no data race. _source?.setEventHandler(handler: globalFuncHandler) - super.init() _source?.resume() } deinit { @@ -40,4 +45,3 @@ sleep(1) print("Done.") // CHECK: Done. -// CHECK-NOT: ThreadSanitizer: data race diff --git a/test/Sanitizers/tsan-norace-deinit-run-time.swift b/test/Sanitizers/tsan-norace-deinit-run-time.swift index 56c2cabd5ce0c..d3a8861970daf 100644 --- a/test/Sanitizers/tsan-norace-deinit-run-time.swift +++ b/test/Sanitizers/tsan-norace-deinit-run-time.swift @@ -1,8 +1,7 @@ -// RUN: %target-swiftc_driver %s -g -sanitize=thread -target %sanitizers-target-triple -o %t_tsan-binary +// RUN: %target-swiftc_driver %s -g -sanitize=thread %import-libdispatch -target %sanitizers-target-triple -o %t_tsan-binary // RUN: %target-codesign %t_tsan-binary -// RUN: env %env-TSAN_OPTIONS=abort_on_error=0:ignore_interceptors_accesses=1 %target-run %t_tsan-binary 2>&1 | %FileCheck %s +// RUN: env %env-TSAN_OPTIONS=abort_on_error=0:ignore_interceptors_accesses=1 %target-run %t_tsan-binary 2>&1 | %FileCheck %s --implicit-check-not='ThreadSanitizer' // REQUIRES: executable_test -// REQUIRES: objc_interop // REQUIRES: tsan_runtime // FIXME: This should be covered by "tsan_runtime"; older versions of Apple OSs @@ -10,11 +9,18 @@ // UNSUPPORTED: remote_run // Test that we do not report a race on deinit; the synchronization is guaranteed by runtime. -import Foundation - -public class TestDeallocObject : NSObject { +import Dispatch +#if canImport(Darwin) + import Darwin +#elseif canImport(Glibc) + import Glibc +#else +#error("Unsupported platform") +#endif + +public class TestDeallocObject { public var v : Int - public override init() { + public init() { v = 1 } @@ -33,7 +39,7 @@ public class TestDeallocObject : NSObject { } } -if (true) { +do { var tdo : TestDeallocObject = TestDeallocObject() tdo.accessMember() @@ -52,4 +58,3 @@ if (true) { print("Done.") // CHECK: Done. -// CHECK-NOT: ThreadSanitizer: data race diff --git a/test/Sanitizers/tsan.swift b/test/Sanitizers/tsan.swift index 528ff53b5d968..a06fac9cf17e6 100644 --- a/test/Sanitizers/tsan.swift +++ b/test/Sanitizers/tsan.swift @@ -1,4 +1,4 @@ -// RUN: %target-swiftc_driver %s -target %sanitizers-target-triple -g -sanitize=thread -o %t_tsan-binary +// RUN: %target-swiftc_driver %s -target %sanitizers-target-triple -g -sanitize=thread %import-libdispatch -o %t_tsan-binary // RUN: %target-codesign %t_tsan-binary // RUN: not env %env-TSAN_OPTIONS="abort_on_error=0" %target-run %t_tsan-binary 2>&1 | %FileCheck %s // REQUIRES: executable_test diff --git a/test/lit.cfg b/test/lit.cfg index 6ebee108f64f5..e91de1d745b7e 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -728,6 +728,10 @@ if run_vendor == 'apple': config.target_codesign = "codesign -f -s -" config.target_runtime = "objc" + config.available_features.add('libdispatch') + config.available_features.add('foundation') + config.available_features.add('objc_interop') + xcrun_prefix = ( "xcrun --toolchain %s --sdk %r" % (config.darwin_xcrun_toolchain, config.variant_sdk)) @@ -978,6 +982,21 @@ elif run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'windows-cygnus', 'wi config.target_sdk_name = "linux" config.target_runtime = "native" config.target_swift_autolink_extract = inferSwiftBinary("swift-autolink-extract") + + libdispatch_build_dir = make_path(config.swift_obj_root, os.pardir, + 'libdispatch%s' % config.variant_suffix, 'src') + libdispatch_build_artifacts = [ + make_path(libdispatch_build_dir, 'libdispatch.so'), + make_path(libdispatch_build_dir, 'libswiftDispatch.so'), + make_path(libdispatch_build_dir, 'swift', 'Dispatch.swiftmodule')] + if (all(os.path.exists(p) for p in libdispatch_build_artifacts)): + config.available_features.add('libdispatch') + config.libdispatch_build_dir = libdispatch_build_dir + libdispatch_source_dir = make_path(config.swift_src_root, os.pardir, 'swift-corelibs-libdispatch') + libdispatch_swift_module_dir = make_path(libdispatch_build_dir, 'swift') + config.import_libdispatch = ('-I %s -I %s -L %s' + % (libdispatch_source_dir, libdispatch_swift_module_dir, libdispatch_build_dir)) + config.target_build_swift = ( '%s -target %s %s %s %s %s %s' % (config.swiftc, config.variant_triple, resource_dir_opt, mcp_opt, @@ -1294,7 +1313,7 @@ runtime_libs = { 'fuzzer': 'fuzzer_runtime' } -if run_ptrsize != "32": +if run_ptrsize == '64' and 'libdispatch' in config.available_features: runtime_libs['tsan'] = 'tsan_runtime' check_runtime_libs(runtime_libs) @@ -1393,14 +1412,15 @@ if os.path.exists(static_libswiftCore_path): # default Swift tests to use the just-built libraries target_stdlib_path = platform_module_dir if not kIsWindows: + libdispatch_path = getattr(config, 'libdispatch_build_dir', '') if 'use_os_stdlib' not in lit_config.params: lit_config.note('Testing with the just-built libraries at ' + target_stdlib_path) config.target_run = ( "/usr/bin/env " "DYLD_LIBRARY_PATH='{0}' " # Apple option - "LD_LIBRARY_PATH='{0}' " # Linux option + "LD_LIBRARY_PATH='{0}:{1}' " # Linux option "SIMCTL_CHILD_DYLD_LIBRARY_PATH='{0}' " # Simulator option - .format(target_stdlib_path)) + config.target_run + .format(target_stdlib_path, libdispatch_path)) + config.target_run else: os_stdlib_path = '' if run_vendor == 'apple': @@ -1411,9 +1431,9 @@ if not kIsWindows: config.target_run = ( "/usr/bin/env " "DYLD_LIBRARY_PATH='{0}' " # Apple option - "LD_LIBRARY_PATH='{0}' " # Linux option + "LD_LIBRARY_PATH='{0}:{1}' " # Linux option "SIMCTL_CHILD_DYLD_LIBRARY_PATH='{0}' " # Simulator option - .format(all_stdlib_path)) + config.target_run + .format(all_stdlib_path, libdispatch_path)) + config.target_run if not getattr(config, 'target_run_simple_swift', None): config.target_run_simple_swift_parameterized = \ @@ -1457,7 +1477,7 @@ if not getattr(config, 'target_run_simple_swift', None): % (config.target_build_swift, mcp_opt, config.target_codesign, config.target_run)) # -# When changing substitutions, update docs/Testing.rst. +# When changing substitutions, update docs/Testing.md. # config.substitutions.append(('%target-runtime', config.target_runtime)) @@ -1580,6 +1600,7 @@ config.substitutions.append(('%FileCheck', config.filecheck, '--enable-windows-compatibility' if kIsWindows else ''))) config.substitutions.append(('%raw-FileCheck', pipes.quote(config.filecheck))) +config.substitutions.append(('%import-libdispatch', getattr(config, 'import_libdispatch', ''))) if config.lldb_build_root != "": config.available_features.add('lldb') @@ -1608,25 +1629,5 @@ if platform.system() == 'Linux': config.available_features.add("LinuxDistribution=" + distributor + '-' + release) lit_config.note('Running tests on %s-%s' % (distributor, release)) -if run_vendor == 'apple': - config.available_features.add('libdispatch') - config.available_features.add('foundation') - config.available_features.add('objc_interop') -else: - # TODO(yln): Works with the packaged swift distribution, but not during build. - # We need to make libdispatch/foundation available in the test resource directory - # or pass along the proper library include paths in the compiler invocations that are used - # to build the tests. - def has_lib(name): - return False - - if has_lib('dispatch'): - config.available_features.add('libdispatch') - else: - # TSan runtime requires libdispatch on non-Apple platforms - config.available_features.discard('tsan_runtime') - - if has_lib('Foundation'): - config.available_features.add('foundation') lit_config.note("Available features: " + ", ".join(sorted(config.available_features))) diff --git a/test/stdlib/Dispatch.swift b/test/stdlib/Dispatch.swift index 82d1a26407caa..18cf07a8653d2 100644 --- a/test/stdlib/Dispatch.swift +++ b/test/stdlib/Dispatch.swift @@ -1,6 +1,7 @@ // RUN: %target-run-simple-swift // REQUIRES: executable_test // REQUIRES: libdispatch +// UNSUPPORTED: OS=linux-gnu import Dispatch import StdlibUnittest diff --git a/test/stdlib/DispatchData.swift b/test/stdlib/DispatchData.swift index 758e82d0e5bb0..8c90e43641d89 100644 --- a/test/stdlib/DispatchData.swift +++ b/test/stdlib/DispatchData.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) -// RUN: %target-build-swift -swift-version 4 %s -o %t/a.out-4 && %target-codesign %t/a.out-4 && %target-run %t/a.out-4 -// RUN: %target-build-swift -swift-version 4.2 %s -o %t/a.out-4.2 && %target-codesign %t/a.out-4.2 && %target-run %t/a.out-4.2 +// RUN: %target-build-swift -swift-version 4 %s %import-libdispatch -o %t/a.out-4 && %target-codesign %t/a.out-4 && %target-run %t/a.out-4 +// RUN: %target-build-swift -swift-version 4.2 %s %import-libdispatch -o %t/a.out-4.2 && %target-codesign %t/a.out-4.2 && %target-run %t/a.out-4.2 // REQUIRES: executable_test // REQUIRES: libdispatch @@ -22,11 +22,12 @@ DispatchAPI.test("dispatch_data_t deallocator") { let q = DispatchQueue(label: "dealloc queue") var t = 0 - autoreleasepool { + do { let size = 1024 let p = UnsafeMutablePointer.allocate(capacity: size) let _ = DispatchData(bytesNoCopy: UnsafeBufferPointer(start: p, count: size), deallocator: .custom(q, { t = 1 + p.deallocate(); })) } diff --git a/test/stdlib/DispatchDeprecationMacOS.swift b/test/stdlib/DispatchDeprecationMacOS.swift index d132a59c1e269..04440f6f316d7 100644 --- a/test/stdlib/DispatchDeprecationMacOS.swift +++ b/test/stdlib/DispatchDeprecationMacOS.swift @@ -1,8 +1,7 @@ // RUN: %swift -typecheck -target x86_64-apple-macosx10.9 -verify -sdk %sdk %s // REQUIRES: OS=macosx -// REQUIRES: objc_interop +// REQUIRES: libdispatch -import Foundation import Dispatch // Don't warn because these APIs were deprecated in macOS 10.10 and the diff --git a/test/stdlib/DispatchDeprecationWatchOS.swift b/test/stdlib/DispatchDeprecationWatchOS.swift index 74aff3f82bc96..5e70dbca1dee3 100644 --- a/test/stdlib/DispatchDeprecationWatchOS.swift +++ b/test/stdlib/DispatchDeprecationWatchOS.swift @@ -1,8 +1,7 @@ // RUN: %swift -typecheck -target i386-apple-watchos2.0 -verify -sdk %sdk %s // REQUIRES: CPU=i386, OS=watchos -// REQUIRES: objc_interop +// REQUIRES: libdispatch -import Foundation import Dispatch // These are deprecated on all versions of watchOS. diff --git a/test/stdlib/DispatchRenames.swift b/test/stdlib/DispatchRenames.swift index 03aeeca98ad98..d6d717a980409 100644 --- a/test/stdlib/DispatchRenames.swift +++ b/test/stdlib/DispatchRenames.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift %import-libdispatch // REQUIRES: libdispatch import Dispatch diff --git a/test/stdlib/DispatchTypes.swift b/test/stdlib/DispatchTypes.swift index 6a57b3a089012..f454b97d669ab 100644 --- a/test/stdlib/DispatchTypes.swift +++ b/test/stdlib/DispatchTypes.swift @@ -1,6 +1,7 @@ // RUN: %target-swift-frontend -typecheck %s // REQUIRES: libdispatch +// UNSUPPORTED: OS=linux-gnu import Dispatch diff --git a/validation-test/Runtime/weak-reference-racetests-dispatch.swift b/validation-test/Runtime/weak-reference-racetests-dispatch.swift index 8a18258915af8..dcb2e17d94df9 100644 --- a/validation-test/Runtime/weak-reference-racetests-dispatch.swift +++ b/validation-test/Runtime/weak-reference-racetests-dispatch.swift @@ -1,4 +1,5 @@ -// RUN: %target-run-simple-swift +// RUN: %target-build-swift %s %import-libdispatch -o %t_binary +// RUN: %target-run %t_binary // REQUIRES: executable_test // REQUIRES: stress_test // REQUIRES: libdispatch diff --git a/validation-test/Sanitizers/tsan-ignores-arc-locks.swift b/validation-test/Sanitizers/tsan-ignores-arc-locks.swift index 0695e05c1471e..00dc01b465100 100644 --- a/validation-test/Sanitizers/tsan-ignores-arc-locks.swift +++ b/validation-test/Sanitizers/tsan-ignores-arc-locks.swift @@ -3,7 +3,7 @@ // REQUIRES: executable_test // REQUIRES: stress_test // REQUIRES: tsan_runtime -// REQUIRES: objc_interop +// REQUIRES: foundation // Check that TSan ignores the retain count update locks in the runtime. diff --git a/validation-test/Sanitizers/tsan-inout.swift b/validation-test/Sanitizers/tsan-inout.swift index 774e641ee70a2..7a87d073cc7e9 100644 --- a/validation-test/Sanitizers/tsan-inout.swift +++ b/validation-test/Sanitizers/tsan-inout.swift @@ -2,18 +2,23 @@ // RUN: cd %t // RUN: %target-build-swift %S/Inputs/tsan-uninstrumented.swift -target %sanitizers-target-triple -module-name TSanUninstrumented -emit-module -emit-module-path %t/TSanUninstrumented.swiftmodule -parse-as-library // RUN: %target-build-swift %S/Inputs/tsan-uninstrumented.swift -target %sanitizers-target-triple -c -module-name TSanUninstrumented -parse-as-library -o %t/TSanUninstrumented.o -// RUN: %target-swiftc_driver %s %t/TSanUninstrumented.o -target %sanitizers-target-triple -I%t -L%t -g -sanitize=thread -o %t/tsan-binary +// RUN: %target-swiftc_driver %s %t/TSanUninstrumented.o -target %sanitizers-target-triple -I%t -L%t -g -sanitize=thread %import-libdispatch -o %t/tsan-binary // RUN: not env %env-TSAN_OPTIONS=abort_on_error=0 %target-run %t/tsan-binary 2>&1 | %FileCheck %s // RUN: not env %env-TSAN_OPTIONS=abort_on_error=0:ignore_interceptors_accesses=0 %target-run %t/tsan-binary 2>&1 | %FileCheck %s --check-prefix CHECK-INTERCEPTORS-ACCESSES // REQUIRES: executable_test // REQUIRES: stress_test -// REQUIRES: objc_interop // REQUIRES: tsan_runtime // Test ThreadSanitizer execution end-to-end when calling // an uninstrumented module with inout parameters -import Darwin +#if canImport(Darwin) + import Darwin +#elseif canImport(Glibc) + import Glibc +#else +#error("Unsupported platform") +#endif import TSanUninstrumented // Globals to allow closures passed to pthread_create() to be thin. @@ -23,8 +28,14 @@ var gInThread2: () -> () = { } // Spawn two threads, run the two passed in closures simultaneously, and // join them. func testRace(name: String, thread inThread1: @escaping () -> (), thread inThread2: @escaping () -> ()) { +#if canImport(Darwin) var thread1: pthread_t? var thread2: pthread_t? +#else + var thread1: pthread_t = 0 + var thread2: pthread_t = 0 + var t : pthread_t = 0 +#endif fputs("Running \(name)\n", stderr) // Store these in globals so the closure passed to pthread_create @@ -41,8 +52,13 @@ func testRace(name: String, thread inThread1: @escaping () -> (), thread inThrea return nil }, nil) +#if canImport(Darwin) _ = pthread_join(thread1!, nil) _ = pthread_join(thread2!, nil) +#else + _ = pthread_join(thread1, nil) + _ = pthread_join(thread2, nil) +#endif // TSan reports go to stderr fputs("Done \(name)\n", stderr) diff --git a/validation-test/Sanitizers/tsan-type-metadata.swift b/validation-test/Sanitizers/tsan-type-metadata.swift index e9edc7241b9c0..63501a4b5abf2 100644 --- a/validation-test/Sanitizers/tsan-type-metadata.swift +++ b/validation-test/Sanitizers/tsan-type-metadata.swift @@ -1,8 +1,7 @@ -// RUN: %target-swiftc_driver -target %sanitizers-target-triple -sanitize=thread %s -o %t_binary +// RUN: %target-swiftc_driver -target %sanitizers-target-triple -sanitize=thread %import-libdispatch %s -o %t_binary // RUN: %env-TSAN_OPTIONS=ignore_interceptors_accesses=1:halt_on_error=1 %target-run %t_binary // REQUIRES: executable_test // REQUIRES: stress_test -// REQUIRES: objc_interop // REQUIRES: tsan_runtime // We expect not to report any races on this testcase. diff --git a/validation-test/Sanitizers/witness_table_lookup.swift b/validation-test/Sanitizers/witness_table_lookup.swift index 33994d1f00547..a9eb07171f0c9 100644 --- a/validation-test/Sanitizers/witness_table_lookup.swift +++ b/validation-test/Sanitizers/witness_table_lookup.swift @@ -1,4 +1,4 @@ -// RUN: %target-build-swift -sanitize=thread -target %sanitizers-target-triple %s -o %t_binary +// RUN: %target-build-swift -sanitize=thread %import-libdispatch -target %sanitizers-target-triple %s -o %t_binary // RUN: %env-TSAN_OPTIONS=ignore_interceptors_accesses=1:halt_on_error=1 %target-run %t_binary // REQUIRES: executable_test // REQUIRES: stress_test From 1f08ed458fa90b5f3f1063b094606db826312b9f Mon Sep 17 00:00:00 2001 From: Julian Lettner Date: Thu, 30 May 2019 10:27:08 -0700 Subject: [PATCH 088/112] Wire libdispatch build path through CMake Wire libdispatch build path through CMake `build-script-impl -> lit.site.cfg.in -> lit.cfg` instead of computing it in lit.cfg. --- test/lit.cfg | 21 ++++++++++----------- test/lit.site.cfg.in | 1 + utils/build-script-impl | 1 + validation-test/lit.site.cfg.in | 1 + 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/test/lit.cfg b/test/lit.cfg index e91de1d745b7e..5bd15cb314447 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -983,19 +983,18 @@ elif run_os in ['linux-gnu', 'linux-gnueabihf', 'freebsd', 'windows-cygnus', 'wi config.target_runtime = "native" config.target_swift_autolink_extract = inferSwiftBinary("swift-autolink-extract") - libdispatch_build_dir = make_path(config.swift_obj_root, os.pardir, - 'libdispatch%s' % config.variant_suffix, 'src') - libdispatch_build_artifacts = [ - make_path(libdispatch_build_dir, 'libdispatch.so'), - make_path(libdispatch_build_dir, 'libswiftDispatch.so'), - make_path(libdispatch_build_dir, 'swift', 'Dispatch.swiftmodule')] - if (all(os.path.exists(p) for p in libdispatch_build_artifacts)): + libdispatch_artifact_dir = make_path(config.libdispatch_build_path, 'src') + libdispatch_artifacts = [ + make_path(libdispatch_artifact_dir, 'libdispatch.so'), + make_path(libdispatch_artifact_dir, 'libswiftDispatch.so'), + make_path(libdispatch_artifact_dir, 'swift', 'Dispatch.swiftmodule')] + if (all(os.path.exists(p) for p in libdispatch_artifacts)): config.available_features.add('libdispatch') - config.libdispatch_build_dir = libdispatch_build_dir + config.libdispatch_artifact_dir = libdispatch_artifact_dir libdispatch_source_dir = make_path(config.swift_src_root, os.pardir, 'swift-corelibs-libdispatch') - libdispatch_swift_module_dir = make_path(libdispatch_build_dir, 'swift') + libdispatch_swift_module_dir = make_path(libdispatch_artifact_dir, 'swift') config.import_libdispatch = ('-I %s -I %s -L %s' - % (libdispatch_source_dir, libdispatch_swift_module_dir, libdispatch_build_dir)) + % (libdispatch_source_dir, libdispatch_swift_module_dir, libdispatch_artifact_dir)) config.target_build_swift = ( '%s -target %s %s %s %s %s %s' @@ -1412,7 +1411,7 @@ if os.path.exists(static_libswiftCore_path): # default Swift tests to use the just-built libraries target_stdlib_path = platform_module_dir if not kIsWindows: - libdispatch_path = getattr(config, 'libdispatch_build_dir', '') + libdispatch_path = getattr(config, 'libdispatch_artifact_dir', '') if 'use_os_stdlib' not in lit_config.params: lit_config.note('Testing with the just-built libraries at ' + target_stdlib_path) config.target_run = ( diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index 6c6352e31c781..8733e1f7b8ba9 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -32,6 +32,7 @@ config.swift_test_results_dir = \ config.coverage_mode = "@SWIFT_ANALYZE_CODE_COVERAGE@" config.lldb_build_root = "@LLDB_BUILD_DIR@" +config.libdispatch_build_path = "@SWIFT_PATH_TO_LIBDISPATCH_BUILD@" # --- Darwin --- config.darwin_xcrun_toolchain = "@SWIFT_DARWIN_XCRUN_TOOLCHAIN@" diff --git a/utils/build-script-impl b/utils/build-script-impl index 3c5edb655258c..06630077d4135 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -2402,6 +2402,7 @@ for host in "${ALL_HOSTS[@]}"; do -DSWIFT_PATH_TO_CMARK_SOURCE:PATH="${CMARK_SOURCE_DIR}" -DSWIFT_PATH_TO_CMARK_BUILD:PATH="$(build_directory ${host} cmark)" -DSWIFT_PATH_TO_LIBDISPATCH_SOURCE:PATH="${LIBDISPATCH_SOURCE_DIR}" + -DSWIFT_PATH_TO_LIBDISPATCH_BUILD:PATH="$(build_directory ${host} libdispatch)" ) if [[ ! "${SKIP_BUILD_LIBICU}" ]] ; then diff --git a/validation-test/lit.site.cfg.in b/validation-test/lit.site.cfg.in index 1141e7152e8b4..6a00ee3ab5ef7 100644 --- a/validation-test/lit.site.cfg.in +++ b/validation-test/lit.site.cfg.in @@ -50,6 +50,7 @@ else: config.coverage_mode = "@SWIFT_ANALYZE_CODE_COVERAGE@" config.lldb_build_root = "@LLDB_BUILD_DIR@" +config.libdispatch_build_path = "@SWIFT_PATH_TO_LIBDISPATCH_BUILD@" if "@SWIFT_ASAN_BUILD@" == "TRUE": config.available_features.add("asan") From 0b27345d68fbc6191cbf6347580a9cf45d567f5c Mon Sep 17 00:00:00 2001 From: Christopher Rogers Date: Fri, 6 Jul 2018 19:28:19 +0900 Subject: [PATCH 089/112] Swift should complain about weak references to classes that don't support them Resolves SR-6706 --- include/swift/AST/Decl.h | 19 ++++++++++++-- include/swift/AST/DiagnosticsSema.def | 3 +++ lib/AST/Decl.cpp | 11 ++++++++ lib/ClangImporter/ImportDecl.cpp | 3 +++ lib/Sema/TypeCheckAttr.cpp | 9 +++++++ .../Inputs/diag_ownership_incompatibility.h | 5 ++++ .../Sema/diag_ownership_incompatibility.swift | 25 +++++++++++++++++++ 7 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 test/Sema/Inputs/diag_ownership_incompatibility.h create mode 100644 test/Sema/diag_ownership_incompatibility.swift diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index a05cd74c9a689..5c0b32b80843b 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -553,7 +553,7 @@ class alignas(1 << DeclAlignInBits) Decl { NumRequirementsInSignature : 16 ); - SWIFT_INLINE_BITFIELD(ClassDecl, NominalTypeDecl, 1+2+1+2+1+6+1+1+1, + SWIFT_INLINE_BITFIELD(ClassDecl, NominalTypeDecl, 1+2+1+2+1+6+1+1+1+1, /// Whether this class requires all of its instance variables to /// have in-class initializers. RequiresStoredPropertyInits : 1, @@ -581,7 +581,11 @@ class alignas(1 << DeclAlignInBits) Decl { AncestryComputed : 1, HasMissingDesignatedInitializers : 1, - HasMissingVTableEntries : 1 + HasMissingVTableEntries : 1, + + /// Whether instances of this class are incompatible + /// with weak and unowned references. + IsIncompatibleWithWeakReferences : 1 ); SWIFT_INLINE_BITFIELD(StructDecl, NominalTypeDecl, 1, @@ -3860,6 +3864,17 @@ class ClassDecl final : public NominalTypeDecl { Bits.ClassDecl.HasMissingVTableEntries = newValue; } + /// Returns true if this class cannot be used with weak or unowned + /// references. + /// + /// Note that this is true if this class or any of its ancestor classes + /// are marked incompatible. + bool isIncompatibleWithWeakReferences() const; + + void setIsIncompatibleWithWeakReferences(bool newValue = true) { + Bits.ClassDecl.IsIncompatibleWithWeakReferences = newValue; + } + /// Find a method of a class that overrides a given method. /// Return nullptr, if no such method exists. AbstractFunctionDecl *findOverridingDecl( diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index daeb29c70093a..9550180c5865a 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -3565,6 +3565,9 @@ ERROR(invalid_ownership_protocol_type,none, "%0 must not be applied to non-class-bound %1; " "consider adding a protocol conformance that has a class bound", (ReferenceOwnership, Type)) +ERROR(invalid_ownership_incompatible_class,none, + "%0 is incompatible with %1 references", + (Type, ReferenceOwnership)) ERROR(invalid_ownership_with_optional,none, "%0 variable cannot have optional type", (ReferenceOwnership)) ERROR(invalid_ownership_not_optional,none, diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 99a2860b0f7d0..ae6a0c11c02b9 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -3691,6 +3691,7 @@ ClassDecl::ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc, Bits.ClassDecl.AncestryComputed = 0; Bits.ClassDecl.HasMissingDesignatedInitializers = 0; Bits.ClassDecl.HasMissingVTableEntries = 0; + Bits.ClassDecl.IsIncompatibleWithWeakReferences = 0; } bool ClassDecl::hasResilientMetadata() const { @@ -3774,6 +3775,16 @@ bool ClassDecl::hasMissingVTableEntries() const { return Bits.ClassDecl.HasMissingVTableEntries; } +bool ClassDecl::isIncompatibleWithWeakReferences() const { + if (Bits.ClassDecl.IsIncompatibleWithWeakReferences) { + return true; + } + if (auto superclass = getSuperclassDecl()) { + return superclass->isIncompatibleWithWeakReferences(); + } + return false; +} + bool ClassDecl::inheritsSuperclassInitializers(LazyResolver *resolver) { // Check whether we already have a cached answer. if (addedImplicitInitializers()) diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index af44228b91aaa..47cae58950337 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -4692,6 +4692,9 @@ namespace { } #include "InferredAttributes.def" + if (decl->isArcWeakrefUnavailable()) + result->setIsIncompatibleWithWeakReferences(); + result->setMemberLoader(&Impl, 0); result->addImplicitDestructor(); diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index e8c59e3d4088a..8d6b02f25c44b 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -2678,6 +2678,15 @@ void TypeChecker::checkReferenceOwnershipAttr(VarDecl *var, attr->setInvalid(); } + ClassDecl *underlyingClass = underlyingType->getClassOrBoundGenericClass(); + if (underlyingClass && underlyingClass->isIncompatibleWithWeakReferences()) { + diagnose(attr->getLocation(), + diag::invalid_ownership_incompatible_class, + underlyingType, ownershipKind) + .fixItRemove(attr->getRange()); + attr->setInvalid(); + } + auto PDC = dyn_cast((var->getDeclContext())); if (PDC && !PDC->isObjC()) { // Ownership does not make sense in protocols, except for "weak" on diff --git a/test/Sema/Inputs/diag_ownership_incompatibility.h b/test/Sema/Inputs/diag_ownership_incompatibility.h new file mode 100644 index 0000000000000..a7bbdd933e8bf --- /dev/null +++ b/test/Sema/Inputs/diag_ownership_incompatibility.h @@ -0,0 +1,5 @@ +@import Foundation; + +__attribute__((objc_arc_weak_reference_unavailable)) +@interface NoWeakClass : NSObject +@end diff --git a/test/Sema/diag_ownership_incompatibility.swift b/test/Sema/diag_ownership_incompatibility.swift new file mode 100644 index 0000000000000..70eda04c82ee6 --- /dev/null +++ b/test/Sema/diag_ownership_incompatibility.swift @@ -0,0 +1,25 @@ +// RUN: %target-typecheck-verify-swift -enable-objc-interop -import-objc-header %S/Inputs/diag_ownership_incompatibility.h + +class C { + weak var weakVar: NoWeakClass? = nil // expected-error {{'NoWeakClass' is incompatible with 'weak' references}} + unowned var unownedVar = NoWeakClass() // expected-error {{'NoWeakClass' is incompatible with 'unowned' references}} +} + +_ = C() + +weak var weakVar: NoWeakClass? = nil // expected-error {{'NoWeakClass' is incompatible with 'weak' references}} +unowned var unownedVar = NoWeakClass() // expected-error {{'NoWeakClass' is incompatible with 'unowned' references}} + +// Subclasses are also incompatible. + +class SwiftNoWeakClass: NoWeakClass { } + +class D { + weak var weakVar: SwiftNoWeakClass? = nil // expected-error {{'SwiftNoWeakClass' is incompatible with 'weak' references}} + unowned var unownedVar = SwiftNoWeakClass() // expected-error {{'SwiftNoWeakClass' is incompatible with 'unowned' references}} +} + +_ = D() + +weak var weakSwiftVar: SwiftNoWeakClass? = nil // expected-error {{'SwiftNoWeakClass' is incompatible with 'weak' references}} +unowned var unownedSwiftVar = SwiftNoWeakClass() // expected-error {{'SwiftNoWeakClass' is incompatible with 'unowned' references}} \ No newline at end of file From da22342a83bf028f3659d17ea69cb41713d43443 Mon Sep 17 00:00:00 2001 From: Christopher Rogers Date: Fri, 6 Jul 2018 19:28:56 +0900 Subject: [PATCH 090/112] Typo/grammar fixes --- lib/Sema/TypeCheckAttr.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 8d6b02f25c44b..49f4c9fa9fd15 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -41,7 +41,7 @@ namespace { template void diagnoseAndRemoveAttr(TypeChecker &TC, Decl *D, DeclAttribute *attr, ArgTypes &&...Args) { - assert(!D->hasClangNode() && "Clang imported propagated a bogus attribute"); + assert(!D->hasClangNode() && "Clang importer propagated a bogus attribute"); if (!D->hasClangNode()) { SourceLoc loc = attr->getLocation(); assert(loc.isValid() && "Diagnosing attribute with invalid location"); @@ -1433,9 +1433,9 @@ void AttributeChecker::visitNSCopyingAttr(NSCopyingAttr *attr) { assert(VD->getOverriddenDecl() == nullptr && "Can't have value with storage that is an override"); - // Check the type. It must be must be [unchecked]optional, weak, a normal + // Check the type. It must be an [unchecked]optional, weak, a normal // class, AnyObject, or classbound protocol. - // must conform to the NSCopying protocol. + // It must conform to the NSCopying protocol. } From c0da367fb5614bd05e3f12ee8daaf3c645a1f290 Mon Sep 17 00:00:00 2001 From: Christopher Rogers Date: Sat, 8 Jun 2019 16:33:00 -0600 Subject: [PATCH 091/112] Remove duplicate include --- lib/Sema/TypeCheckAttr.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 49f4c9fa9fd15..1723735d4f8c9 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -32,7 +32,6 @@ #include "swift/Sema/IDETypeChecking.h" #include "clang/Basic/CharInfo.h" #include "llvm/Support/Debug.h" -#include "clang/Basic/CharInfo.h" using namespace swift; From db6f15e5b1dc8595446349bab221bff3a5415b8b Mon Sep 17 00:00:00 2001 From: Christopher Rogers Date: Mon, 10 Jun 2019 19:16:47 -0400 Subject: [PATCH 092/112] Fix broken test on Linux --- test/Sema/diag_ownership_incompatibility.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Sema/diag_ownership_incompatibility.swift b/test/Sema/diag_ownership_incompatibility.swift index 70eda04c82ee6..0a1ee917e4d1c 100644 --- a/test/Sema/diag_ownership_incompatibility.swift +++ b/test/Sema/diag_ownership_incompatibility.swift @@ -1,3 +1,5 @@ +// REQUIRES: objc_interop + // RUN: %target-typecheck-verify-swift -enable-objc-interop -import-objc-header %S/Inputs/diag_ownership_incompatibility.h class C { From 01cf8a8dfced42e30d41f210514355f0838d220d Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 10 Jun 2019 15:37:36 -0700 Subject: [PATCH 093/112] tests: disable backward deployment tests on Windows PE/COFF does not support weak linking semantics. Disable the tests until we can emulate the required behaviour. This will allow us to enable running the validation test suite on Windows in the mean time. --- .../test_backward_deploy_always_emit_into_client.swift | 3 +++ validation-test/Evolution/test_backward_deploy_class.swift | 3 +++ validation-test/Evolution/test_backward_deploy_enum.swift | 3 +++ validation-test/Evolution/test_backward_deploy_protocol.swift | 3 +++ validation-test/Evolution/test_backward_deploy_struct.swift | 3 +++ validation-test/Evolution/test_backward_deploy_top_level.swift | 3 +++ validation-test/Evolution/test_protocol_add_requirements.swift | 3 +++ 7 files changed, 21 insertions(+) diff --git a/validation-test/Evolution/test_backward_deploy_always_emit_into_client.swift b/validation-test/Evolution/test_backward_deploy_always_emit_into_client.swift index ca66738b7560e..a5392af9e4cf2 100644 --- a/validation-test/Evolution/test_backward_deploy_always_emit_into_client.swift +++ b/validation-test/Evolution/test_backward_deploy_always_emit_into_client.swift @@ -4,6 +4,9 @@ // Uses swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic +// SR-10913 +// UNSUPPORTED: OS=windows-msvc + import StdlibUnittest import backward_deploy_always_emit_into_client diff --git a/validation-test/Evolution/test_backward_deploy_class.swift b/validation-test/Evolution/test_backward_deploy_class.swift index 2b5bb40893330..e76ff63d9088d 100644 --- a/validation-test/Evolution/test_backward_deploy_class.swift +++ b/validation-test/Evolution/test_backward_deploy_class.swift @@ -4,6 +4,9 @@ // Uses swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic +// SR-10913 +// UNSUPPORTED: OS=windows-msvc + import StdlibUnittest import backward_deploy_class diff --git a/validation-test/Evolution/test_backward_deploy_enum.swift b/validation-test/Evolution/test_backward_deploy_enum.swift index b8fa8c95ad501..058782aac4fdd 100644 --- a/validation-test/Evolution/test_backward_deploy_enum.swift +++ b/validation-test/Evolution/test_backward_deploy_enum.swift @@ -4,6 +4,9 @@ // Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic +// SR-10913 +// UNSUPPORTED: OS=windows-msvc + import StdlibUnittest import backward_deploy_enum diff --git a/validation-test/Evolution/test_backward_deploy_protocol.swift b/validation-test/Evolution/test_backward_deploy_protocol.swift index a2ca336225c6e..526691809649c 100644 --- a/validation-test/Evolution/test_backward_deploy_protocol.swift +++ b/validation-test/Evolution/test_backward_deploy_protocol.swift @@ -4,6 +4,9 @@ // Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic +// SR-10913 +// UNSUPPORTED: OS=windows-msvc + import StdlibUnittest import backward_deploy_protocol diff --git a/validation-test/Evolution/test_backward_deploy_struct.swift b/validation-test/Evolution/test_backward_deploy_struct.swift index 49832ecf965e7..f1fb79ffbb8b4 100644 --- a/validation-test/Evolution/test_backward_deploy_struct.swift +++ b/validation-test/Evolution/test_backward_deploy_struct.swift @@ -4,6 +4,9 @@ // Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic +// SR-10913 +// UNSUPPORTED: OS=windows-msvc + import StdlibUnittest import backward_deploy_struct diff --git a/validation-test/Evolution/test_backward_deploy_top_level.swift b/validation-test/Evolution/test_backward_deploy_top_level.swift index bb03f29ce0855..6229847c10c76 100644 --- a/validation-test/Evolution/test_backward_deploy_top_level.swift +++ b/validation-test/Evolution/test_backward_deploy_top_level.swift @@ -4,6 +4,9 @@ // Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic +// SR-10913 +// UNSUPPORTED: OS=windows-msvc + import StdlibUnittest import backward_deploy_top_level diff --git a/validation-test/Evolution/test_protocol_add_requirements.swift b/validation-test/Evolution/test_protocol_add_requirements.swift index 197a43a221656..eb1ecb7335747 100644 --- a/validation-test/Evolution/test_protocol_add_requirements.swift +++ b/validation-test/Evolution/test_protocol_add_requirements.swift @@ -4,6 +4,9 @@ // Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic +// SR-10913 +// UNSUPPORTED: OS=windows-msvc + import StdlibUnittest import protocol_add_requirements From c7cf96660a3e565b3faadf6746812d48fbb45ef6 Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Mon, 10 Jun 2019 17:01:46 -0700 Subject: [PATCH 094/112] SourceKit/Indentation: align function names in chained trailing closures Chained trailing closures are sibling-like thus they should be aligned. rdar://22205716 --- lib/IDE/Formatting.cpp | 18 +++++++++++ .../SourceKit/CodeFormat/indent-closure.swift | 31 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/lib/IDE/Formatting.cpp b/lib/IDE/Formatting.cpp index ac84c733da910..0cac1f0691c8e 100644 --- a/lib/IDE/Formatting.cpp +++ b/lib/IDE/Formatting.cpp @@ -481,6 +481,24 @@ class FormatContext { } } + // Chained trailing closures shouldn't require additional indentation. + // a.map { + // ... + // }.filter { <--- No indentation here. + // ... + // }.map { <--- No indentation here. + // ... + // } + if (AtExprEnd && AtCursorExpr && isa(AtExprEnd)) { + if (auto *UDE = dyn_cast(AtCursorExpr)) { + if (auto *Base = UDE->getBase()) { + if (exprEndAtLine(Base, Line)) + return false; + } + } + } + + // Indent another level from the outer context by default. return true; } diff --git a/test/SourceKit/CodeFormat/indent-closure.swift b/test/SourceKit/CodeFormat/indent-closure.swift index 56d678a4415d9..b75a3e3df4b7e 100644 --- a/test/SourceKit/CodeFormat/indent-closure.swift +++ b/test/SourceKit/CodeFormat/indent-closure.swift @@ -52,6 +52,16 @@ func foo8() { }) } +func foo9(input: [Int]){ + input.map { (ele) in + ele + 1 + }.filter{(ele) in + return ele > 10 + }.map {(ele) in + return ele + 1 + } +} + // 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 @@ -68,6 +78,17 @@ func foo8() { // RUN: %sourcekitd-test -req=format -line=32 -length=1 %s >>%t.response // RUN: %sourcekitd-test -req=format -line=42 -length=1 %s >>%t.response // RUN: %sourcekitd-test -req=format -line=50 -length=1 %s >>%t.response + +// RUN: %sourcekitd-test -req=format -line=55 -length=1 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=56 -length=1 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=57 -length=1 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=58 -length=1 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=59 -length=1 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=60 -length=1 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=61 -length=1 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=62 -length=1 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=63 -length=1 %s >>%t.response + // RUN: %FileCheck --strict-whitespace %s <%t.response // CHECK: key.sourcetext: " var abc = 1" @@ -94,3 +115,13 @@ func foo8() { // CHECK: key.sourcetext: " })" // CHECK: key.sourcetext: " }, B: {" + +// CHECK: key.sourcetext: "func foo9(input: [Int]){" +// CHECK: key.sourcetext: " input.map { (ele) in" +// CHECK: key.sourcetext: " ele + 1" +// CHECK: key.sourcetext: " }.filter{(ele) in" +// CHECK: key.sourcetext: " return ele > 10" +// CHECK: key.sourcetext: " }.map {(ele) in" +// CHECK: key.sourcetext: " return ele + 1" +// CHECK: key.sourcetext: " }" +// CHECK: key.sourcetext: "}" From b10632811f3a8d7b8e87fd4b65cc667234684cb2 Mon Sep 17 00:00:00 2001 From: Scott Perry Date: Mon, 10 Jun 2019 17:14:26 -0700 Subject: [PATCH 095/112] [Foundation] Bridge difference APIs between Foundation and swift stdlib rdar://problem/51604652 --- include/swift/AST/KnownIdentifiers.def | 1 + include/swift/AST/KnownStdlibTypes.def | 1 + lib/AST/ASTContext.cpp | 4 + .../public/Darwin/Foundation/CMakeLists.txt | 1 + .../NSOrderedCollectionDifference.swift | 106 ++++++++++++++++++ 5 files changed, 113 insertions(+) create mode 100644 stdlib/public/Darwin/Foundation/NSOrderedCollectionDifference.swift diff --git a/include/swift/AST/KnownIdentifiers.def b/include/swift/AST/KnownIdentifiers.def index f5e0e46d8a669..6288b8d7de860 100644 --- a/include/swift/AST/KnownIdentifiers.def +++ b/include/swift/AST/KnownIdentifiers.def @@ -31,6 +31,7 @@ IDENTIFIER(Any) IDENTIFIER(ArrayLiteralElement) IDENTIFIER(atIndexedSubscript) IDENTIFIER_(bridgeToObjectiveC) +IDENTIFIER(Change) IDENTIFIER_WITH_NAME(code_, "_code") IDENTIFIER(CodingKeys) IDENTIFIER(combine) diff --git a/include/swift/AST/KnownStdlibTypes.def b/include/swift/AST/KnownStdlibTypes.def index 07a055d242958..ab30681d0aa3e 100644 --- a/include/swift/AST/KnownStdlibTypes.def +++ b/include/swift/AST/KnownStdlibTypes.def @@ -54,6 +54,7 @@ KNOWN_STDLIB_TYPE_DECL(Array, NominalTypeDecl, 1) KNOWN_STDLIB_TYPE_DECL(Set, NominalTypeDecl, 1) KNOWN_STDLIB_TYPE_DECL(Sequence, NominalTypeDecl, 1) KNOWN_STDLIB_TYPE_DECL(Dictionary, NominalTypeDecl, 2) +KNOWN_STDLIB_TYPE_DECL(CollectionDifference, NominalTypeDecl, 1) KNOWN_STDLIB_TYPE_DECL(AnyHashable, NominalTypeDecl, 0) KNOWN_STDLIB_TYPE_DECL(MutableCollection, ProtocolDecl, 1) KNOWN_STDLIB_TYPE_DECL(Hasher, NominalTypeDecl, 0) diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 93112b8d92982..4d470850daea9 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -4189,6 +4189,10 @@ bool ASTContext::isTypeBridgedInExternalModule( nominal == getFloatDecl() || nominal == getDoubleDecl() || nominal == getArrayDecl() || + nominal == getCollectionDifferenceDecl() || + (nominal->getDeclContext()->getAsDecl() == + getCollectionDifferenceDecl() && + nominal->getBaseName() == Id_Change) || nominal == getDictionaryDecl() || nominal == getSetDecl() || nominal == getStringDecl() || diff --git a/stdlib/public/Darwin/Foundation/CMakeLists.txt b/stdlib/public/Darwin/Foundation/CMakeLists.txt index d69fd1e657a51..31804de6fe95c 100644 --- a/stdlib/public/Darwin/Foundation/CMakeLists.txt +++ b/stdlib/public/Darwin/Foundation/CMakeLists.txt @@ -41,6 +41,7 @@ add_swift_target_library(swiftFoundation ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES NSItemProvider.swift NSNumber.swift NSObject.swift + NSOrderedCollectionDifference.swift NSPredicate.swift NSRange.swift NSSet.swift diff --git a/stdlib/public/Darwin/Foundation/NSOrderedCollectionDifference.swift b/stdlib/public/Darwin/Foundation/NSOrderedCollectionDifference.swift new file mode 100644 index 0000000000000..d07a0fb3d337e --- /dev/null +++ b/stdlib/public/Darwin/Foundation/NSOrderedCollectionDifference.swift @@ -0,0 +1,106 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +@_exported import Foundation // Clang module + +// CollectionDifference.Change is conditionally bridged to NSOrderedCollectionChange +@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) +extension CollectionDifference.Change : _ObjectiveCBridgeable { + @_semantics("convertToObjectiveC") + public func _bridgeToObjectiveC() -> NSOrderedCollectionChange { + switch self { + case .insert(offset: let o, element: let e, associatedWith: let a): + return NSOrderedCollectionChange(object: e, type: .insert, index: o, associatedIndex: a ?? NSNotFound) + case .remove(offset: let o, element: let e, associatedWith: let a): + return NSOrderedCollectionChange(object: e, type: .remove, index: o, associatedIndex: a ?? NSNotFound) + } + } + + public static func _forceBridgeFromObjectiveC(_ input: NSOrderedCollectionChange, result: inout CollectionDifference.Change?) { + let _ = input.object as! ChangeElement + + if !_conditionallyBridgeFromObjectiveC(input, result: &result) { + fatalError("Unable to bridge \(_ObjectiveCType.self) to \(self)") + } + } + + public static func _conditionallyBridgeFromObjectiveC( + _ x: NSOrderedCollectionChange, result: inout CollectionDifference.Change? + ) -> Bool { + guard let element = x.object as? ChangeElement else { return false } + + let a: Int? + if x.associatedIndex == NSNotFound { + a = nil + } else { + a = x.associatedIndex + } + + switch x.changeType { + case .insert: + result = .insert(offset: x.index, element: element, associatedWith: a) + case .remove: + result = .remove(offset: x.index, element: element, associatedWith: a) + default: + return false + } + + return true + } + + @_effects(readonly) + public static func _unconditionallyBridgeFromObjectiveC(_ s: NSOrderedCollectionChange?) -> CollectionDifference.Change { + var result: CollectionDifference.Change? = nil + CollectionDifference.Change._forceBridgeFromObjectiveC(s!, result: &result) + return result! + } +} + +// CollectionDifference is conditionally bridged to NSOrderedCollectionDifference +@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) +extension CollectionDifference : _ObjectiveCBridgeable { + @_semantics("convertToObjectiveC") + public func _bridgeToObjectiveC() -> NSOrderedCollectionDifference { + return NSOrderedCollectionDifference(changes: self.map({ $0 as NSOrderedCollectionChange })) + } + + public static func _forceBridgeFromObjectiveC(_ input: NSOrderedCollectionDifference, result: inout CollectionDifference?) { + if !_conditionallyBridgeFromObjectiveC(input, result: &result) { + fatalError("Unable to bridge \(_ObjectiveCType.self) to \(self)") + } + } + + private static func _formDifference( + from input: NSOrderedCollectionDifference, + _ changeConverter: (Any) -> CollectionDifference.Change? + ) -> CollectionDifference? { + var changes = Array() + let iteratorSeq = IteratorSequence(NSFastEnumerationIterator(input)) + for objc_change in iteratorSeq { + guard let swift_change = changeConverter(objc_change) else { return nil } + changes.append(swift_change) + } + return CollectionDifference(changes) + } + + public static func _conditionallyBridgeFromObjectiveC( + _ input: NSOrderedCollectionDifference, result: inout CollectionDifference? + ) -> Bool { + result = _formDifference(from: input) { $0 as? Change } + return result != nil + } + + @_effects(readonly) + public static func _unconditionallyBridgeFromObjectiveC(_ s: NSOrderedCollectionDifference?) -> CollectionDifference { + return _formDifference(from: s!) { $0 as! Change }! + } +} From 89b918a35a67cede05065285daf14e41ea31aea3 Mon Sep 17 00:00:00 2001 From: Karoy Lorentey Date: Mon, 10 Jun 2019 17:46:03 -0700 Subject: [PATCH 096/112] [Foundation] Temporarily revert to 9999 versions --- .../Darwin/Foundation/NSOrderedCollectionDifference.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/public/Darwin/Foundation/NSOrderedCollectionDifference.swift b/stdlib/public/Darwin/Foundation/NSOrderedCollectionDifference.swift index d07a0fb3d337e..8254a2207d6c8 100644 --- a/stdlib/public/Darwin/Foundation/NSOrderedCollectionDifference.swift +++ b/stdlib/public/Darwin/Foundation/NSOrderedCollectionDifference.swift @@ -13,7 +13,7 @@ @_exported import Foundation // Clang module // CollectionDifference.Change is conditionally bridged to NSOrderedCollectionChange -@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) +@available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) // FIXME(availability-5.1) extension CollectionDifference.Change : _ObjectiveCBridgeable { @_semantics("convertToObjectiveC") public func _bridgeToObjectiveC() -> NSOrderedCollectionChange { @@ -66,7 +66,7 @@ extension CollectionDifference.Change : _ObjectiveCBridgeable { } // CollectionDifference is conditionally bridged to NSOrderedCollectionDifference -@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) +@available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) // FIXME(availability-5.1) extension CollectionDifference : _ObjectiveCBridgeable { @_semantics("convertToObjectiveC") public func _bridgeToObjectiveC() -> NSOrderedCollectionDifference { From 2bc648c26baccd95847cde2ad025c8c1b1fd0375 Mon Sep 17 00:00:00 2001 From: Pavol Vaskovic Date: Tue, 11 Jun 2019 04:44:10 +0200 Subject: [PATCH 097/112] =?UTF-8?q?[stdlib]=20Lemire=E2=80=99s=20Nearly=20?= =?UTF-8?q?Divisionless=20Random=20Integer=20Generation=20(#25286)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [stdlib] Lemire’s nearly divisionless random int Implementation of Daniel Lemire’s “Fast Random Integer Generation in Interval” See https://arxiv.org/pdf/1805.10941.pdf * [stdlib] Simpler, optimized expression * [stdlib] O'Neill’s modulo optimization See http://www.pcg-random.org/posts/bounded-rands.html#optimizing-modulo * [stdlib] Remove modulo optimization Swift, compared to C, seems unable to generate tightly fused instructions here for some reason (probably the division by zero check?)… removing. * [stdlib] Keep OpenBSD debiasing method on 32-bit systems until the https://bugs.swift.org/browse/SR-10910 is resolved. * [stdlib] TODO FIXME SR-10912 Remove the old OpenBSD generation method, once 32-bit systems support multipliedFullWidth on UInt64. --- stdlib/public/core/Random.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/stdlib/public/core/Random.swift b/stdlib/public/core/Random.swift index f3cdfac18cf40..bdbb95c407dd2 100644 --- a/stdlib/public/core/Random.swift +++ b/stdlib/public/core/Random.swift @@ -94,6 +94,7 @@ extension RandomNumberGenerator { upperBound: T ) -> T { _precondition(upperBound != 0, "upperBound cannot be zero.") +#if arch(i386) || arch(arm) // TODO(FIXME) SR-10912 let tmp = (T.max % upperBound) + 1 let range = tmp == upperBound ? 0 : tmp var random: T = 0 @@ -103,6 +104,19 @@ extension RandomNumberGenerator { } while random < range return random % upperBound +#endif +#if arch(x86_64) || arch(arm64) + var random: T = next() + var m = random.multipliedFullWidth(by: upperBound) + if m.low < upperBound { + let t = (0 &- upperBound) % upperBound + while m.low < t { + random = next() + m = random.multipliedFullWidth(by: upperBound) + } + } + return m.high +#endif } } From 6798eea160776e8d8365064424105f4eb6f1a365 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 10 Jun 2019 17:24:41 -0700 Subject: [PATCH 098/112] Evolution: Some of these tests pass with swift_test_mode_optimize_none_with_implicit_dynamic The remaining failures still warrant investigation. --- .../test_backward_deploy_always_emit_into_client.swift | 3 --- validation-test/Evolution/test_backward_deploy_class.swift | 3 --- validation-test/Evolution/test_backward_deploy_enum.swift | 3 --- validation-test/Evolution/test_backward_deploy_protocol.swift | 3 --- validation-test/Evolution/test_backward_deploy_struct.swift | 3 --- validation-test/Evolution/test_backward_deploy_top_level.swift | 3 --- validation-test/Evolution/test_bitwise_takable.swift | 1 - .../Evolution/test_change_default_argument_to_magic.swift | 3 --- .../Evolution/test_class_add_convenience_init.swift | 3 --- validation-test/Evolution/test_class_add_deinit.swift | 3 --- validation-test/Evolution/test_class_add_property.swift | 3 --- .../Evolution/test_class_add_property_attribute.swift | 3 --- .../Evolution/test_class_add_property_subclass.swift | 3 --- .../Evolution/test_class_change_lazy_to_computed.swift | 3 --- validation-test/Evolution/test_class_change_size.swift | 1 - .../Evolution/test_class_change_stored_to_computed.swift | 3 --- .../Evolution/test_class_change_stored_to_observed.swift | 3 --- .../Evolution/test_class_fixed_layout_add_virtual_method.swift | 3 --- .../test_class_fixed_layout_add_virtual_method_subclass.swift | 3 --- .../test_class_fixed_layout_superclass_reorder_methods.swift | 3 --- validation-test/Evolution/test_class_insert_superclass.swift | 1 - validation-test/Evolution/test_class_remove_property.swift | 1 - .../Evolution/test_class_resilient_add_override.swift | 3 --- .../Evolution/test_class_resilient_add_virtual_method.swift | 3 --- .../test_class_resilient_add_virtual_method_subclass.swift | 3 --- .../Evolution/test_class_resilient_superclass_methods.swift | 3 --- .../Evolution/test_class_resilient_superclass_properties.swift | 3 --- .../test_class_resilient_superclass_reorder_methods.swift | 3 --- validation-test/Evolution/test_conformance_reference.swift | 3 --- validation-test/Evolution/test_enum_add_cases.swift | 3 --- validation-test/Evolution/test_enum_add_cases_trap.swift | 3 --- validation-test/Evolution/test_enum_change_size.swift | 1 - validation-test/Evolution/test_enum_reorder_cases.swift | 3 --- .../Evolution/test_function_change_transparent_body.swift | 3 --- .../Evolution/test_generic_resilient_struct_add_property.swift | 3 --- validation-test/Evolution/test_global_change_size.swift | 1 - validation-test/Evolution/test_global_stored_to_computed.swift | 3 --- validation-test/Evolution/test_keypath_default_argument.swift | 3 --- validation-test/Evolution/test_keypaths.swift.gyb | 3 --- validation-test/Evolution/test_move_method_to_extension.swift | 3 --- .../test_opaque_archetypes_change_underlying_type.swift | 3 --- validation-test/Evolution/test_protocol_add_requirements.swift | 3 --- .../Evolution/test_protocol_reorder_requirements.swift | 3 --- validation-test/Evolution/test_rth.swift | 3 --- validation-test/Evolution/test_struct_add_initializer.swift | 3 --- validation-test/Evolution/test_struct_add_property.swift | 1 - .../Evolution/test_struct_add_property_attribute.swift | 3 --- .../Evolution/test_struct_change_lazy_to_computed.swift | 3 --- validation-test/Evolution/test_struct_change_size.swift | 1 - .../Evolution/test_struct_change_stored_to_computed.swift | 1 - .../test_struct_change_stored_to_computed_static.swift | 1 - .../Evolution/test_struct_change_stored_to_observed.swift | 3 --- .../Evolution/test_struct_fixed_layout_add_conformance.swift | 3 --- .../test_struct_fixed_layout_remove_conformance.swift | 1 - validation-test/Evolution/test_struct_remove_property.swift | 1 - .../Evolution/test_struct_resilient_add_conformance.swift | 3 --- .../Evolution/test_struct_resilient_remove_conformance.swift | 1 - .../Evolution/test_struct_static_stored_to_computed.swift | 3 --- 58 files changed, 148 deletions(-) diff --git a/validation-test/Evolution/test_backward_deploy_always_emit_into_client.swift b/validation-test/Evolution/test_backward_deploy_always_emit_into_client.swift index a5392af9e4cf2..1e595632bade2 100644 --- a/validation-test/Evolution/test_backward_deploy_always_emit_into_client.swift +++ b/validation-test/Evolution/test_backward_deploy_always_emit_into_client.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test --backward-deployment // REQUIRES: executable_test -// Uses swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - // SR-10913 // UNSUPPORTED: OS=windows-msvc diff --git a/validation-test/Evolution/test_backward_deploy_class.swift b/validation-test/Evolution/test_backward_deploy_class.swift index e76ff63d9088d..75c4b794c5e8f 100644 --- a/validation-test/Evolution/test_backward_deploy_class.swift +++ b/validation-test/Evolution/test_backward_deploy_class.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test --backward-deployment // REQUIRES: executable_test -// Uses swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - // SR-10913 // UNSUPPORTED: OS=windows-msvc diff --git a/validation-test/Evolution/test_backward_deploy_enum.swift b/validation-test/Evolution/test_backward_deploy_enum.swift index 058782aac4fdd..9b2d367a31481 100644 --- a/validation-test/Evolution/test_backward_deploy_enum.swift +++ b/validation-test/Evolution/test_backward_deploy_enum.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test --backward-deployment // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - // SR-10913 // UNSUPPORTED: OS=windows-msvc diff --git a/validation-test/Evolution/test_backward_deploy_protocol.swift b/validation-test/Evolution/test_backward_deploy_protocol.swift index 526691809649c..a00d49f278ae5 100644 --- a/validation-test/Evolution/test_backward_deploy_protocol.swift +++ b/validation-test/Evolution/test_backward_deploy_protocol.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test --backward-deployment // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - // SR-10913 // UNSUPPORTED: OS=windows-msvc diff --git a/validation-test/Evolution/test_backward_deploy_struct.swift b/validation-test/Evolution/test_backward_deploy_struct.swift index f1fb79ffbb8b4..f0430c73252ce 100644 --- a/validation-test/Evolution/test_backward_deploy_struct.swift +++ b/validation-test/Evolution/test_backward_deploy_struct.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test --backward-deployment // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - // SR-10913 // UNSUPPORTED: OS=windows-msvc diff --git a/validation-test/Evolution/test_backward_deploy_top_level.swift b/validation-test/Evolution/test_backward_deploy_top_level.swift index 6229847c10c76..b72f64516c221 100644 --- a/validation-test/Evolution/test_backward_deploy_top_level.swift +++ b/validation-test/Evolution/test_backward_deploy_top_level.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test --backward-deployment // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - // SR-10913 // UNSUPPORTED: OS=windows-msvc diff --git a/validation-test/Evolution/test_bitwise_takable.swift b/validation-test/Evolution/test_bitwise_takable.swift index 44a65ebeecbef..9e58bced92c53 100644 --- a/validation-test/Evolution/test_bitwise_takable.swift +++ b/validation-test/Evolution/test_bitwise_takable.swift @@ -1,7 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic import StdlibUnittest diff --git a/validation-test/Evolution/test_change_default_argument_to_magic.swift b/validation-test/Evolution/test_change_default_argument_to_magic.swift index cb796616bb3c3..730d0ba6afada 100644 --- a/validation-test/Evolution/test_change_default_argument_to_magic.swift +++ b/validation-test/Evolution/test_change_default_argument_to_magic.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import change_default_argument_to_magic diff --git a/validation-test/Evolution/test_class_add_convenience_init.swift b/validation-test/Evolution/test_class_add_convenience_init.swift index 3befc292f017d..95069e5d8090b 100644 --- a/validation-test/Evolution/test_class_add_convenience_init.swift +++ b/validation-test/Evolution/test_class_add_convenience_init.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_add_convenience_init diff --git a/validation-test/Evolution/test_class_add_deinit.swift b/validation-test/Evolution/test_class_add_deinit.swift index d2d7427664abb..2aae0de153b4c 100644 --- a/validation-test/Evolution/test_class_add_deinit.swift +++ b/validation-test/Evolution/test_class_add_deinit.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_add_deinit diff --git a/validation-test/Evolution/test_class_add_property.swift b/validation-test/Evolution/test_class_add_property.swift index ed01b02ce7641..64ebd5821e01f 100644 --- a/validation-test/Evolution/test_class_add_property.swift +++ b/validation-test/Evolution/test_class_add_property.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_add_property diff --git a/validation-test/Evolution/test_class_add_property_attribute.swift b/validation-test/Evolution/test_class_add_property_attribute.swift index 2b060af5dee01..178e69b8fcabb 100644 --- a/validation-test/Evolution/test_class_add_property_attribute.swift +++ b/validation-test/Evolution/test_class_add_property_attribute.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_add_property_attribute diff --git a/validation-test/Evolution/test_class_add_property_subclass.swift b/validation-test/Evolution/test_class_add_property_subclass.swift index 49f10c4c3f533..78367ccc30231 100644 --- a/validation-test/Evolution/test_class_add_property_subclass.swift +++ b/validation-test/Evolution/test_class_add_property_subclass.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_add_property_subclass diff --git a/validation-test/Evolution/test_class_change_lazy_to_computed.swift b/validation-test/Evolution/test_class_change_lazy_to_computed.swift index 8cdf0292a2ca2..07b6331f9ae55 100644 --- a/validation-test/Evolution/test_class_change_lazy_to_computed.swift +++ b/validation-test/Evolution/test_class_change_lazy_to_computed.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_change_lazy_to_computed diff --git a/validation-test/Evolution/test_class_change_size.swift b/validation-test/Evolution/test_class_change_size.swift index 06d29ce236755..ec0952e85ca12 100644 --- a/validation-test/Evolution/test_class_change_size.swift +++ b/validation-test/Evolution/test_class_change_size.swift @@ -1,7 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic import StdlibUnittest diff --git a/validation-test/Evolution/test_class_change_stored_to_computed.swift b/validation-test/Evolution/test_class_change_stored_to_computed.swift index 835c4fd156c29..980632902feaf 100644 --- a/validation-test/Evolution/test_class_change_stored_to_computed.swift +++ b/validation-test/Evolution/test_class_change_stored_to_computed.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_change_stored_to_computed diff --git a/validation-test/Evolution/test_class_change_stored_to_observed.swift b/validation-test/Evolution/test_class_change_stored_to_observed.swift index 37cb2f047f867..b11ce83b61f36 100644 --- a/validation-test/Evolution/test_class_change_stored_to_observed.swift +++ b/validation-test/Evolution/test_class_change_stored_to_observed.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_change_stored_to_observed diff --git a/validation-test/Evolution/test_class_fixed_layout_add_virtual_method.swift b/validation-test/Evolution/test_class_fixed_layout_add_virtual_method.swift index 44ecfe48688fa..d4d7a269ee6c3 100644 --- a/validation-test/Evolution/test_class_fixed_layout_add_virtual_method.swift +++ b/validation-test/Evolution/test_class_fixed_layout_add_virtual_method.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_fixed_layout_add_virtual_method diff --git a/validation-test/Evolution/test_class_fixed_layout_add_virtual_method_subclass.swift b/validation-test/Evolution/test_class_fixed_layout_add_virtual_method_subclass.swift index d49ecae3e04d6..193148d549d2c 100644 --- a/validation-test/Evolution/test_class_fixed_layout_add_virtual_method_subclass.swift +++ b/validation-test/Evolution/test_class_fixed_layout_add_virtual_method_subclass.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_fixed_layout_add_virtual_method_subclass diff --git a/validation-test/Evolution/test_class_fixed_layout_superclass_reorder_methods.swift b/validation-test/Evolution/test_class_fixed_layout_superclass_reorder_methods.swift index dd54226a55bb0..478955e10ce3a 100644 --- a/validation-test/Evolution/test_class_fixed_layout_superclass_reorder_methods.swift +++ b/validation-test/Evolution/test_class_fixed_layout_superclass_reorder_methods.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_fixed_layout_superclass_reorder_methods diff --git a/validation-test/Evolution/test_class_insert_superclass.swift b/validation-test/Evolution/test_class_insert_superclass.swift index f1205a19f10bd..1ee00fa15454f 100644 --- a/validation-test/Evolution/test_class_insert_superclass.swift +++ b/validation-test/Evolution/test_class_insert_superclass.swift @@ -1,7 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic import StdlibUnittest diff --git a/validation-test/Evolution/test_class_remove_property.swift b/validation-test/Evolution/test_class_remove_property.swift index 6cf4d818d4306..e514a8b4c89f4 100644 --- a/validation-test/Evolution/test_class_remove_property.swift +++ b/validation-test/Evolution/test_class_remove_property.swift @@ -1,7 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic import StdlibUnittest diff --git a/validation-test/Evolution/test_class_resilient_add_override.swift b/validation-test/Evolution/test_class_resilient_add_override.swift index 8c142df3dea0f..1313b0d8b3aef 100644 --- a/validation-test/Evolution/test_class_resilient_add_override.swift +++ b/validation-test/Evolution/test_class_resilient_add_override.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_resilient_add_override diff --git a/validation-test/Evolution/test_class_resilient_add_virtual_method.swift b/validation-test/Evolution/test_class_resilient_add_virtual_method.swift index 268450171dd48..440ee7b797115 100644 --- a/validation-test/Evolution/test_class_resilient_add_virtual_method.swift +++ b/validation-test/Evolution/test_class_resilient_add_virtual_method.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_resilient_add_virtual_method diff --git a/validation-test/Evolution/test_class_resilient_add_virtual_method_subclass.swift b/validation-test/Evolution/test_class_resilient_add_virtual_method_subclass.swift index 496a35921ca0d..21b4d3ec9bb30 100644 --- a/validation-test/Evolution/test_class_resilient_add_virtual_method_subclass.swift +++ b/validation-test/Evolution/test_class_resilient_add_virtual_method_subclass.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_resilient_add_virtual_method_subclass diff --git a/validation-test/Evolution/test_class_resilient_superclass_methods.swift b/validation-test/Evolution/test_class_resilient_superclass_methods.swift index 710988b02e7c6..58e354503b5f3 100644 --- a/validation-test/Evolution/test_class_resilient_superclass_methods.swift +++ b/validation-test/Evolution/test_class_resilient_superclass_methods.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_resilient_superclass_methods diff --git a/validation-test/Evolution/test_class_resilient_superclass_properties.swift b/validation-test/Evolution/test_class_resilient_superclass_properties.swift index c79988221e68e..4673bf58d4043 100644 --- a/validation-test/Evolution/test_class_resilient_superclass_properties.swift +++ b/validation-test/Evolution/test_class_resilient_superclass_properties.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_resilient_superclass_properties diff --git a/validation-test/Evolution/test_class_resilient_superclass_reorder_methods.swift b/validation-test/Evolution/test_class_resilient_superclass_reorder_methods.swift index a4da0677cb892..b67ea4b8a801a 100644 --- a/validation-test/Evolution/test_class_resilient_superclass_reorder_methods.swift +++ b/validation-test/Evolution/test_class_resilient_superclass_reorder_methods.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import class_resilient_superclass_reorder_methods diff --git a/validation-test/Evolution/test_conformance_reference.swift b/validation-test/Evolution/test_conformance_reference.swift index a239e2392bf07..94971ec3a3c04 100644 --- a/validation-test/Evolution/test_conformance_reference.swift +++ b/validation-test/Evolution/test_conformance_reference.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test --no-symbol-diff // REQUIRES: executable_test -// Uses swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import conformance_reference diff --git a/validation-test/Evolution/test_enum_add_cases.swift b/validation-test/Evolution/test_enum_add_cases.swift index 447a4e94e7d22..5a7be594b126b 100644 --- a/validation-test/Evolution/test_enum_add_cases.swift +++ b/validation-test/Evolution/test_enum_add_cases.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import enum_add_cases diff --git a/validation-test/Evolution/test_enum_add_cases_trap.swift b/validation-test/Evolution/test_enum_add_cases_trap.swift index c283dbb3f9188..e5b8e2c1d53b4 100644 --- a/validation-test/Evolution/test_enum_add_cases_trap.swift +++ b/validation-test/Evolution/test_enum_add_cases_trap.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import enum_add_cases_trap diff --git a/validation-test/Evolution/test_enum_change_size.swift b/validation-test/Evolution/test_enum_change_size.swift index 6d059e643693c..5c8f97d95c337 100644 --- a/validation-test/Evolution/test_enum_change_size.swift +++ b/validation-test/Evolution/test_enum_change_size.swift @@ -1,7 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic import StdlibUnittest diff --git a/validation-test/Evolution/test_enum_reorder_cases.swift b/validation-test/Evolution/test_enum_reorder_cases.swift index 49eb8fe2a075f..b342e7f880e4f 100644 --- a/validation-test/Evolution/test_enum_reorder_cases.swift +++ b/validation-test/Evolution/test_enum_reorder_cases.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import enum_reorder_cases import StdlibUnittest diff --git a/validation-test/Evolution/test_function_change_transparent_body.swift b/validation-test/Evolution/test_function_change_transparent_body.swift index 3cfe03d3b626b..577d875c61fef 100644 --- a/validation-test/Evolution/test_function_change_transparent_body.swift +++ b/validation-test/Evolution/test_function_change_transparent_body.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import function_change_transparent_body diff --git a/validation-test/Evolution/test_generic_resilient_struct_add_property.swift b/validation-test/Evolution/test_generic_resilient_struct_add_property.swift index bdedbd400fddd..d0ab07405557a 100644 --- a/validation-test/Evolution/test_generic_resilient_struct_add_property.swift +++ b/validation-test/Evolution/test_generic_resilient_struct_add_property.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import generic_resilient_struct_add_property diff --git a/validation-test/Evolution/test_global_change_size.swift b/validation-test/Evolution/test_global_change_size.swift index db94f24ebddd3..21e10b7318188 100644 --- a/validation-test/Evolution/test_global_change_size.swift +++ b/validation-test/Evolution/test_global_change_size.swift @@ -1,7 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic import StdlibUnittest diff --git a/validation-test/Evolution/test_global_stored_to_computed.swift b/validation-test/Evolution/test_global_stored_to_computed.swift index 7b76ed7111fed..b5323f75456af 100644 --- a/validation-test/Evolution/test_global_stored_to_computed.swift +++ b/validation-test/Evolution/test_global_stored_to_computed.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import global_stored_to_computed diff --git a/validation-test/Evolution/test_keypath_default_argument.swift b/validation-test/Evolution/test_keypath_default_argument.swift index 9b0350d259456..ceed3a7043343 100644 --- a/validation-test/Evolution/test_keypath_default_argument.swift +++ b/validation-test/Evolution/test_keypath_default_argument.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import keypath_default_argument diff --git a/validation-test/Evolution/test_keypaths.swift.gyb b/validation-test/Evolution/test_keypaths.swift.gyb index c66e262193bca..c67cb46f5b47e 100644 --- a/validation-test/Evolution/test_keypaths.swift.gyb +++ b/validation-test/Evolution/test_keypaths.swift.gyb @@ -7,9 +7,6 @@ // REQUIRES: executable_test -// Uses swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import keypaths import StdlibUnittest diff --git a/validation-test/Evolution/test_move_method_to_extension.swift b/validation-test/Evolution/test_move_method_to_extension.swift index ce675f4b810a9..e34b494b03b04 100644 --- a/validation-test/Evolution/test_move_method_to_extension.swift +++ b/validation-test/Evolution/test_move_method_to_extension.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import move_method_to_extension diff --git a/validation-test/Evolution/test_opaque_archetypes_change_underlying_type.swift b/validation-test/Evolution/test_opaque_archetypes_change_underlying_type.swift index d8a8e4ac32495..4b99f7881455e 100644 --- a/validation-test/Evolution/test_opaque_archetypes_change_underlying_type.swift +++ b/validation-test/Evolution/test_opaque_archetypes_change_underlying_type.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import opaque_archetypes_change_underlying_type import StdlibUnittest diff --git a/validation-test/Evolution/test_protocol_add_requirements.swift b/validation-test/Evolution/test_protocol_add_requirements.swift index eb1ecb7335747..4ea1430116f29 100644 --- a/validation-test/Evolution/test_protocol_add_requirements.swift +++ b/validation-test/Evolution/test_protocol_add_requirements.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - // SR-10913 // UNSUPPORTED: OS=windows-msvc diff --git a/validation-test/Evolution/test_protocol_reorder_requirements.swift b/validation-test/Evolution/test_protocol_reorder_requirements.swift index cdd04eef877fe..d7aef9863f5fe 100644 --- a/validation-test/Evolution/test_protocol_reorder_requirements.swift +++ b/validation-test/Evolution/test_protocol_reorder_requirements.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import protocol_reorder_requirements diff --git a/validation-test/Evolution/test_rth.swift b/validation-test/Evolution/test_rth.swift index 86b0e88923310..07a02413216f4 100644 --- a/validation-test/Evolution/test_rth.swift +++ b/validation-test/Evolution/test_rth.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - // Check for the 'rth' tool itself, to make sure it's doing what we expect. import rth diff --git a/validation-test/Evolution/test_struct_add_initializer.swift b/validation-test/Evolution/test_struct_add_initializer.swift index bb6235a45c7cb..9f04fe94f173e 100644 --- a/validation-test/Evolution/test_struct_add_initializer.swift +++ b/validation-test/Evolution/test_struct_add_initializer.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import struct_add_initializer diff --git a/validation-test/Evolution/test_struct_add_property.swift b/validation-test/Evolution/test_struct_add_property.swift index 96bd954d71059..c98074c8782e9 100644 --- a/validation-test/Evolution/test_struct_add_property.swift +++ b/validation-test/Evolution/test_struct_add_property.swift @@ -1,7 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic import StdlibUnittest diff --git a/validation-test/Evolution/test_struct_add_property_attribute.swift b/validation-test/Evolution/test_struct_add_property_attribute.swift index 02c03aa1b2fb0..543baaca78ea2 100644 --- a/validation-test/Evolution/test_struct_add_property_attribute.swift +++ b/validation-test/Evolution/test_struct_add_property_attribute.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import struct_add_property_attribute diff --git a/validation-test/Evolution/test_struct_change_lazy_to_computed.swift b/validation-test/Evolution/test_struct_change_lazy_to_computed.swift index e13f3825a46d8..dfabc875c34c7 100644 --- a/validation-test/Evolution/test_struct_change_lazy_to_computed.swift +++ b/validation-test/Evolution/test_struct_change_lazy_to_computed.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import struct_change_lazy_to_computed diff --git a/validation-test/Evolution/test_struct_change_size.swift b/validation-test/Evolution/test_struct_change_size.swift index 823958a81a61c..707ec9e41718e 100644 --- a/validation-test/Evolution/test_struct_change_size.swift +++ b/validation-test/Evolution/test_struct_change_size.swift @@ -1,7 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic import StdlibUnittest diff --git a/validation-test/Evolution/test_struct_change_stored_to_computed.swift b/validation-test/Evolution/test_struct_change_stored_to_computed.swift index 3656f6cfca435..dbece4f509a72 100644 --- a/validation-test/Evolution/test_struct_change_stored_to_computed.swift +++ b/validation-test/Evolution/test_struct_change_stored_to_computed.swift @@ -1,7 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic import StdlibUnittest diff --git a/validation-test/Evolution/test_struct_change_stored_to_computed_static.swift b/validation-test/Evolution/test_struct_change_stored_to_computed_static.swift index d33b06f5b2d9c..43a3869f3c18b 100644 --- a/validation-test/Evolution/test_struct_change_stored_to_computed_static.swift +++ b/validation-test/Evolution/test_struct_change_stored_to_computed_static.swift @@ -1,7 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic import StdlibUnittest diff --git a/validation-test/Evolution/test_struct_change_stored_to_observed.swift b/validation-test/Evolution/test_struct_change_stored_to_observed.swift index 1b9e42cc6aefc..7692368c5e5fe 100644 --- a/validation-test/Evolution/test_struct_change_stored_to_observed.swift +++ b/validation-test/Evolution/test_struct_change_stored_to_observed.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Uses swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import struct_change_stored_to_observed diff --git a/validation-test/Evolution/test_struct_fixed_layout_add_conformance.swift b/validation-test/Evolution/test_struct_fixed_layout_add_conformance.swift index 32ea815c99fb8..995fe4aba136f 100644 --- a/validation-test/Evolution/test_struct_fixed_layout_add_conformance.swift +++ b/validation-test/Evolution/test_struct_fixed_layout_add_conformance.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import struct_fixed_layout_add_conformance diff --git a/validation-test/Evolution/test_struct_fixed_layout_remove_conformance.swift b/validation-test/Evolution/test_struct_fixed_layout_remove_conformance.swift index c4350e02a8dd0..38fafd13731aa 100644 --- a/validation-test/Evolution/test_struct_fixed_layout_remove_conformance.swift +++ b/validation-test/Evolution/test_struct_fixed_layout_remove_conformance.swift @@ -1,7 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic import StdlibUnittest diff --git a/validation-test/Evolution/test_struct_remove_property.swift b/validation-test/Evolution/test_struct_remove_property.swift index 7fe1a9637c442..1217a972bf5c6 100644 --- a/validation-test/Evolution/test_struct_remove_property.swift +++ b/validation-test/Evolution/test_struct_remove_property.swift @@ -1,7 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic import StdlibUnittest diff --git a/validation-test/Evolution/test_struct_resilient_add_conformance.swift b/validation-test/Evolution/test_struct_resilient_add_conformance.swift index 67e2d88c88595..d1aafecb546c3 100644 --- a/validation-test/Evolution/test_struct_resilient_add_conformance.swift +++ b/validation-test/Evolution/test_struct_resilient_add_conformance.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import struct_resilient_add_conformance diff --git a/validation-test/Evolution/test_struct_resilient_remove_conformance.swift b/validation-test/Evolution/test_struct_resilient_remove_conformance.swift index 8921785e4c7a9..603eb53b21c0d 100644 --- a/validation-test/Evolution/test_struct_resilient_remove_conformance.swift +++ b/validation-test/Evolution/test_struct_resilient_remove_conformance.swift @@ -1,7 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. // UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic import StdlibUnittest diff --git a/validation-test/Evolution/test_struct_static_stored_to_computed.swift b/validation-test/Evolution/test_struct_static_stored_to_computed.swift index 6643f63592f88..2575fabc3b908 100644 --- a/validation-test/Evolution/test_struct_static_stored_to_computed.swift +++ b/validation-test/Evolution/test_struct_static_stored_to_computed.swift @@ -1,9 +1,6 @@ // RUN: %target-resilience-test // REQUIRES: executable_test -// Use swift-version 4. -// UNSUPPORTED: swift_test_mode_optimize_none_with_implicit_dynamic - import StdlibUnittest import struct_static_stored_to_computed From 712927c4942a470447f381f31a01f33e0b9fc2c8 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 11 Jun 2019 00:50:47 -0700 Subject: [PATCH 099/112] Sema: Go back to synthesizing hashValue on _StoredBridgedNSError conformers Commit e0bba70 added a default implementation, however this is wrong for non-imported types. Instead, synthesize the body as before. Since this is one of the few derived methods that can appear on an imported type, make sure to build fully type-checked AST. Fixes . --- .../DerivedConformanceEquatableHashable.cpp | 29 +++++++++++++++++-- stdlib/public/Darwin/Foundation/NSError.swift | 4 --- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp index 56aa16303a8ca..f69b16877ced0 100644 --- a/lib/Sema/DerivedConformanceEquatableHashable.cpp +++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp @@ -1055,18 +1055,41 @@ deriveBodyHashable_hashValue(AbstractFunctionDecl *hashValueDecl, void *) { // return _hashValue(for: self) auto *hashFunc = C.getHashValueForDecl(); - auto hashExpr = new (C) DeclRefExpr(hashFunc, DeclNameLoc(), + if (!hashFunc->hasInterfaceType()) + C.getLazyResolver()->resolveDeclSignature(hashFunc); + + auto selfType = hashValueDecl->mapTypeIntoContext( + parentDC->getSelfInterfaceType()); + auto hashableProto = C.getProtocol(KnownProtocolKind::Hashable); + auto conformance = TypeChecker::conformsToProtocol(selfType, hashableProto, + parentDC, None); + auto subs = SubstitutionMap::get(hashFunc->getGenericSignature(), + ArrayRef(selfType), + ArrayRef(*conformance)); + ConcreteDeclRef hashRef(hashFunc, subs); + + auto hashExpr = new (C) DeclRefExpr(hashRef, DeclNameLoc(), /*implicit*/ true); + + Type intType = C.getIntDecl()->getDeclaredType(); + hashExpr->setType(FunctionType::get(AnyFunctionType::Param(selfType), + intType)); + auto selfDecl = hashValueDecl->getImplicitSelfDecl(); auto selfRef = new (C) DeclRefExpr(selfDecl, DeclNameLoc(), /*implicit*/ true); - auto callExpr = CallExpr::createImplicit(C, hashExpr, - { selfRef }, { C.Id_for }); + selfRef->setType(selfType); + + auto callExpr = CallExpr::createImplicit(C, hashExpr, { selfRef }, { }); + callExpr->setType(intType); + callExpr->setThrows(false); + auto returnStmt = new (C) ReturnStmt(SourceLoc(), callExpr); auto body = BraceStmt::create(C, SourceLoc(), {returnStmt}, SourceLoc(), /*implicit*/ true); hashValueDecl->setBody(body); + hashValueDecl->setBodyTypeCheckedIfPresent(); } /// Derive a 'hashValue' implementation. diff --git a/stdlib/public/Darwin/Foundation/NSError.swift b/stdlib/public/Darwin/Foundation/NSError.swift index 996d2d2f3bf18..57a238566b6c4 100644 --- a/stdlib/public/Darwin/Foundation/NSError.swift +++ b/stdlib/public/Darwin/Foundation/NSError.swift @@ -489,10 +489,6 @@ extension _BridgedStoredNSError { public func hash(into hasher: inout Hasher) { hasher.combine(_nsError) } - - @_alwaysEmitIntoClient public var hashValue: Int { - return _nsError.hashValue - } } /// Describes the code of an error. From c84aad8bf195a641e504760dc909265191dc99fc Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 11 Jun 2019 01:29:54 -0700 Subject: [PATCH 100/112] Sema: TypeChecker::conformsToProtocol() is static --- lib/Sema/CSApply.cpp | 55 +++++++++---------- lib/Sema/CSBindings.cpp | 2 +- lib/Sema/CSDiag.cpp | 22 ++++---- lib/Sema/CSGen.cpp | 4 +- lib/Sema/CSRanking.cpp | 2 +- lib/Sema/CSSimplify.cpp | 2 +- lib/Sema/CSSolver.cpp | 12 ++-- lib/Sema/CalleeCandidateInfo.cpp | 4 +- lib/Sema/DerivedConformanceCodable.cpp | 42 +++++++------- .../DerivedConformanceEquatableHashable.cpp | 15 ++--- .../DerivedConformanceRawRepresentable.cpp | 6 +- lib/Sema/DerivedConformances.cpp | 2 +- lib/Sema/TypeCheckAttr.cpp | 21 +++---- lib/Sema/TypeCheckAvailability.cpp | 8 +-- lib/Sema/TypeCheckConstraints.cpp | 2 +- lib/Sema/TypeCheckDecl.cpp | 13 +++-- lib/Sema/TypeCheckNameLookup.cpp | 8 +-- lib/Sema/TypeCheckProtocol.cpp | 7 ++- lib/Sema/TypeCheckProtocolInference.cpp | 2 +- lib/Sema/TypeCheckStmt.cpp | 12 ++-- 20 files changed, 120 insertions(+), 121 deletions(-) diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 6e9da3712d9d8..912e24b11d170 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -77,8 +77,6 @@ SubstitutionMap Solution::computeSubstitutions( for (const auto &opened : openedTypes->second) subs[opened.first] = getFixedType(opened.second); - auto &tc = getConstraintSystem().getTypeChecker(); - auto lookupConformanceFn = [&](CanType original, Type replacement, ProtocolDecl *protoType) -> Optional { @@ -88,9 +86,9 @@ SubstitutionMap Solution::computeSubstitutions( return ProtocolConformanceRef(protoType); } - return tc.conformsToProtocol(replacement, protoType, - getConstraintSystem().DC, - ConformanceCheckFlags::InExpression); + return TypeChecker::conformsToProtocol(replacement, protoType, + getConstraintSystem().DC, + ConformanceCheckFlags::InExpression); }; return SubstitutionMap::get(sig, @@ -425,7 +423,7 @@ namespace { if (!baseTy->is() && !baseTy->isAnyExistentialType()) { auto &tc = cs.getTypeChecker(); auto conformance = - tc.conformsToProtocol( + TypeChecker::conformsToProtocol( baseTy, proto, cs.DC, ConformanceCheckFlags::InExpression); if (conformance && conformance->isConcrete()) { @@ -1694,10 +1692,10 @@ namespace { // Try to find the conformance of the value type to _BridgedToObjectiveC. auto bridgedToObjectiveCConformance - = tc.conformsToProtocol(valueType, - bridgedProto, - cs.DC, - ConformanceCheckFlags::InExpression); + = TypeChecker::conformsToProtocol(valueType, + bridgedProto, + cs.DC, + ConformanceCheckFlags::InExpression); FuncDecl *fn = nullptr; @@ -1973,8 +1971,8 @@ namespace { ProtocolDecl *protocol = tc.getProtocol( expr->getLoc(), KnownProtocolKind::ExpressibleByStringLiteral); - if (!tc.conformsToProtocol(type, protocol, cs.DC, - ConformanceCheckFlags::InExpression)) { + if (!TypeChecker::conformsToProtocol(type, protocol, cs.DC, + ConformanceCheckFlags::InExpression)) { // If the type does not conform to ExpressibleByStringLiteral, it should // be ExpressibleByExtendedGraphemeClusterLiteral. protocol = tc.getProtocol( @@ -1983,8 +1981,8 @@ namespace { isStringLiteral = false; isGraphemeClusterLiteral = true; } - if (!tc.conformsToProtocol(type, protocol, cs.DC, - ConformanceCheckFlags::InExpression)) { + if (!TypeChecker::conformsToProtocol(type, protocol, cs.DC, + ConformanceCheckFlags::InExpression)) { // ... or it should be ExpressibleByUnicodeScalarLiteral. protocol = tc.getProtocol( expr->getLoc(), @@ -2105,8 +2103,8 @@ namespace { assert(proto && "Missing string interpolation protocol?"); auto conformance = - tc.conformsToProtocol(type, proto, cs.DC, - ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(type, proto, cs.DC, + ConformanceCheckFlags::InExpression); assert(conformance && "string interpolation type conforms to protocol"); DeclName constrName(tc.Context, DeclBaseName::createConstructor(), argLabels); @@ -2234,8 +2232,8 @@ namespace { auto proto = tc.getLiteralProtocol(expr); assert(proto && "Missing object literal protocol?"); auto conformance = - tc.conformsToProtocol(conformingType, proto, cs.DC, - ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(conformingType, proto, cs.DC, + ConformanceCheckFlags::InExpression); assert(conformance && "object literal type conforms to protocol"); Expr *base = TypeExpr::createImplicitHack(expr->getLoc(), conformingType, @@ -2898,8 +2896,8 @@ namespace { assert(arrayProto && "type-checked array literal w/o protocol?!"); auto conformance = - tc.conformsToProtocol(arrayTy, arrayProto, cs.DC, - ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(arrayTy, arrayProto, cs.DC, + ConformanceCheckFlags::InExpression); assert(conformance && "Type does not conform to protocol?"); DeclName name(tc.Context, DeclBaseName::createConstructor(), @@ -2943,8 +2941,8 @@ namespace { KnownProtocolKind::ExpressibleByDictionaryLiteral); auto conformance = - tc.conformsToProtocol(dictionaryTy, dictionaryProto, cs.DC, - ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(dictionaryTy, dictionaryProto, cs.DC, + ConformanceCheckFlags::InExpression); if (!conformance) return nullptr; @@ -4572,7 +4570,6 @@ namespace { auto hashable = cs.getASTContext().getProtocol(KnownProtocolKind::Hashable); - auto &TC = cs.getTypeChecker(); auto fnType = overload.openedType->castTo(); for (const auto ¶m : fnType->getParams()) { auto indexType = simplifyType(param.getPlainType()); @@ -4580,8 +4577,8 @@ namespace { // verified by the solver, we just need to get it again // with all of the generic parameters resolved. auto hashableConformance = - TC.conformsToProtocol(indexType, hashable, cs.DC, - ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(indexType, hashable, cs.DC, + ConformanceCheckFlags::InExpression); assert(hashableConformance.hasValue()); conformances.push_back(*hashableConformance); @@ -6242,7 +6239,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType, // Find the conformance of the source type to Hashable. auto hashable = tc.Context.getProtocol(KnownProtocolKind::Hashable); auto conformance = - tc.conformsToProtocol( + TypeChecker::conformsToProtocol( cs.getType(expr), hashable, cs.DC, ConformanceCheckFlags::InExpression); assert(conformance && "must conform to Hashable"); @@ -6748,8 +6745,8 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal, Optional builtinConformance; if (builtinProtocol && (builtinConformance = - tc.conformsToProtocol(type, builtinProtocol, cs.DC, - ConformanceCheckFlags::InExpression))) { + TypeChecker::conformsToProtocol(type, builtinProtocol, cs.DC, + ConformanceCheckFlags::InExpression))) { // Find the witness that we'll use to initialize the type via a builtin // literal. @@ -6780,7 +6777,7 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal, // This literal type must conform to the (non-builtin) protocol. assert(protocol && "requirements should have stopped recursion"); - auto conformance = tc.conformsToProtocol(type, protocol, cs.DC, + auto conformance = TypeChecker::conformsToProtocol(type, protocol, cs.DC, ConformanceCheckFlags::InExpression); assert(conformance && "must conform to literal protocol"); diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index 6258a705a552f..be679cebf0458 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -676,7 +676,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) { do { // If the type conforms to this protocol, we're covered. - if (tc.conformsToProtocol( + if (TypeChecker::conformsToProtocol( testType, protocol, DC, (ConformanceCheckFlags::InExpression | ConformanceCheckFlags::SkipConditionalRequirements))) { diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index 55648f3829a91..ebe79ebcf8a0e 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -1212,7 +1212,7 @@ bool FailureDiagnosis::diagnoseGeneralConversionFailure(Constraint *constraint){ } // Emit a conformance error through conformsToProtocol. - if (auto conformance = CS.TC.conformsToProtocol( + if (auto conformance = TypeChecker::conformsToProtocol( fromType, PT->getDecl(), CS.DC, ConformanceCheckFlags::InExpression, expr->getLoc())) { if (conformance->isAbstract() || @@ -1724,8 +1724,8 @@ static bool conformsToKnownProtocol(Type fromType, KnownProtocolKind kind, if (!proto) return false; - if (CS.TC.conformsToProtocol(fromType, proto, CS.DC, - ConformanceCheckFlags::InExpression)) { + if (TypeChecker::conformsToProtocol(fromType, proto, CS.DC, + ConformanceCheckFlags::InExpression)) { return true; } @@ -1745,7 +1745,7 @@ static Type isRawRepresentable(Type fromType, const ConstraintSystem &CS) { if (!rawReprType) return Type(); - auto conformance = CS.TC.conformsToProtocol( + auto conformance = TypeChecker::conformsToProtocol( fromType, rawReprType, CS.DC, ConformanceCheckFlags::InExpression); if (!conformance) return Type(); @@ -2122,8 +2122,8 @@ bool FailureDiagnosis::diagnoseContextualConversionError( if (auto errorCodeProtocol = TC.Context.getProtocol(KnownProtocolKind::ErrorCodeProtocol)) { if (auto conformance = - TC.conformsToProtocol(CS.getType(expr), errorCodeProtocol, CS.DC, - ConformanceCheckFlags::InExpression)) { + TypeChecker::conformsToProtocol(CS.getType(expr), errorCodeProtocol, CS.DC, + ConformanceCheckFlags::InExpression)) { Type errorCodeType = CS.getType(expr); Type errorType = conformance->getTypeWitnessByName(errorCodeType, @@ -6261,8 +6261,8 @@ bool FailureDiagnosis::visitArrayExpr(ArrayExpr *E) { // Check to see if the contextual type conforms. if (auto Conformance - = CS.TC.conformsToProtocol(contextualType, ALC, CS.DC, - ConformanceCheckFlags::InExpression)) { + = TypeChecker::conformsToProtocol(contextualType, ALC, CS.DC, + ConformanceCheckFlags::InExpression)) { Type contextualElementType = Conformance->getTypeWitnessByName( contextualType, CS.getASTContext().Id_ArrayLiteralElement) @@ -6286,8 +6286,8 @@ bool FailureDiagnosis::visitArrayExpr(ArrayExpr *E) { if (!DLC) return visitExpr(E); - if (CS.TC.conformsToProtocol(contextualType, DLC, CS.DC, - ConformanceCheckFlags::InExpression)) { + if (TypeChecker::conformsToProtocol(contextualType, DLC, CS.DC, + ConformanceCheckFlags::InExpression)) { // If the contextual type conforms to ExpressibleByDictionaryLiteral and // this is an empty array, then they meant "[:]". auto numElements = E->getNumElements(); @@ -6344,7 +6344,7 @@ bool FailureDiagnosis::visitDictionaryExpr(DictionaryExpr *E) { // Validate the contextual type conforms to ExpressibleByDictionaryLiteral // and figure out what the contextual Key/Value types are in place. - auto Conformance = CS.TC.conformsToProtocol( + auto Conformance = TypeChecker::conformsToProtocol( contextualType, DLC, CS.DC, ConformanceCheckFlags::InExpression); if (!Conformance) { diagnose(E->getStartLoc(), diag::type_is_not_dictionary, contextualType) diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 1403197f0237b..32b15bfa4afab 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -577,8 +577,8 @@ namespace { // the literal. if (otherArgTy && otherArgTy->getAnyNominal()) { if (otherArgTy->isEqual(paramTy) && - tc.conformsToProtocol(otherArgTy, literalProto, CS.DC, - ConformanceCheckFlags::InExpression)) + TypeChecker::conformsToProtocol(otherArgTy, literalProto, CS.DC, + ConformanceCheckFlags::InExpression)) return true; } else if (Type defaultType = tc.getDefaultType(literalProto, CS.DC)) { // If there is a default type for the literal protocol, check whether diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp index d0e57049170d3..9ebd37f0ba150 100644 --- a/lib/Sema/CSRanking.cpp +++ b/lib/Sema/CSRanking.cpp @@ -249,7 +249,7 @@ computeSelfTypeRelationship(TypeChecker &tc, DeclContext *dc, ValueDecl *decl1, // If the model type does not conform to the protocol, the bases are // unrelated. - auto conformance = tc.conformsToProtocol( + auto conformance = TypeChecker::conformsToProtocol( modelTy, proto, dc, (ConformanceCheckFlags::InExpression| ConformanceCheckFlags::SkipConditionalRequirements)); diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index ee62373280539..c1d18a3a30c9b 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -3329,7 +3329,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint( case ConstraintKind::LiteralConformsTo: { // Check whether this type conforms to the protocol. if (auto conformance = - TC.conformsToProtocol( + TypeChecker::conformsToProtocol( type, protocol, DC, (ConformanceCheckFlags::InExpression| ConformanceCheckFlags::SkipConditionalRequirements))) { diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index e0553b48401b8..9ff2b5f94edfd 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -1671,11 +1671,11 @@ void ConstraintSystem::ArgumentInfoCollector::minimizeLiteralProtocols() { const auto &candidate = candidates[i]; auto first = - CS.TC.conformsToProtocol(candidate.second, candidates[result].first, - CS.DC, ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(candidate.second, candidates[result].first, + CS.DC, ConformanceCheckFlags::InExpression); auto second = - CS.TC.conformsToProtocol(candidates[result].second, candidate.first, - CS.DC, ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(candidates[result].second, candidate.first, + CS.DC, ConformanceCheckFlags::InExpression); if ((first && second) || (!first && !second)) return; @@ -1878,8 +1878,8 @@ void ConstraintSystem::sortDesignatedTypes( ++nextType; break; } else if (auto *protoDecl = dyn_cast(nominalTypes[i])) { - if (TC.conformsToProtocol(argType, protoDecl, DC, - ConformanceCheckFlags::InExpression)) { + if (TypeChecker::conformsToProtocol(argType, protoDecl, DC, + ConformanceCheckFlags::InExpression)) { std::swap(nominalTypes[nextType], nominalTypes[i]); ++nextType; break; diff --git a/lib/Sema/CalleeCandidateInfo.cpp b/lib/Sema/CalleeCandidateInfo.cpp index 6628314c00b96..b74beb9366fab 100644 --- a/lib/Sema/CalleeCandidateInfo.cpp +++ b/lib/Sema/CalleeCandidateInfo.cpp @@ -1059,8 +1059,8 @@ bool CalleeCandidateInfo::diagnoseGenericParameterErrors(Expr *badArgExpr) { // FIXME: Add specific error for not subclass, if the archetype has a superclass? for (auto proto : paramArchetype->getConformsTo()) { - if (!CS.TC.conformsToProtocol(substitution, proto, CS.DC, - ConformanceCheckFlags::InExpression)) { + if (!TypeChecker::conformsToProtocol(substitution, proto, CS.DC, + ConformanceCheckFlags::InExpression)) { if (substitution->isEqual(argType)) { CS.TC.diagnose(badArgExpr->getLoc(), diag::cannot_convert_argument_value_protocol, diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp index 438cbcceb8844..43402828d9512 100644 --- a/lib/Sema/DerivedConformanceCodable.cpp +++ b/lib/Sema/DerivedConformanceCodable.cpp @@ -72,25 +72,23 @@ enum CodableConformanceType { /// Returns whether the given type conforms to the given {En,De}codable /// protocol. /// -/// \param tc The typechecker to use in validating {En,De}codable conformance. -/// /// \param context The \c DeclContext the var declarations belong to. /// /// \param target The \c Type to validate. /// /// \param proto The \c ProtocolDecl to check conformance to. -static CodableConformanceType typeConformsToCodable(TypeChecker &tc, - DeclContext *context, +static CodableConformanceType typeConformsToCodable(DeclContext *context, Type target, bool isIUO, ProtocolDecl *proto) { target = context->mapTypeIntoContext(target); if (isIUO) - return typeConformsToCodable(tc, context, target->getOptionalObjectType(), + return typeConformsToCodable(context, target->getOptionalObjectType(), false, proto); - return tc.conformsToProtocol(target, proto, context, None) ? Conforms - : DoesNotConform; + return (TypeChecker::conformsToProtocol(target, proto, context, None) + ? Conforms + : DoesNotConform); } /// Returns whether the given variable conforms to the given {En,De}codable @@ -131,7 +129,7 @@ static CodableConformanceType varConformsToCodable(TypeChecker &tc, bool isIUO = varDecl->getAttrs().hasAttribute(); - return typeConformsToCodable(tc, context, varDecl->getValueInterfaceType(), + return typeConformsToCodable(context, varDecl->getValueInterfaceType(), isIUO, proto); } @@ -287,9 +285,9 @@ static CodingKeysValidity hasValidCodingKeysEnum(DerivedConformance &derived) { // Ensure that the type we found conforms to the CodingKey protocol. auto *codingKeyProto = C.getProtocol(KnownProtocolKind::CodingKey); - if (!tc.conformsToProtocol(codingKeysType, codingKeyProto, - derived.getConformanceContext(), - None)) { + if (!TypeChecker::conformsToProtocol(codingKeysType, codingKeyProto, + derived.getConformanceContext(), + None)) { // If CodingKeys is a typealias which doesn't point to a valid nominal type, // codingKeysTypeDecl will be nullptr here. In that case, we need to warn on // the location of the usage, since there isn't an underlying type to @@ -1082,7 +1080,8 @@ static bool canSynthesize(DerivedConformance &derived, ValueDecl *requirement) { if (auto *superclassDecl = classDecl->getSuperclassDecl()) { DeclName memberName; auto superType = superclassDecl->getDeclaredInterfaceType(); - if (tc.conformsToProtocol(superType, proto, superclassDecl, None)) { + if (TypeChecker::conformsToProtocol(superType, proto, superclassDecl, + None)) { // super.init(from:) must be accessible. memberName = cast(requirement)->getFullName(); } else { @@ -1097,8 +1096,8 @@ static bool canSynthesize(DerivedConformance &derived, ValueDecl *requirement) { if (result.empty()) { // No super initializer for us to call. - tc.diagnose(superclassDecl, diag::decodable_no_super_init_here, - requirement->getFullName(), memberName); + superclassDecl->diagnose(diag::decodable_no_super_init_here, + requirement->getFullName(), memberName); return false; } else if (result.size() > 1) { // There are multiple results for this lookup. We'll end up producing a @@ -1111,22 +1110,21 @@ static bool canSynthesize(DerivedConformance &derived, ValueDecl *requirement) { auto conformanceDC = derived.getConformanceContext(); if (!initializer->isDesignatedInit()) { // We must call a superclass's designated initializer. - tc.diagnose(initializer, - diag::decodable_super_init_not_designated_here, - requirement->getFullName(), memberName); + initializer->diagnose(diag::decodable_super_init_not_designated_here, + requirement->getFullName(), memberName); return false; } else if (!initializer->isAccessibleFrom(conformanceDC)) { // Cannot call an inaccessible method. auto accessScope = initializer->getFormalAccessScope(conformanceDC); - tc.diagnose(initializer, diag::decodable_inaccessible_super_init_here, - requirement->getFullName(), memberName, - accessScope.accessLevelForDiagnostics()); + initializer->diagnose(diag::decodable_inaccessible_super_init_here, + requirement->getFullName(), memberName, + accessScope.accessLevelForDiagnostics()); return false; } else if (initializer->getFailability() != OTK_None) { // We can't call super.init() if it's failable, since init(from:) // isn't failable. - tc.diagnose(initializer, diag::decodable_super_init_is_failable_here, - requirement->getFullName(), memberName); + initializer->diagnose(diag::decodable_super_init_is_failable_here, + requirement->getFullName(), memberName); return false; } } diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp index 56aa16303a8ca..bffa7948a359e 100644 --- a/lib/Sema/DerivedConformanceEquatableHashable.cpp +++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp @@ -1082,18 +1082,19 @@ static ValueDecl *deriveHashable_hashValue(DerivedConformance &derived) { // We can't form a Hashable conformance if Int isn't Hashable or // ExpressibleByIntegerLiteral. - if (!tc.conformsToProtocol(intType, - C.getProtocol(KnownProtocolKind::Hashable), - parentDC, None)) { - tc.diagnose(derived.ConformanceDecl, diag::broken_int_hashable_conformance); + if (!TypeChecker::conformsToProtocol(intType, + C.getProtocol(KnownProtocolKind::Hashable), + parentDC, None)) { + derived.ConformanceDecl->diagnose(diag::broken_int_hashable_conformance); return nullptr; } ProtocolDecl *intLiteralProto = C.getProtocol(KnownProtocolKind::ExpressibleByIntegerLiteral); - if (!tc.conformsToProtocol(intType, intLiteralProto, parentDC, None)) { - tc.diagnose(derived.ConformanceDecl, - diag::broken_int_integer_literal_convertible_conformance); + if (!TypeChecker::conformsToProtocol(intType, intLiteralProto, + parentDC, None)) { + derived.ConformanceDecl->diagnose( + diag::broken_int_integer_literal_convertible_conformance); return nullptr; } diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp index a97d95918002e..25f205b5df0f4 100644 --- a/lib/Sema/DerivedConformanceRawRepresentable.cpp +++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp @@ -421,7 +421,8 @@ deriveRawRepresentable_init(DerivedConformance &derived) { auto equatableProto = tc.getProtocol(enumDecl->getLoc(), KnownProtocolKind::Equatable); assert(equatableProto); - assert(tc.conformsToProtocol(rawType, equatableProto, enumDecl, None)); + assert(TypeChecker::conformsToProtocol(rawType, equatableProto, + enumDecl, None)); (void)equatableProto; (void)rawType; @@ -489,7 +490,8 @@ static bool canSynthesizeRawRepresentable(DerivedConformance &derived) { if (!equatableProto) return false; - if (!tc.conformsToProtocol(rawType, equatableProto, enumDecl, None)) + if (!TypeChecker::conformsToProtocol(rawType, equatableProto, + enumDecl, None)) return false; // There must be enum elements. diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp index 5b66439ee4755..fd470139dca76 100644 --- a/lib/Sema/DerivedConformances.cpp +++ b/lib/Sema/DerivedConformances.cpp @@ -152,7 +152,7 @@ ValueDecl *DerivedConformance::getDerivableRequirement(TypeChecker &tc, auto proto = ctx.getProtocol(kind); if (!proto) return nullptr; - if (auto conformance = tc.conformsToProtocol( + if (auto conformance = TypeChecker::conformsToProtocol( nominal->getDeclaredInterfaceType(), proto, nominal, ConformanceCheckFlags::SkipConditionalRequirements)) { auto DC = conformance->getConcrete()->getDeclContext(); diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 1723735d4f8c9..ac6f128c5170b 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -897,8 +897,8 @@ bool swift::isValidDynamicCallableMethod(FuncDecl *decl, DeclContext *DC, if (!hasKeywordArguments) { auto arrayLitProto = TC.Context.getProtocol(KnownProtocolKind::ExpressibleByArrayLiteral); - return TC.conformsToProtocol(argType, arrayLitProto, DC, - ConformanceCheckOptions()).hasValue(); + return TypeChecker::conformsToProtocol(argType, arrayLitProto, DC, + ConformanceCheckOptions()).hasValue(); } // If keyword arguments, check that argument type conforms to // `ExpressibleByDictionaryLiteral` and that the `Key` associated type @@ -907,15 +907,15 @@ bool swift::isValidDynamicCallableMethod(FuncDecl *decl, DeclContext *DC, TC.Context.getProtocol(KnownProtocolKind::ExpressibleByStringLiteral); auto dictLitProto = TC.Context.getProtocol(KnownProtocolKind::ExpressibleByDictionaryLiteral); - auto dictConf = TC.conformsToProtocol(argType, dictLitProto, DC, - ConformanceCheckOptions()); + auto dictConf = TypeChecker::conformsToProtocol(argType, dictLitProto, DC, + ConformanceCheckOptions()); if (!dictConf) return false; auto lookup = dictLitProto->lookupDirect(TC.Context.Id_Key); auto keyAssocType = cast(lookup[0])->getDeclaredInterfaceType(); auto keyType = dictConf.getValue().getAssociatedType(argType, keyAssocType); - return TC.conformsToProtocol(keyType, stringLitProtocol, DC, - ConformanceCheckOptions()).hasValue(); + return TypeChecker::conformsToProtocol(keyType, stringLitProtocol, DC, + ConformanceCheckOptions()).hasValue(); } /// Returns true if the given nominal type has a valid implementation of a @@ -1004,8 +1004,8 @@ bool swift::isValidStringDynamicMemberLookup(SubscriptDecl *decl, TC.Context.getProtocol(KnownProtocolKind::ExpressibleByStringLiteral); // If this is `subscript(dynamicMember: String*)` - return bool(TC.conformsToProtocol(paramType, stringLitProto, DC, - ConformanceCheckOptions())); + return bool(TypeChecker::conformsToProtocol(paramType, stringLitProto, DC, + ConformanceCheckOptions())); } bool swift::isValidKeyPathDynamicMemberLookup(SubscriptDecl *decl, @@ -1490,8 +1490,9 @@ void AttributeChecker::checkApplicationMainAttribute(DeclAttribute *attr, } if (!ApplicationDelegateProto || - !TC.conformsToProtocol(CD->getDeclaredType(), ApplicationDelegateProto, - CD, None)) { + !TypeChecker::conformsToProtocol(CD->getDeclaredType(), + ApplicationDelegateProto, + CD, None)) { TC.diagnose(attr->getLocation(), diag::attr_ApplicationMain_not_ApplicationDelegate, applicationMainKind); diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index fc67ed345b057..85b279332122d 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -2627,10 +2627,10 @@ static bool isIntegerOrFloatingPointType(Type ty, DeclContext *DC, if (!integerType || !floatingType) return false; return - TC.conformsToProtocol(ty, integerType, DC, - ConformanceCheckFlags::InExpression) || - TC.conformsToProtocol(ty, floatingType, DC, - ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(ty, integerType, DC, + ConformanceCheckFlags::InExpression) || + TypeChecker::conformsToProtocol(ty, floatingType, DC, + ConformanceCheckFlags::InExpression); } diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 07f78f97e0bba..413872023e728 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -1993,7 +1993,7 @@ Expr *PreCheckExpression::simplifyTypeConstructionWithLiteralArg(Expr *E) { options |= ConformanceCheckFlags::InExpression; options |= ConformanceCheckFlags::SkipConditionalRequirements; - auto result = TC.conformsToProtocol(type, protocol, DC, options); + auto result = TypeChecker::conformsToProtocol(type, protocol, DC, options); if (!result || !result->isConcrete()) return nullptr; diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 35e39b60c2e7f..0cf3c05f11b74 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1488,7 +1488,8 @@ static void checkEnumRawValues(TypeChecker &TC, EnumDecl *ED) { // primitive literal protocols. auto conformsToProtocol = [&](KnownProtocolKind protoKind) { ProtocolDecl *proto = TC.getProtocol(ED->getLoc(), protoKind); - return TC.conformsToProtocol(rawTy, proto, ED->getDeclContext(), None); + return TypeChecker::conformsToProtocol(rawTy, proto, + ED->getDeclContext(), None); }; static auto otherLiteralProtocolKinds = { @@ -4486,7 +4487,7 @@ static void finalizeType(TypeChecker &TC, NominalTypeDecl *nominal) { TC.requestSuperclassLayout(CD); auto forceConformance = [&](ProtocolDecl *protocol) { - if (auto ref = TC.conformsToProtocol( + if (auto ref = TypeChecker::conformsToProtocol( CD->getDeclaredInterfaceType(), protocol, CD, ConformanceCheckFlags::SkipConditionalRequirements, SourceLoc())) { @@ -4949,10 +4950,10 @@ static void diagnoseClassWithoutInitializers(TypeChecker &tc, ASTContext &C = tc.Context; auto *decodableProto = C.getProtocol(KnownProtocolKind::Decodable); auto superclassType = superclassDecl->getDeclaredInterfaceType(); - if (auto ref = tc.conformsToProtocol(superclassType, decodableProto, - superclassDecl, - ConformanceCheckOptions(), - SourceLoc())) { + if (auto ref = TypeChecker::conformsToProtocol(superclassType, decodableProto, + superclassDecl, + ConformanceCheckOptions(), + SourceLoc())) { // super conforms to Decodable, so we've failed to inherit init(from:). // Let's suggest overriding it here. // diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp index 9b87eee3c62ca..d849f289d7bde 100644 --- a/lib/Sema/TypeCheckNameLookup.cpp +++ b/lib/Sema/TypeCheckNameLookup.cpp @@ -231,11 +231,9 @@ namespace { // Dig out the protocol conformance. auto *foundProto = cast(foundDC); - auto resolver = DC->getASTContext().getLazyResolver(); - assert(resolver && "Need an active resolver"); - auto &tc = *static_cast(resolver); - auto conformance = tc.conformsToProtocol(conformingType, foundProto, DC, - conformanceOptions); + auto conformance = TypeChecker::conformsToProtocol(conformingType, + foundProto, DC, + conformanceOptions); if (!conformance) { // If there's no conformance, we have an existential // and we found a member from one of the protocols, and diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index c084baeaa9d25..2e7ab575646bd 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1718,7 +1718,7 @@ checkIndividualConformance(NormalProtocolConformance *conformance, // Check that T conforms to all inherited protocols. for (auto InheritedProto : Proto->getInheritedProtocols()) { auto InheritedConformance = - TC.conformsToProtocol( + TypeChecker::conformsToProtocol( T, InheritedProto, DC, ConformanceCheckFlags::SkipConditionalRequirements, ComplainLoc); @@ -2932,7 +2932,8 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) { // a member that could in turn satisfy *this* requirement. auto derivableProto = cast(derivable->getDeclContext()); if (auto conformance = - TC.conformsToProtocol(Adoptee, derivableProto, DC, None)) { + TypeChecker::conformsToProtocol(Adoptee, derivableProto, + DC, None)) { if (conformance->isConcrete()) (void)conformance->getConcrete()->getWitnessDecl(derivable, &TC); } @@ -3313,7 +3314,7 @@ CheckTypeWitnessResult swift::checkTypeWitness(TypeChecker &tc, DeclContext *dc, // Check protocol conformances. for (auto reqProto : genericSig->getConformsTo(depTy)) { - if (!tc.conformsToProtocol( + if (!TypeChecker::conformsToProtocol( contextType, reqProto, dc, ConformanceCheckFlags::SkipConditionalRequirements)) return CheckTypeWitnessResult(reqProto->getDeclaredType()); diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp index 7bf44b6ff2166..8595602fddf88 100644 --- a/lib/Sema/TypeCheckProtocolInference.cpp +++ b/lib/Sema/TypeCheckProtocolInference.cpp @@ -970,7 +970,7 @@ Type AssociatedTypeInference::substCurrentTypeWitnesses(Type type) { // If that failed, check whether it's because of the conformance we're // evaluating. auto localConformance - = tc.conformsToProtocol( + = TypeChecker::conformsToProtocol( baseTy, assocType->getProtocol(), dc, ConformanceCheckFlags::SkipConditionalRequirements); if (!localConformance || localConformance->isAbstract() || diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index a07157ffa36b9..1cdfc4fc54083 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -739,9 +739,9 @@ class StmtChecker : public StmtVisitor { { Type sequenceType = sequence->getType(); auto conformance = - TC.conformsToProtocol(sequenceType, sequenceProto, DC, - ConformanceCheckFlags::InExpression, - sequence->getLoc()); + TypeChecker::conformsToProtocol(sequenceType, sequenceProto, DC, + ConformanceCheckFlags::InExpression, + sequence->getLoc()); if (!conformance) return nullptr; @@ -789,9 +789,9 @@ class StmtChecker : public StmtVisitor { // FIXME: Would like to customize the diagnostic emitted in // conformsToProtocol(). auto genConformance = - TC.conformsToProtocol(generatorTy, generatorProto, DC, - ConformanceCheckFlags::InExpression, - sequence->getLoc()); + TypeChecker::conformsToProtocol(generatorTy, generatorProto, DC, + ConformanceCheckFlags::InExpression, + sequence->getLoc()); if (!genConformance) return nullptr; From 823ba0bb7352732a02395c49390f1fcfb6322205 Mon Sep 17 00:00:00 2001 From: Parker Schuh Date: Thu, 28 Mar 2019 11:14:18 -0700 Subject: [PATCH 101/112] Convert ObjectLiteralExpr to not use tc.callWitness() or generate a SemanticExpr. For reference, all other literal types except dictionaries and string interpolation have been converted over to this form. --- include/swift/AST/Expr.h | 10 ++++++ lib/AST/ASTDumper.cpp | 2 ++ lib/SILGen/SILGenExpr.cpp | 9 ++++- lib/Sema/CSApply.cpp | 29 ++++------------ lib/Sema/MiscDiagnostics.cpp | 4 +++ test/SILGen/literals.swift | 65 ++++++++++++++++++++++++++++++++++++ 6 files changed, 95 insertions(+), 24 deletions(-) diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index e6af2df8196bf..7af6c2080b537 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -1135,6 +1135,7 @@ class ObjectLiteralExpr final Expr *Arg; Expr *SemanticExpr; SourceLoc PoundLoc; + ConcreteDeclRef Initializer; ObjectLiteralExpr(SourceLoc PoundLoc, LiteralKind LitKind, Expr *Arg, @@ -1195,6 +1196,15 @@ class ObjectLiteralExpr final StringRef getLiteralKindPlainName() const; + /// Retrieve the initializer that will be used to construct the 'object' + /// literal from the result of the initializer. + ConcreteDeclRef getInitializer() const { return Initializer; } + + /// Set the initializer that will be used to construct the 'object' literal. + void setInitializer(ConcreteDeclRef initializer) { + Initializer = initializer; + } + static bool classof(const Expr *E) { return E->getKind() == ExprKind::ObjectLiteral; } diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 2a205bcd84592..e6844632658fe 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -1967,6 +1967,8 @@ class PrintExpr : public ExprVisitor { void visitObjectLiteralExpr(ObjectLiteralExpr *E) { printCommon(E, "object_literal") << " kind='" << E->getLiteralKindPlainName() << "'"; + PrintWithColorRAII(OS, LiteralValueColor) << " initializer="; + E->getInitializer().dump(PrintWithColorRAII(OS, LiteralValueColor).getOS()); printArgumentLabels(E->getArgumentLabels()); OS << "\n"; printRec(E->getArg()); diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index e1d02a526018d..7a57c88145ffa 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -2346,7 +2346,14 @@ visitInterpolatedStringLiteralExpr(InterpolatedStringLiteralExpr *E, RValue RValueEmitter:: visitObjectLiteralExpr(ObjectLiteralExpr *E, SGFContext C) { - return visit(E->getSemanticExpr(), C); + ConcreteDeclRef init = E->getInitializer(); + auto *decl = cast(init.getDecl()); + AnyFunctionType *fnTy = decl->getMethodInterfaceType() + .subst(init.getSubstitutions()) + ->getAs(); + PreparedArguments args(fnTy->getParams(), E->getArg()); + return SGF.emitApplyAllocatingInitializer(SILLocation(E), init, + std::move(args), E->getType(), C); } RValue RValueEmitter:: diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 912e24b11d170..6ff140658bd53 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -2211,7 +2211,6 @@ namespace { if (cs.getType(expr) && !cs.getType(expr)->hasTypeVariable()) return expr; - auto &ctx = cs.getASTContext(); auto &tc = cs.getTypeChecker(); // Figure out the type we're converting to. @@ -2236,30 +2235,14 @@ namespace { ConformanceCheckFlags::InExpression); assert(conformance && "object literal type conforms to protocol"); - Expr *base = TypeExpr::createImplicitHack(expr->getLoc(), conformingType, - ctx); - cs.cacheExprTypes(base); - - SmallVector args; - if (!isa(expr->getArg())) - return nullptr; - auto tupleArg = cast(expr->getArg()); - for (auto elt : tupleArg->getElements()) { - cs.setExprTypes(elt); - args.push_back(elt); - } DeclName constrName(tc.getObjectLiteralConstructorName(expr)); - cs.cacheExprTypes(base); - cs.setExprTypes(base); - - Expr *semanticExpr = tc.callWitness(base, dc, proto, *conformance, - constrName, args, - diag::object_literal_broken_proto); - if (semanticExpr) - cs.cacheExprTypes(semanticExpr); - - expr->setSemanticExpr(semanticExpr); + ConcreteDeclRef witness = + conformance->getWitnessByName(conformingType->getRValueType(), + constrName); + if (!witness || !isa(witness.getDecl())) + return nullptr; + expr->setInitializer(witness); return expr; } diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 9d6361bcee2cc..95b6bc739e9a7 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -124,6 +124,10 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E, if (isa(Base)) checkUseOfMetaTypeName(Base); + if (auto *OLE = dyn_cast(E)) { + CallArgs.insert(OLE->getArg()); + } + if (auto *SE = dyn_cast(E)) CallArgs.insert(SE->getIndex()); diff --git a/test/SILGen/literals.swift b/test/SILGen/literals.swift index 47471cdde1d9d..722e70ff5aa14 100644 --- a/test/SILGen/literals.swift +++ b/test/SILGen/literals.swift @@ -255,3 +255,68 @@ func makeBasic() -> T { return T() } func throwingElement() throws -> [T] { return try [makeBasic(), makeThrowing()] } + +struct Color: _ExpressibleByColorLiteral { + init(_colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float) {} +} + +// CHECK-LABEL: sil hidden [ossa] @$s8literals16makeColorLiteralAA0C0VyF : $@convention(thin) () -> Color { +// CHECK: [[COLOR_METATYPE:%.*]] = metatype $@thin Color.Type +// CHECK: [[VALUE:%.*]] = float_literal $Builtin.FPIEEE80, 0x3FFFADD2F1A9FBE76C8B +// CHECK: [[METATYPE:%.*]] = metatype $@thin Float.Type +// CHECK: [[FN:%.*]] = function_ref @$sSf20_builtinFloatLiteralSfBf80__tcfC +// CHECK: [[R:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.FPIEEE80, @thin Float.Type) -> Float + +// CHECK: [[VALUE:%.*]] = float_literal $Builtin.FPIEEE80, 0xBFFB978D4FDF3B645A1D +// CHECK: [[METATYPE:%.*]] = metatype $@thin Float.Type +// CHECK: [[FN:%.*]] = function_ref @$sSf20_builtinFloatLiteralSfBf80__tcfC +// CHECK: [[G:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.FPIEEE80, @thin Float.Type) -> Float + +// CHECK: [[VALUE:%.*]] = float_literal $Builtin.FPIEEE80, 0xBFF8C49BA5E353F7CED9 +// CHECK: [[METATYPE:%.*]] = metatype $@thin Float.Type +// CHECK: [[FN:%.*]] = function_ref @$sSf20_builtinFloatLiteralSfBf80__tcfC +// CHECK: [[B:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.FPIEEE80, @thin Float.Type) -> Float + +// CHECK: [[VALUE:%.*]] = float_literal $Builtin.FPIEEE80, 0x3FFF8000000000000000 +// CHECK: [[METATYPE:%.*]] = metatype $@thin Float.Type +// CHECK: [[FN:%.*]] = function_ref @$sSf20_builtinFloatLiteralSfBf80__tcfC +// CHECK: [[A:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.FPIEEE80, @thin Float.Type) -> Float + +// CHECK: [[FN:%.*]] = function_ref @$s8literals5ColorV16_colorLiteralRed5green4blue5alphaACSf_S3ftcfC : $@convention(method) (Float, Float, Float, Float, @thin Color.Type) -> Color +// CHECK: [[LIT:%.*]] = apply [[FN]]([[R]], [[G]], [[B]], [[A]], [[COLOR_METATYPE]]) : $@convention(method) (Float, Float, Float, Float, @thin Color.Type) -> Color +// CHECK: return [[LIT]] : $Color +func makeColorLiteral() -> Color { + return #colorLiteral(red: 1.358, green: -0.074, blue: -0.012, alpha: 1.0) +} + +struct Image: _ExpressibleByImageLiteral { + init(imageLiteralResourceName: String) {} +} + +func makeTmpString() -> String { return "" } + +// CHECK-LABEL: sil hidden [ossa] @$s8literals16makeImageLiteralAA0C0VyF : $@convention(thin) () -> Image +// CHECK: [[METATYPE:%.*]] = metatype $@thin Image.Type +// CHECK: [[FN:%.*]] = function_ref @$s8literals13makeTmpStringSSyF : $@convention(thin) () -> @owned String +// CHECK: [[STR:%.*]] = apply [[FN]]() : $@convention(thin) () -> @owned String +// CHECK: [[FN:%.*]] = function_ref @$s8literals5ImageV24imageLiteralResourceNameACSS_tcfC : $@convention(method) (@owned String, @thin Image.Type) -> Image +// CHECK: [[LIT:%.*]] = apply [[FN]]([[STR]], [[METATYPE]]) : $@convention(method) (@owned String, @thin Image.Type) -> Image +// CHECK: return [[LIT]] : $Image +func makeImageLiteral() -> Image { + return #imageLiteral(resourceName: makeTmpString()) +} + +struct FileReference: _ExpressibleByFileReferenceLiteral { + init(fileReferenceLiteralResourceName: String) {} +} + +// CHECK-LABEL: sil hidden [ossa] @$s8literals24makeFileReferenceLiteralAA0cD0VyF : $@convention(thin) () -> FileReference +// CHECK: [[METATYPE:%.*]] = metatype $@thin FileReference.Type +// CHECK: [[FN:%.*]] = function_ref @$s8literals13makeTmpStringSSyF : $@convention(thin) () -> @owned String +// CHECK: [[STR:%.*]] = apply [[FN]]() : $@convention(thin) () -> @owned String +// CHECK: [[FN:%.*]] = function_ref @$s8literals13FileReferenceV04fileC19LiteralResourceNameACSS_tcfC +// CHECK: [[LIT:%.*]] = apply [[FN]]([[STR]], [[METATYPE]]) : $@convention(method) (@owned String, @thin FileReference.Type) -> FileReference +// CHECK: return [[LIT]] : $FileReference +func makeFileReferenceLiteral() -> FileReference { + return #fileLiteral(resourceName: makeTmpString()) +} From 6e90172010d810b5a831b811a3deae884ff6d4de Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 11 Jun 2019 02:32:48 -0700 Subject: [PATCH 102/112] AST: Remove unnecessary fast path --- lib/AST/ProtocolConformance.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp index 13dd5944ec3c1..88d17346b4c3f 100644 --- a/lib/AST/ProtocolConformance.cpp +++ b/lib/AST/ProtocolConformance.cpp @@ -1120,11 +1120,6 @@ SpecializedProtocolConformance::getWitnessDeclRef( auto witnessMap = baseWitness.getSubstitutions(); auto combinedMap = witnessMap.subst(specializationMap); - - // Fast path if the substitutions didn't change. - if (combinedMap == baseWitness.getSubstitutions()) - return baseWitness; - return ConcreteDeclRef(witnessDecl, combinedMap); } From ae5a427193a42b9e7427d3f12453d3c03a9dcb12 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 11 Jun 2019 02:35:25 -0700 Subject: [PATCH 103/112] AST: Fix ProtocolConformance::getWitnessDeclRef() This method was only ever called with non-generic witnesses, because it assumed the substitutions stored in the witness would always be derived from the conforming type. There were two cases where this wasn't the case though: 1) If the witness is itself generic 2) The witness was defined in a protocol extension and the conforming type is a non-final class In all cases, the SubstitutionMap stored in a Witness always uses the 'synthetic environment'. In some cases, the 'synthetic environment' is the generic environment of the witness. But in 1) and 2) it was different. While 1) never occurred because we never used this method to look up witnesses for generic requirements, 2) could happen. --- lib/AST/ProtocolConformance.cpp | 19 +++++++++++++++++-- test/SILGen/literals.swift | 23 +++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp index 88d17346b4c3f..d17a89fb5355f 100644 --- a/lib/AST/ProtocolConformance.cpp +++ b/lib/AST/ProtocolConformance.cpp @@ -966,8 +966,23 @@ Witness SelfProtocolConformance::getWitness(ValueDecl *requirement, ConcreteDeclRef RootProtocolConformance::getWitnessDeclRef(ValueDecl *requirement, LazyResolver *resolver) const { - if (auto witness = getWitness(requirement, resolver)) - return witness.getDeclRef(); + if (auto witness = getWitness(requirement, resolver)) { + auto *witnessDecl = witness.getDecl(); + + // If the witness is generic, you have to call getWitness() and build + // your own substitutions in terms of the synthetic environment. + if (auto *witnessDC = dyn_cast(witnessDecl)) + assert(!witnessDC->isInnermostContextGeneric()); + + // If the witness is not generic, use type substitutions from the + // witness's parent. Don't use witness.getSubstitutions(), which + // are written in terms of the synthetic environment. + auto subs = + getType()->getContextSubstitutionMap(getDeclContext()->getParentModule(), + witnessDecl->getDeclContext()); + return ConcreteDeclRef(witness.getDecl(), subs); + } + return ConcreteDeclRef(); } diff --git a/test/SILGen/literals.swift b/test/SILGen/literals.swift index 722e70ff5aa14..df38a0e41bb29 100644 --- a/test/SILGen/literals.swift +++ b/test/SILGen/literals.swift @@ -320,3 +320,26 @@ struct FileReference: _ExpressibleByFileReferenceLiteral { func makeFileReferenceLiteral() -> FileReference { return #fileLiteral(resourceName: makeTmpString()) } + +class ReferenceColor { required init() {} } + +protocol Silly { + init() + init(_colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float) +} + +extension Silly { + init(_colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float) { + self.init() + } +} + +extension ReferenceColor : Silly, _ExpressibleByColorLiteral {} + +func makeColorLiteral() -> ReferenceColor { + return #colorLiteral(red: 1.358, green: -0.074, blue: -0.012, alpha: 1.0) +} + +// CHECK-LABEL: sil hidden [ossa] @$s8literals16makeColorLiteralAA09ReferenceC0CyxGylF : $@convention(thin) () -> @owned ReferenceColor +// CHECK: [[FN:%.*]] = function_ref @$s8literals5SillyPAAE16_colorLiteralRed5green4blue5alphaxSf_S3ftcfC : $@convention(method) <τ_0_0 where τ_0_0 : Silly> (Float, Float, Float, Float, @thick τ_0_0.Type) -> @out τ_0_0 +// CHECK: apply [[FN]]>( From f5ab62aa819531f05276f2897557c26f6d4bc8ca Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 11 Jun 2019 09:43:26 -0700 Subject: [PATCH 104/112] [SE-0258] Move "has lazy resolver" check later to handle merge-modules properly The merge-modules phase doesn't have an active type checker, so we were bailing out of property-wrapper queries before we had a chance to check the cache. Move the check later, to the points where we actually need a type checker. Fixes SR-10844 / rdar://problem/51484958. --- lib/AST/Decl.cpp | 9 ------ lib/AST/TypeCheckRequests.cpp | 1 + lib/Sema/TypeCheckPropertyWrapper.cpp | 10 +++++-- .../Inputs/def_property_wrappers.swift | 29 +++++++++++++++++++ test/Serialization/property_wrappers.swift | 12 ++++++-- 5 files changed, 48 insertions(+), 13 deletions(-) diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index bf09b7ccd8f50..057f23df1b966 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -5444,9 +5444,6 @@ PropertyWrapperTypeInfo VarDecl::getAttachedPropertyWrapperTypeInfo() const { Type VarDecl::getAttachedPropertyWrapperType() const { auto &ctx = getASTContext(); - if (!ctx.getLazyResolver()) - return nullptr; - auto mutableThis = const_cast(this); return evaluateOrDefault(ctx.evaluator, AttachedPropertyWrapperTypeRequest{mutableThis}, @@ -5455,9 +5452,6 @@ Type VarDecl::getAttachedPropertyWrapperType() const { Type VarDecl::getPropertyWrapperBackingPropertyType() const { ASTContext &ctx = getASTContext(); - if (!ctx.getLazyResolver()) - return nullptr; - auto mutableThis = const_cast(this); return evaluateOrDefault( ctx.evaluator, PropertyWrapperBackingPropertyTypeRequest{mutableThis}, @@ -5467,9 +5461,6 @@ Type VarDecl::getPropertyWrapperBackingPropertyType() const { PropertyWrapperBackingPropertyInfo VarDecl::getPropertyWrapperBackingPropertyInfo() const { auto &ctx = getASTContext(); - if (!ctx.getLazyResolver()) - return PropertyWrapperBackingPropertyInfo(); - auto mutableThis = const_cast(this); return evaluateOrDefault( ctx.evaluator, diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 3cb6d2aa7d66b..756b897b4d741 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -648,6 +648,7 @@ void PropertyWrapperBackingPropertyTypeRequest::noteCycleStep( DiagnosticEngine &diags) const { std::get<0>(getStorage())->diagnose(diag::circular_reference_through); } + bool PropertyWrapperBackingPropertyInfoRequest::isCached() const { auto var = std::get<0>(getStorage()); return !var->getAttrs().isEmpty(); diff --git a/lib/Sema/TypeCheckPropertyWrapper.cpp b/lib/Sema/TypeCheckPropertyWrapper.cpp index a108fb8a05648..c4737ad51a1ef 100644 --- a/lib/Sema/TypeCheckPropertyWrapper.cpp +++ b/lib/Sema/TypeCheckPropertyWrapper.cpp @@ -371,12 +371,15 @@ AttachedPropertyWrapperTypeRequest::evaluate(Evaluator &evaluator, if (!customAttr) return Type(); + ASTContext &ctx = var->getASTContext(); + if (!ctx.getLazyResolver()) + return nullptr; + auto resolution = TypeResolution::forContextual(var->getDeclContext()); TypeResolutionOptions options(TypeResolverContext::PatternBindingDecl); options |= TypeResolutionFlags::AllowUnboundGenerics; - ASTContext &ctx = var->getASTContext(); auto &tc = *static_cast(ctx.getLazyResolver()); if (tc.validateType(customAttr->getTypeLoc(), resolution, options)) return ErrorType::get(ctx); @@ -409,10 +412,13 @@ PropertyWrapperBackingPropertyTypeRequest::evaluate( if (!binding) return Type(); + ASTContext &ctx = var->getASTContext(); + if (!ctx.getLazyResolver()) + return Type(); + // If there's an initializer of some sort, checking it will determine the // property wrapper type. unsigned index = binding->getPatternEntryIndexForVarDecl(var); - ASTContext &ctx = var->getASTContext(); TypeChecker &tc = *static_cast(ctx.getLazyResolver()); if (binding->isInitialized(index)) { tc.validateDecl(var); diff --git a/test/Serialization/Inputs/def_property_wrappers.swift b/test/Serialization/Inputs/def_property_wrappers.swift index aafddd6824125..cb9d32025e592 100644 --- a/test/Serialization/Inputs/def_property_wrappers.swift +++ b/test/Serialization/Inputs/def_property_wrappers.swift @@ -10,3 +10,32 @@ public struct SomeWrapper { public struct HasWrappers { @SomeWrapper public var x: Int = 17 } + +// SR-10844 +@_propertyWrapper +class A { + + private var _value: T + + var value: T { + get { _value } + set { _value = newValue } + } + + init(initialValue: T) { + _value = initialValue + } +} + +@_propertyWrapper +class B: A { + override var value: Double { + get { super.value } + set { super.value = newValue } + } +} + +class Holder { + // @A var b = 10.0 // ok + @B var b = 10.0 // crash in test target +} diff --git a/test/Serialization/property_wrappers.swift b/test/Serialization/property_wrappers.swift index a819d9df8dc14..18c488a03c806 100644 --- a/test/Serialization/property_wrappers.swift +++ b/test/Serialization/property_wrappers.swift @@ -1,8 +1,16 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_property_wrappers.swift +// RUN: %empty-directory(%t-scratch) +// RUN: %target-swift-frontend -emit-module -o %t-scratch/def_property_wrappers~partial.swiftmodule -primary-file %S/Inputs/def_property_wrappers.swift -module-name def_property_wrappers -enable-testing +// RUN: %target-swift-frontend -merge-modules -emit-module -parse-as-library -sil-merge-partial-modules -disable-diagnostic-passes -disable-sil-perf-optzns -enable-testing %t-scratch/def_property_wrappers~partial.swiftmodule -module-name def_property_wrappers -o %t/def_property_wrappers.swiftmodule // RUN: %target-swift-frontend -typecheck -I%t -verify %s -verify-ignore-unknown -import def_property_wrappers +@testable import def_property_wrappers + +// SR-10844 +func testSR10844() { + let holder = Holder() + holder.b = 100 +} func useWrappers(hd: HasWrappers) { // Access the original properties From 5e00f01ce49dd644ece8cfd3e012863492e0f91a Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 11 Jun 2019 10:01:53 -0700 Subject: [PATCH 105/112] [SE-0258] Ensure that we fully check the property type vs. wrapper's value type Various optimizations / shortcuts in type checking property wrappers meant that we weren't consistently verifying that a wrapped property type is identical to the type of the 'value' property of the wrapper. Do so. Fixes SR-10899 / rdar://problem/51588022. --- lib/Sema/CodeSynthesis.cpp | 25 +++++++++++++++++++++++-- test/decl/var/property_wrappers.swift | 10 ++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 7cb168c3b1bf0..ee8fcce40c782 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -1756,13 +1756,34 @@ PropertyWrapperBackingPropertyInfoRequest::evaluate(Evaluator &evaluator, auto dc = var->getDeclContext(); Type storageInterfaceType = wrapperType; - Type storageType = - var->getDeclContext()->mapTypeIntoContext(storageInterfaceType); + Type storageType = dc->mapTypeIntoContext(storageInterfaceType); if (!storageType) { storageType = ErrorType::get(ctx); isInvalid = true; } + // Make sure that the property type matches the value of the + // wrapper type. + if (!storageType->hasError()) { + Type expectedPropertyType = + storageType->getTypeOfMember( + dc->getParentModule(), + wrapperInfo.valueVar, + wrapperInfo.valueVar->getValueInterfaceType()); + Type propertyType = + dc->mapTypeIntoContext(var->getValueInterfaceType()); + if (!expectedPropertyType->hasError() && + !propertyType->hasError() && + !propertyType->isEqual(expectedPropertyType)) { + var->diagnose(diag::property_wrapper_incompatible_property, + propertyType, wrapperType); + if (auto nominalWrapper = wrapperType->getAnyNominal()) { + nominalWrapper->diagnose(diag::property_wrapper_declared_here, + nominalWrapper->getFullName()); + } + } + } + // Create the backing storage property and note it in the cache. VarDecl *backingVar = new (ctx) VarDecl(/*IsStatic=*/var->isStatic(), VarDecl::Specifier::Var, diff --git a/test/decl/var/property_wrappers.swift b/test/decl/var/property_wrappers.swift index 4982942ee3cc4..0142fc1fba2b3 100644 --- a/test/decl/var/property_wrappers.swift +++ b/test/decl/var/property_wrappers.swift @@ -758,3 +758,13 @@ struct UsesWrapperRequiringP { // expected-error@-2{{expected declaration}} // expected-error@-3{{type annotation missing in pattern}} } + +// SR-10899 / rdar://problem/51588022 +@_propertyWrapper +struct SR_10899_Wrapper { // expected-note{{property wrapper type 'SR_10899_Wrapper' declared here}} + var value: String { "hi" } +} + +struct SR_10899_Usage { + @SR_10899_Wrapper var thing: Bool // expected-error{{property type 'Bool' does not match that of the 'value' property of its wrapper type 'SR_10899_Wrapper'}} +} From 2b190648c089f0407960310ca8e7e929e76875b7 Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Tue, 11 Jun 2019 10:53:03 -0700 Subject: [PATCH 106/112] SourceKit/Indentation: avoid indenting the end of subscript expressions in call chain. rdar://50591281 --- lib/IDE/Formatting.cpp | 3 ++- test/SourceKit/CodeFormat/indent-closure.swift | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/IDE/Formatting.cpp b/lib/IDE/Formatting.cpp index 0cac1f0691c8e..cfb336bb684db 100644 --- a/lib/IDE/Formatting.cpp +++ b/lib/IDE/Formatting.cpp @@ -489,7 +489,8 @@ class FormatContext { // }.map { <--- No indentation here. // ... // } - if (AtExprEnd && AtCursorExpr && isa(AtExprEnd)) { + if (AtExprEnd && AtCursorExpr && + (isa(AtExprEnd) || isa(AtExprEnd))) { if (auto *UDE = dyn_cast(AtCursorExpr)) { if (auto *Base = UDE->getBase()) { if (exprEndAtLine(Base, Line)) diff --git a/test/SourceKit/CodeFormat/indent-closure.swift b/test/SourceKit/CodeFormat/indent-closure.swift index b75a3e3df4b7e..b24b0571e9d37 100644 --- a/test/SourceKit/CodeFormat/indent-closure.swift +++ b/test/SourceKit/CodeFormat/indent-closure.swift @@ -62,6 +62,11 @@ func foo9(input: [Int]){ } } +func foo10() { + Something() [ + ].whatever +} + // 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 @@ -89,6 +94,9 @@ func foo9(input: [Int]){ // RUN: %sourcekitd-test -req=format -line=62 -length=1 %s >>%t.response // RUN: %sourcekitd-test -req=format -line=63 -length=1 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=66 -length=1 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=67 -length=1 %s >>%t.response + // RUN: %FileCheck --strict-whitespace %s <%t.response // CHECK: key.sourcetext: " var abc = 1" @@ -125,3 +133,6 @@ func foo9(input: [Int]){ // CHECK: key.sourcetext: " return ele + 1" // CHECK: key.sourcetext: " }" // CHECK: key.sourcetext: "}" + +// CHECK: key.sourcetext: " Something() [" +// CHECK: key.sourcetext: " ].whatever" From bbd44a186f4f0182367d2a885b901104d263e192 Mon Sep 17 00:00:00 2001 From: Stephen Canon Date: Tue, 11 Jun 2019 14:36:43 -0400 Subject: [PATCH 107/112] Replace two #ifs with #if/#else in new integer random algorithm (#25352) Swift gets used on archs other than 32 and 64b Intel and ARM (e.g. IBM's systems); as written this would fail to compile there. --- stdlib/public/core/Random.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stdlib/public/core/Random.swift b/stdlib/public/core/Random.swift index bdbb95c407dd2..a1c27c0049fef 100644 --- a/stdlib/public/core/Random.swift +++ b/stdlib/public/core/Random.swift @@ -104,8 +104,7 @@ extension RandomNumberGenerator { } while random < range return random % upperBound -#endif -#if arch(x86_64) || arch(arm64) +#else var random: T = next() var m = random.multipliedFullWidth(by: upperBound) if m.low < upperBound { From 4bd5a1e4e1d0288b5a13746bc68a8855c6c9af86 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 11 Jun 2019 11:46:54 -0700 Subject: [PATCH 108/112] [Diagnostics] Clarify requirement failure source when it's anchored at assignment While trying to fetch owner type for generic requirement failures anchored at assignment expression, use assignment source as an anchor because that's where requirements come from - conversion from source type to destination. Resolves: rdar://problem/51587755 --- lib/Sema/CSDiagnostics.cpp | 14 +++++++++++--- test/Constraints/sr10906.swift | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 test/Constraints/sr10906.swift diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index a9b4e76c102ec..8ce2e332ea5db 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -111,9 +111,17 @@ Optional FailureDiagnostic::getChoiceFor(Expr *expr) const { } Type RequirementFailure::getOwnerType() const { - return getType(getRawAnchor()) - ->getInOutObjectType() - ->getMetatypeInstanceType(); + auto *anchor = getRawAnchor(); + + // If diagnostic is anchored at assignment expression + // it means that requirement failure happend while trying + // to convert source to destination, which means that + // owner type is actually not an assignment expression + // itself but its source. + if (auto *assignment = dyn_cast(anchor)) + anchor = assignment->getSrc(); + + return getType(anchor)->getInOutObjectType()->getMetatypeInstanceType(); } const GenericContext *RequirementFailure::getGenericContext() const { diff --git a/test/Constraints/sr10906.swift b/test/Constraints/sr10906.swift new file mode 100644 index 0000000000000..1903ca3ca4500 --- /dev/null +++ b/test/Constraints/sr10906.swift @@ -0,0 +1,24 @@ +// RUN: %target-typecheck-verify-swift + +protocol ViewDataSource: class { + func foo() -> [T] +} + +class View { + weak var delegate: ViewDataSource? +} + +final class ViewController { + let view = View() + init() { + view.delegate = self + // expected-error@-1 {{generic class 'ViewController' requires the types 'T' and 'String' be equivalent}} + } +} + +extension ViewController: ViewDataSource where T == String { +// expected-note@-1 {{requirement from conditional conformance of 'ViewController' to 'ViewDataSource'}} + func foo() -> [T] { + return [] + } +} From 3491fecc04e1f6ff22fc12d788c7b05d830089fe Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 11 Jun 2019 14:22:48 -0700 Subject: [PATCH 109/112] Revert "Sema: Go back to synthesizing hashValue on _StoredBridgedNSError conformers" This reverts commit 712927c4942a470447f381f31a01f33e0b9fc2c8. --- .../DerivedConformanceEquatableHashable.cpp | 29 ++----------------- stdlib/public/Darwin/Foundation/NSError.swift | 4 +++ 2 files changed, 7 insertions(+), 26 deletions(-) diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp index d9cf07e16328e..c51e48564e899 100644 --- a/lib/Sema/DerivedConformanceEquatableHashable.cpp +++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp @@ -1125,41 +1125,18 @@ deriveBodyHashable_hashValue(AbstractFunctionDecl *hashValueDecl, void *) { // return _hashValue(for: self) auto *hashFunc = C.getHashValueForDecl(); - if (!hashFunc->hasInterfaceType()) - C.getLazyResolver()->resolveDeclSignature(hashFunc); - - auto selfType = hashValueDecl->mapTypeIntoContext( - parentDC->getSelfInterfaceType()); - auto hashableProto = C.getProtocol(KnownProtocolKind::Hashable); - auto conformance = TypeChecker::conformsToProtocol(selfType, hashableProto, - parentDC, None); - auto subs = SubstitutionMap::get(hashFunc->getGenericSignature(), - ArrayRef(selfType), - ArrayRef(*conformance)); - ConcreteDeclRef hashRef(hashFunc, subs); - - auto hashExpr = new (C) DeclRefExpr(hashRef, DeclNameLoc(), + auto hashExpr = new (C) DeclRefExpr(hashFunc, DeclNameLoc(), /*implicit*/ true); - - Type intType = C.getIntDecl()->getDeclaredType(); - hashExpr->setType(FunctionType::get(AnyFunctionType::Param(selfType), - intType)); - auto selfDecl = hashValueDecl->getImplicitSelfDecl(); auto selfRef = new (C) DeclRefExpr(selfDecl, DeclNameLoc(), /*implicit*/ true); - selfRef->setType(selfType); - - auto callExpr = CallExpr::createImplicit(C, hashExpr, { selfRef }, { }); - callExpr->setType(intType); - callExpr->setThrows(false); - + auto callExpr = CallExpr::createImplicit(C, hashExpr, + { selfRef }, { C.Id_for }); auto returnStmt = new (C) ReturnStmt(SourceLoc(), callExpr); auto body = BraceStmt::create(C, SourceLoc(), {returnStmt}, SourceLoc(), /*implicit*/ true); hashValueDecl->setBody(body); - hashValueDecl->setBodyTypeCheckedIfPresent(); } /// Derive a 'hashValue' implementation. diff --git a/stdlib/public/Darwin/Foundation/NSError.swift b/stdlib/public/Darwin/Foundation/NSError.swift index 57a238566b6c4..996d2d2f3bf18 100644 --- a/stdlib/public/Darwin/Foundation/NSError.swift +++ b/stdlib/public/Darwin/Foundation/NSError.swift @@ -489,6 +489,10 @@ extension _BridgedStoredNSError { public func hash(into hasher: inout Hasher) { hasher.combine(_nsError) } + + @_alwaysEmitIntoClient public var hashValue: Int { + return _nsError.hashValue + } } /// Describes the code of an error. From 67fd1f23729772fede230f089a5a87f7023047fe Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 11 Jun 2019 14:26:04 -0700 Subject: [PATCH 110/112] Foundation: Manually define hashValue witnesses for CocoaError, URLError, POSIXError and MachError --- stdlib/public/Darwin/Foundation/NSError.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/stdlib/public/Darwin/Foundation/NSError.swift b/stdlib/public/Darwin/Foundation/NSError.swift index 996d2d2f3bf18..e844752f9e2d3 100644 --- a/stdlib/public/Darwin/Foundation/NSError.swift +++ b/stdlib/public/Darwin/Foundation/NSError.swift @@ -568,6 +568,10 @@ public struct CocoaError : _BridgedStoredNSError { public static var errorDomain: String { return NSCocoaErrorDomain } + public var hashValue: Int { + return _nsError.hashValue + } + /// The error code itself. public struct Code : RawRepresentable, Hashable, _ErrorCodeProtocol { public typealias _ErrorType = CocoaError @@ -1795,6 +1799,10 @@ public struct URLError : _BridgedStoredNSError { public static var errorDomain: String { return NSURLErrorDomain } + public var hashValue: Int { + return _nsError.hashValue + } + /// The error code itself. public struct Code : RawRepresentable, Hashable, _ErrorCodeProtocol { public typealias _ErrorType = URLError @@ -2451,6 +2459,10 @@ public struct POSIXError : _BridgedStoredNSError { public static var errorDomain: String { return NSPOSIXErrorDomain } + public var hashValue: Int { + return _nsError.hashValue + } + public typealias Code = POSIXErrorCode } @@ -2937,6 +2949,10 @@ public struct MachError : _BridgedStoredNSError { public static var errorDomain: String { return NSMachErrorDomain } + public var hashValue: Int { + return _nsError.hashValue + } + public typealias Code = MachErrorCode } From 528025432593c4a9472260c3e2d3728d6b5076d7 Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Tue, 11 Jun 2019 15:11:14 -0700 Subject: [PATCH 111/112] Sourcekit/Indentation: avoid indenting dot member access appearing after trailing closure --- lib/IDE/Formatting.cpp | 9 +++++++++ test/SourceKit/CodeFormat/indent-closure.swift | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/lib/IDE/Formatting.cpp b/lib/IDE/Formatting.cpp index cfb336bb684db..77b108a02f891 100644 --- a/lib/IDE/Formatting.cpp +++ b/lib/IDE/Formatting.cpp @@ -289,6 +289,15 @@ class FormatContext { isKeywordPossibleDeclStart(*TInfo.StartOfLineBeforeTarget) && TInfo.StartOfLineBeforeTarget->isKeyword()) return false; + // VStack { + // ... + // } + // .onAppear { <---- No indentation here. + if (TInfo.StartOfLineTarget->getKind() == tok::period && + TInfo.StartOfLineBeforeTarget->getKind() == tok::r_brace && + TInfo.StartOfLineBeforeTarget + 1 == TInfo.StartOfLineTarget) { + return false; + } } // Handle switch / case, indent unless at a case label. diff --git a/test/SourceKit/CodeFormat/indent-closure.swift b/test/SourceKit/CodeFormat/indent-closure.swift index b24b0571e9d37..72d285227d1ed 100644 --- a/test/SourceKit/CodeFormat/indent-closure.swift +++ b/test/SourceKit/CodeFormat/indent-closure.swift @@ -67,6 +67,13 @@ func foo10() { ].whatever } +func foo11() { + VStack { + } + .onAppear { + } +} + // 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 @@ -96,6 +103,7 @@ func foo10() { // RUN: %sourcekitd-test -req=format -line=66 -length=1 %s >>%t.response // RUN: %sourcekitd-test -req=format -line=67 -length=1 %s >>%t.response +// RUN: %sourcekitd-test -req=format -line=73 -length=1 %s >>%t.response // RUN: %FileCheck --strict-whitespace %s <%t.response @@ -136,3 +144,4 @@ func foo10() { // CHECK: key.sourcetext: " Something() [" // CHECK: key.sourcetext: " ].whatever" +// CHECK: key.sourcetext: " .onAppear {" From 52c50a78f6f7530fb9b73baceee37dfa21e255b6 Mon Sep 17 00:00:00 2001 From: Dan Zheng Date: Thu, 13 Jun 2019 13:28:30 -0700 Subject: [PATCH 112/112] Fix DifferentiationUnittest. - Remove deprecated `TARGET_SDKS ALL_POSIX_PLATFORMS`. - Specify DARWIN_INSTALL_NAME_DIR. --- stdlib/private/DifferentiationUnittest/CMakeLists.txt | 8 +++++--- ...ifetimeTracked.swift => DifferentiationUnittest.swift} | 0 stdlib/private/TensorFlowUnittest/CMakeLists.txt | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) rename stdlib/private/DifferentiationUnittest/{GenericLifetimeTracked.swift => DifferentiationUnittest.swift} (100%) diff --git a/stdlib/private/DifferentiationUnittest/CMakeLists.txt b/stdlib/private/DifferentiationUnittest/CMakeLists.txt index f3eba31b14da9..cb980eda599a9 100644 --- a/stdlib/private/DifferentiationUnittest/CMakeLists.txt +++ b/stdlib/private/DifferentiationUnittest/CMakeLists.txt @@ -1,5 +1,7 @@ add_swift_target_library(swiftDifferentiationUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB - GenericLifetimeTracked.swift + # This file should be listed first. Module name is inferred from the filename. + DifferentiationUnittest.swift + SWIFT_COMPILE_FLAGS - TARGET_SDKS ALL_POSIX_PLATFORMS - INSTALL_IN_COMPONENT stdlib-experimental) + INSTALL_IN_COMPONENT stdlib-experimental + DARWIN_INSTALL_NAME_DIR "${SWIFT_DARWIN_STDLIB_PRIVATE_INSTALL_NAME_DIR}") diff --git a/stdlib/private/DifferentiationUnittest/GenericLifetimeTracked.swift b/stdlib/private/DifferentiationUnittest/DifferentiationUnittest.swift similarity index 100% rename from stdlib/private/DifferentiationUnittest/GenericLifetimeTracked.swift rename to stdlib/private/DifferentiationUnittest/DifferentiationUnittest.swift diff --git a/stdlib/private/TensorFlowUnittest/CMakeLists.txt b/stdlib/private/TensorFlowUnittest/CMakeLists.txt index 50e6cd6ddeff6..73d3ee252e81d 100644 --- a/stdlib/private/TensorFlowUnittest/CMakeLists.txt +++ b/stdlib/private/TensorFlowUnittest/CMakeLists.txt @@ -1,6 +1,7 @@ find_package(TensorFlow REQUIRED) add_swift_target_library(swiftTensorFlowUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB + # This file should be listed first. Module name is inferred from the filename. TensorFlowUnittest.swift TensorFlowUnittestRemote.swift @@ -8,4 +9,5 @@ add_swift_target_library(swiftTensorFlowUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TY SWIFT_MODULE_DEPENDS_OSX Darwin SWIFT_MODULE_DEPENDS_LINUX Glibc PRIVATE_LINK_LIBRARIES "${TF_LIBRARIES}" - INSTALL_IN_COMPONENT stdlib-experimental) + INSTALL_IN_COMPONENT stdlib-experimental + DARWIN_INSTALL_NAME_DIR "${SWIFT_DARWIN_STDLIB_PRIVATE_INSTALL_NAME_DIR}")