Merge pull request #12121 from aschwaighofer/fix_dom_tree_array_specialization
Fix dominator tree update in array specialization
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 22fb3fb..8acdac1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -66,7 +66,11 @@
endif()
option(SWIFT_BUILD_PERF_TESTSUITE
- "Create targets for swift performance benchmarks."
+ "Create in-tree targets for building swift performance benchmarks."
+ FALSE)
+
+option(SWIFT_BUILD_EXTERNAL_PERF_TESTSUITE
+ "Create out-of-tree targets for building swift performance benchmarks."
FALSE)
option(SWIFT_INCLUDE_TESTS "Create targets for building/running tests." TRUE)
@@ -882,9 +886,16 @@
add_subdirectory(tools/swift-reflection-test)
endif()
-if(SWIFT_BUILD_PERF_TESTSUITE AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
- add_subdirectory(benchmark)
+if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
+ if(SWIFT_BUILD_PERF_TESTSUITE)
+ add_subdirectory(benchmark)
+ endif()
+ if(SWIFT_BUILD_EXTERNAL_PERF_TESTSUITE)
+ include(SwiftExternalBenchmarkBuild)
+ add_external_benchmark_suite()
+ endif()
endif()
+
if(SWIFT_INCLUDE_TESTS)
add_subdirectory(test)
add_subdirectory(unittests)
diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt
index 8012413..fe92ab2 100644
--- a/benchmark/CMakeLists.txt
+++ b/benchmark/CMakeLists.txt
@@ -125,9 +125,16 @@
single-source/XorLoop
)
-set(SWIFT_MULTISOURCE_BENCHES
+set(SWIFT_MULTISOURCE_SWIFT3_BENCHES
+ multi-source/PrimsSplit
)
+set(PrimsSplit_sources
+ multi-source/PrimsSplit/Prims.swift
+ multi-source/PrimsSplit/main.swift)
+
+set(SWIFT_MULTISOURCE_SWIFT4_BENCHES
+)
set(BENCH_DRIVER_LIBRARY_FLAGS)
if (SWIFT_RUNTIME_ENABLE_LEAK_CHECKER)
@@ -231,6 +238,7 @@
message("--")
message("-- Swift Benchmark Suite:")
+message("-- SWIFT_BENCHMARK_BUILT_STANDALONE = ${SWIFT_BENCHMARK_BUILT_STANDALONE}")
message("-- SWIFT_EXEC = ${SWIFT_EXEC}")
message("-- SWIFT_LIBRARY_PATH = ${SWIFT_LIBRARY_PATH}")
message("-- CLANG_EXEC = ${CLANG_EXEC}")
diff --git a/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake b/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
index 3a00b46..e56b583 100644
--- a/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
+++ b/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
@@ -73,6 +73,104 @@
endif()
endfunction()
+function(_construct_sources_for_multibench sources_out objfile_out)
+ cmake_parse_arguments(SOURCEJSONLIST "" "" "SOURCES" ${ARGN})
+
+ set(sources)
+ set(objfiles)
+
+ foreach(source ${SOURCEJSONLIST_SOURCES})
+ list(APPEND sources "${srcdir}/${source}")
+
+ get_filename_component(basename "${source}" NAME_WE)
+ set(objfile "${objdir}/${module_name}/${basename}.o")
+
+ string(CONCAT json "${json}"
+ " \"${srcdir}/${source}\": { \"object\": \"${objfile}\" },\n")
+
+ list(APPEND objfiles "${objfile}")
+ endforeach()
+ string(CONCAT json "${json}" "}")
+ file(WRITE "${objdir}/${module_name}/outputmap.json" ${json})
+ set(${sources_out} ${sources} PARENT_SCOPE)
+ set(${objfile_out} ${objfiles} PARENT_SCOPE)
+endfunction()
+
+# Regular whole-module-compilation: only a single object file is
+# generated.
+function (add_swift_multisource_wmo_benchmark_library objfile_out)
+ cmake_parse_arguments(BENCHLIB "" "MODULE_PATH;SOURCE_DIR;OBJECT_DIR" "SOURCES;LIBRARY_FLAGS;DEPENDS" ${ARGN})
+
+ precondition(BENCHLIB_MODULE_PATH)
+ precondition(BENCHLIB_SOURCE_DIR)
+ precondition(BENCHLIB_OBJECT_DIR)
+ precondition(BENCHLIB_SOURCES)
+
+ set(module_name_path "${BENCHLIB_MODULE_PATH}")
+ get_filename_component(module_name "${module_name_path}" NAME)
+ set(srcdir "${BENCHLIB_SOURCE_DIR}")
+ set(objdir "${BENCHLIB_OBJECT_DIR}")
+
+ set(objfile "${objdir}/${module_name}.o")
+
+ set(sources)
+ foreach(source ${BENCHLIB_SOURCES})
+ list(APPEND sources "${srcdir}/${source}")
+ endforeach()
+
+ add_custom_command(
+ OUTPUT "${objfile}"
+ DEPENDS
+ ${sources} ${BENCHLIB_DEPENDS}
+ COMMAND "${SWIFT_EXEC}"
+ ${BENCHLIB_LIBRARY_FLAGS}
+ "-parse-as-library"
+ "-emit-module" "-module-name" "${module_name}"
+ "-I" "${objdir}"
+ "-o" "${objfile}"
+ ${sources})
+
+ set(${objfile_out} "${objfile}" PARENT_SCOPE)
+endfunction()
+
+function(add_swift_multisource_nonwmo_benchmark_library objfiles_out)
+ cmake_parse_arguments(BENCHLIB "" "MODULE_PATH;SOURCE_DIR;OBJECT_DIR" "SOURCES;LIBRARY_FLAGS;DEPENDS" ${ARGN})
+
+ precondition(BENCHLIB_MODULE_PATH)
+ precondition(BENCHLIB_SOURCE_DIR)
+ precondition(BENCHLIB_OBJECT_DIR)
+ precondition(BENCHLIB_SOURCES)
+
+ set(module_name_path "${BENCHLIB_MODULE_PATH}")
+ get_filename_component(module_name "${module_name_path}" NAME)
+ set(srcdir "${BENCHLIB_SOURCE_DIR}")
+ set(objdir "${BENCHLIB_OBJECT_DIR}")
+
+ set(objfile "${objdir}/${module_name}.o")
+
+ # No whole-module-compilation or multi-threaded compilation.
+ # There is an output object file for each input file. We have to write
+ # an output-map-file to specify the output object file names.
+ set(sources)
+ set(objfiles)
+ _construct_sources_for_multibench(sources objfiles
+ SOURCES ${BENCHLIB_SOURCES})
+
+ add_custom_command(
+ OUTPUT ${objfiles}
+ DEPENDS ${sources} ${BENCHLIB_DEPENDS}
+ COMMAND "${SWIFT_EXEC}"
+ ${BENCHLIB_LIBRARY_FLAGS}
+ "-parse-as-library"
+ "-emit-module-path" "${objdir}/${module_name}.swiftmodule"
+ "-module-name" "${module_name}"
+ "-I" "${objdir}"
+ "-output-file-map" "${objdir}/${module_name}/outputmap.json"
+ ${sources})
+
+ set(${objfiles_out} ${objfiles} PARENT_SCOPE)
+endfunction()
+
function (swift_benchmark_compile_archopts)
cmake_parse_arguments(BENCH_COMPILE_ARCHOPTS "" "PLATFORM;ARCH;OPT" "" ${ARGN})
set(sdk ${${BENCH_COMPILE_ARCHOPTS_PLATFORM}_sdk})
@@ -95,7 +193,6 @@
set(bench_flags "${${benchvar}}")
set(common_options
- "-swift-version" "3" # FIXME: Force Swift 3 version compatibility.
"-c"
"-sdk" "${sdk}"
"-target" "${target}"
@@ -103,6 +200,8 @@
"-${BENCH_COMPILE_ARCHOPTS_OPT}"
"-no-link-objc-runtime"
"-I" "${srcdir}/utils/ObjectiveCTests")
+ set(common_swift3_options ${common_options} "-swift-version" "3")
+ set(common_swift4_options ${common_options} "-swift-version" "4")
# Always optimize the driver modules.
# Note that we compile the driver for Ounchecked also with -Ounchecked
@@ -128,7 +227,7 @@
SOURCE_DIR "${srcdir}"
OBJECT_DIR "${objdir}"
SOURCES ${sources}
- LIBRARY_FLAGS ${common_options})
+ LIBRARY_FLAGS ${common_swift3_options})
precondition(objfile_out)
list(APPEND bench_library_objects "${objfile_out}")
if (SWIFT_BENCHMARK_EMIT_SIB)
@@ -197,7 +296,7 @@
${stdlib_dependencies} ${bench_library_objects}
"${srcdir}/${module_name_path}.swift"
COMMAND "${SWIFT_EXEC}"
- ${common_options}
+ ${common_swift3_options}
${extra_options}
"-parse-as-library"
${bench_flags}
@@ -215,7 +314,7 @@
${stdlib_dependencies} ${bench_library_sibfiles}
"${srcdir}/${module_name_path}.swift"
COMMAND "${SWIFT_EXEC}"
- ${common_options}
+ ${common_swift3_options}
"-parse-as-library"
${bench_flags}
"-module-name" "${module_name}"
@@ -227,67 +326,61 @@
endif()
endforeach()
- foreach(module_name_path ${SWIFT_MULTISOURCE_BENCHES})
+ foreach(module_name_path ${SWIFT_MULTISOURCE_SWIFT3_BENCHES})
get_filename_component(module_name "${module_name_path}" NAME)
if ("${bench_flags}" MATCHES "-whole-module.*" AND
NOT "${bench_flags}" MATCHES "-num-threads.*")
- # Regular whole-module-compilation: only a single object file is
- # generated.
- set(objfile "${objdir}/${module_name}.o")
- list(APPEND SWIFT_BENCH_OBJFILES "${objfile}")
- set(sources)
- foreach(source ${${module_name}_sources})
- list(APPEND sources "${srcdir}/${source}")
- endforeach()
- add_custom_command(
- OUTPUT "${objfile}"
- DEPENDS
- ${stdlib_dependencies} ${bench_library_objects} ${sources}
- COMMAND "${SWIFT_EXEC}"
- ${common_options}
- ${bench_flags}
- "-parse-as-library"
- "-emit-module" "-module-name" "${module_name}"
- "-I" "${objdir}"
- "-o" "${objfile}"
- ${sources})
+ set(objfile_out)
+ add_swift_multisource_wmo_benchmark_library(objfile_out
+ MODULE_PATH "${module_name_path}"
+ SOURCE_DIR "${srcdir}"
+ OBJECT_DIR "${objdir}"
+ SOURCES ${${module_name}_sources}
+ LIBRARY_FLAGS ${common_swift3_options} ${bench_flags}
+ DEPENDS ${bench_library_objects} ${stdlib_dependencies})
+ precondition(objfile_out)
+ list(APPEND SWIFT_BENCH_OBJFILES "${objfile_out}")
else()
+ set(objfiles_out)
+ add_swift_multisource_nonwmo_benchmark_library(objfiles_out
+ MODULE_PATH "${module_name_path}"
+ SOURCE_DIR "${srcdir}"
+ OBJECT_DIR "${objdir}"
+ SOURCES ${${module_name}_sources}
+ LIBRARY_FLAGS ${common_swift3_options} ${bench_flags}
+ DEPENDS ${bench_library_objects} ${stdlib_dependencies})
+ precondition(objfiles_out)
+ list(APPEND SWIFT_BENCH_OBJFILES ${objfiles_out})
+ endif()
+ endforeach()
- # No whole-module-compilation or multi-threaded compilation.
- # There is an output object file for each input file. We have to write
- # an output-map-file to specify the output object file names.
- set(sources)
- set(objfiles)
- set(json "{\n")
- foreach(source ${${module_name}_sources})
- list(APPEND sources "${srcdir}/${source}")
+ foreach(module_name_path ${SWIFT_MULTISOURCE_SWIFT4_BENCHES})
+ get_filename_component(module_name "${module_name_path}" NAME)
- get_filename_component(basename "${source}" NAME_WE)
- set(objfile "${objdir}/${module_name}/${basename}.o")
-
- string(CONCAT json "${json}"
- " \"${srcdir}/${source}\": { \"object\": \"${objfile}\" },\n")
-
- list(APPEND objfiles "${objfile}")
- list(APPEND SWIFT_BENCH_OBJFILES "${objfile}")
- endforeach()
- string(CONCAT json "${json}" "}")
- file(WRITE "${objdir}/${module_name}/outputmap.json" ${json})
-
- add_custom_command(
- OUTPUT ${objfiles}
- DEPENDS
- ${stdlib_dependencies} ${bench_library_objects} ${sources}
- COMMAND "${SWIFT_EXEC}"
- ${common_options}
- ${bench_flags}
- "-parse-as-library"
- "-emit-module-path" "${objdir}/${module_name}.swiftmodule"
- "-module-name" "${module_name}"
- "-I" "${objdir}"
- "-output-file-map" "${objdir}/${module_name}/outputmap.json"
- ${sources})
+ if ("${bench_flags}" MATCHES "-whole-module.*" AND
+ NOT "${bench_flags}" MATCHES "-num-threads.*")
+ set(objfile_out)
+ add_swift_multisource_wmo_benchmark_library(objfile_out
+ MODULE_PATH "${module_name_path}"
+ SOURCE_DIR "${srcdir}"
+ OBJECT_DIR "${objdir}"
+ SOURCES ${${module_name}_sources}
+ LIBRARY_FLAGS ${common_swift4_options} ${bench_flags}
+ DEPENDS ${bench_library_objects} ${stdlib_dependencies})
+ precondition(objfile_out)
+ list(APPEND SWIFT_BENCH_OBJFILES "${objfile_out}")
+ else()
+ set(objfiles_out)
+ add_swift_multisource_nonwmo_benchmark_library(objfiles_out
+ MODULE_PATH "${module_name_path}"
+ SOURCE_DIR "${srcdir}"
+ OBJECT_DIR "${objdir}"
+ SOURCES ${${module_name}_sources}
+ LIBRARY_FLAGS ${common_swift4_options} ${bench_flags}
+ DEPENDS ${bench_library_objects} ${stdlib_dependencies})
+ precondition(objfiles_out)
+ list(APPEND SWIFT_BENCH_OBJFILES ${objfiles_out})
endif()
endforeach()
@@ -301,7 +394,7 @@
${bench_library_sibfiles} ${bench_driver_sibfiles}
${SWIFT_BENCH_SIBFILES} "${source}"
COMMAND "${SWIFT_EXEC}"
- ${common_options}
+ ${common_swift3_options}
"-force-single-frontend-invocation"
"-emit-module" "-module-name" "${module_name}"
"-I" "${objdir}"
@@ -395,7 +488,16 @@
list(APPEND platform_executables ${new_output_exec})
endforeach()
- set(executable_target "swift-benchmark-${SWIFT_BENCHMARK_COMPILE_PLATFORM}-${arch}")
+ # If we are building standalone, we add the -external suffix to all of our
+ # cmake target names. This enables the main swift build to simple create
+ # -external targets and forward them via AddExternalProject to the
+ # standalone benchmark project. The reason why this is necessary is that we
+ # want to be able to support in-tree and out-of-tree benchmark builds at the
+ # same time implying that we need some sort of way to distinguish the
+ # in-tree (which don't have the suffix) from the out of tree target (which
+ # do).
+ translate_flag(SWIFT_BENCHMARK_BUILT_STANDALONE "-external" external)
+ set(executable_target "swift-benchmark-${SWIFT_BENCHMARK_COMPILE_PLATFORM}-${arch}${external}")
add_custom_target("${executable_target}"
DEPENDS ${platform_executables})
diff --git a/benchmark/cmake/modules/SwiftBenchmarkUtils.cmake b/benchmark/cmake/modules/SwiftBenchmarkUtils.cmake
index 4806892..9c5e6a0 100644
--- a/benchmark/cmake/modules/SwiftBenchmarkUtils.cmake
+++ b/benchmark/cmake/modules/SwiftBenchmarkUtils.cmake
@@ -27,3 +27,19 @@
endif()
endif()
endfunction()
+
+# Translate a yes/no variable to the presence of a given string in a
+# variable.
+#
+# Usage:
+# translate_flag(is_set flag_name var_name)
+#
+# If is_set is true, sets ${var_name} to ${flag_name}. Otherwise,
+# unsets ${var_name}.
+function(translate_flag is_set flag_name var_name)
+ if(${is_set})
+ set("${var_name}" "${flag_name}" PARENT_SCOPE)
+ else()
+ set("${var_name}" "" PARENT_SCOPE)
+ endif()
+endfunction()
diff --git a/benchmark/multi-source/PrimsSplit/Prims.swift b/benchmark/multi-source/PrimsSplit/Prims.swift
new file mode 100644
index 0000000..57d1f6d
--- /dev/null
+++ b/benchmark/multi-source/PrimsSplit/Prims.swift
@@ -0,0 +1,214 @@
+//===--- Prims.swift ------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// The test implements Prim's algorithm for minimum spanning tree building.
+// http://en.wikipedia.org/wiki/Prim%27s_algorithm
+
+// This class implements array-based heap (priority queue).
+// It is used to store edges from nodes in spanning tree to nodes outside of it.
+// We are interested only in the edges with the smallest costs, so if there are
+// several edges pointing to the same node, we keep only one from them. Thus,
+// it is enough to record this node instead.
+// We maintain a map (node index in graph)->(node index in heap) to be able to
+// update the heap fast when we add a new node to the tree.
+import TestsUtils
+
+class PriorityQueue {
+ final var heap: Array<EdgeCost>
+ final var graphIndexToHeapIndexMap: Array<Int?>
+
+ // Create heap for graph with NUM nodes.
+ init(Num: Int) {
+ heap = Array<EdgeCost>()
+ graphIndexToHeapIndexMap = Array<Int?>(repeating:nil, count: Num)
+ }
+
+ func isEmpty() -> Bool {
+ return heap.isEmpty
+ }
+
+ // Insert element N to heap, maintaining the heap property.
+ func insert(_ n: EdgeCost) {
+ let ind: Int = heap.count
+ heap.append(n)
+ graphIndexToHeapIndexMap[n.to] = heap.count - 1
+ bubbleUp(ind)
+ }
+
+ // Insert element N if in's not in the heap, or update its cost if the new
+ // value is less than the existing one.
+ func insertOrUpdate(_ n: EdgeCost) {
+ let id = n.to
+ let c = n.cost
+ if let ind = graphIndexToHeapIndexMap[id] {
+ if heap[ind].cost <= c {
+ // We don't need an edge with a bigger cost
+ return
+ }
+ heap[ind].cost = c
+ heap[ind].from = n.from
+ bubbleUp(ind)
+ } else {
+ insert(n)
+ }
+ }
+
+ // Restore heap property by moving element at index IND up.
+ // This is needed after insertion, and after decreasing an element's cost.
+ func bubbleUp(_ ind: Int) {
+ var ind = ind
+ let c = heap[ind].cost
+ while (ind != 0) {
+ let p = getParentIndex(ind)
+ if heap[p].cost > c {
+ Swap(p, with: ind)
+ ind = p
+ } else {
+ break
+ }
+ }
+ }
+
+ // Pop minimum element from heap and restore the heap property after that.
+ func pop() -> EdgeCost? {
+ if (heap.isEmpty) {
+ return nil
+ }
+ Swap(0, with:heap.count-1)
+ let r = heap.removeLast()
+ graphIndexToHeapIndexMap[r.to] = nil
+ bubbleDown(0)
+ return r
+ }
+
+ // Restore heap property by moving element at index IND down.
+ // This is needed after removing an element, and after increasing an
+ // element's cost.
+ func bubbleDown(_ ind: Int) {
+ var ind = ind
+ let n = heap.count
+ while (ind < n) {
+ let l = getLeftChildIndex(ind)
+ let r = getRightChildIndex(ind)
+ if (l >= n) {
+ break
+ }
+ var min: Int
+ if (r < n && heap[r].cost < heap[l].cost) {
+ min = r
+ } else {
+ min = l
+ }
+ if (heap[ind].cost <= heap[min].cost) {
+ break
+ }
+ Swap(ind, with: min)
+ ind = min
+ }
+ }
+
+ // Swaps elements I and J in the heap and correspondingly updates
+ // graphIndexToHeapIndexMap.
+ func Swap(_ i: Int, with j : Int) {
+ if (i == j) {
+ return
+ }
+ (heap[i], heap[j]) = (heap[j], heap[i])
+ let (I, J) = (heap[i].to, heap[j].to)
+ (graphIndexToHeapIndexMap[I], graphIndexToHeapIndexMap[J]) =
+ (graphIndexToHeapIndexMap[J], graphIndexToHeapIndexMap[I])
+ }
+
+ // Dumps the heap.
+ func dump() {
+ print("QUEUE")
+ for nodeCost in heap {
+ let to: Int = nodeCost.to
+ let from: Int = nodeCost.from
+ let cost: Double = nodeCost.cost
+ print("(\(from)->\(to), \(cost))")
+ }
+ }
+
+ func getLeftChildIndex(_ index : Int) -> Int {
+ return index*2 + 1
+ }
+ func getRightChildIndex(_ index : Int) -> Int {
+ return (index + 1)*2
+ }
+ func getParentIndex(_ childIndex : Int) -> Int {
+ return (childIndex - 1)/2
+ }
+}
+
+struct GraphNode {
+ var id: Int
+ var adjList: Array<Int>
+
+ init(i : Int) {
+ id = i
+ adjList = Array<Int>()
+ }
+}
+
+struct EdgeCost {
+ var to: Int
+ var cost: Double
+ var from: Int
+}
+
+struct Edge : Equatable {
+ var start: Int
+ var end: Int
+}
+
+func ==(lhs: Edge, rhs: Edge) -> Bool {
+ return lhs.start == rhs.start && lhs.end == rhs.end
+}
+
+extension Edge : Hashable {
+ var hashValue: Int {
+ get {
+ return start.hashValue ^ end.hashValue
+ }
+ }
+}
+
+func Prims(_ graph : Array<GraphNode>, _ fun : (Int, Int) -> Double) -> Array<Int?> {
+ var treeEdges = Array<Int?>(repeating:nil, count:graph.count)
+
+ let queue = PriorityQueue(Num:graph.count)
+ // Make the minimum spanning tree root its own parent for simplicity.
+ queue.insert(EdgeCost(to: 0, cost: 0.0, from: 0))
+
+ // Take an element with the smallest cost from the queue and add its
+ // neighbors to the queue if their cost was updated
+ while !queue.isEmpty() {
+ // Add an edge with minimum cost to the spanning tree
+ let e = queue.pop()!
+ let newnode = e.to
+ // Add record about the edge newnode->e.from to treeEdges
+ treeEdges[newnode] = e.from
+
+ // Check all adjacent nodes and add edges, ending outside the tree, to the
+ // queue. If the queue already contains an edge to an adjacent node, we
+ // replace existing one with the new one in case the new one costs less.
+ for adjNodeIndex in graph[newnode].adjList {
+ if treeEdges[adjNodeIndex] != nil {
+ continue
+ }
+ let newcost = fun(newnode, graph[adjNodeIndex].id)
+ queue.insertOrUpdate(EdgeCost(to: adjNodeIndex, cost: newcost, from: newnode))
+ }
+ }
+ return treeEdges
+}
diff --git a/benchmark/multi-source/PrimsSplit/README.md b/benchmark/multi-source/PrimsSplit/README.md
new file mode 100644
index 0000000..9987e9c
--- /dev/null
+++ b/benchmark/multi-source/PrimsSplit/README.md
@@ -0,0 +1,4 @@
+
+This test is just a split version of Prims.swift. The reason why this is here is
+to provide at least 1 multi-source benchmark for the purpose of validating that
+the multi-source benchmarks can build successfully.
diff --git a/benchmark/multi-source/PrimsSplit/main.swift b/benchmark/multi-source/PrimsSplit/main.swift
new file mode 100644
index 0000000..0609e92
--- /dev/null
+++ b/benchmark/multi-source/PrimsSplit/main.swift
@@ -0,0 +1,555 @@
+//===--- main.swift -------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+import TestsUtils
+
+@inline(never)
+public func run_PrimsSplit(_ N: Int) {
+ for _ in 1...5*N {
+ let nodes : [Int] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99 ]
+
+ // Prim's algorithm is designed for undirected graphs.
+ // Due to that, in our set all the edges are paired, i.e. for any
+ // edge (start, end, C) there is also an edge (end, start, C).
+ let edges : [(Int, Int, Double)] = [
+ (26, 47, 921),
+ (20, 25, 971),
+ (92, 59, 250),
+ (33, 55, 1391),
+ (78, 39, 313),
+ (7, 25, 637),
+ (18, 19, 1817),
+ (33, 41, 993),
+ (64, 41, 926),
+ (88, 86, 574),
+ (93, 15, 1462),
+ (86, 33, 1649),
+ (37, 35, 841),
+ (98, 51, 1160),
+ (15, 30, 1125),
+ (65, 78, 1052),
+ (58, 12, 1273),
+ (12, 17, 285),
+ (45, 61, 1608),
+ (75, 53, 545),
+ (99, 48, 410),
+ (97, 0, 1303),
+ (48, 17, 1807),
+ (1, 54, 1491),
+ (15, 34, 807),
+ (94, 98, 646),
+ (12, 69, 136),
+ (65, 11, 983),
+ (63, 83, 1604),
+ (78, 89, 1828),
+ (61, 63, 845),
+ (18, 36, 1626),
+ (68, 52, 1324),
+ (14, 50, 690),
+ (3, 11, 943),
+ (21, 68, 914),
+ (19, 44, 1762),
+ (85, 80, 270),
+ (59, 92, 250),
+ (86, 84, 1431),
+ (19, 18, 1817),
+ (52, 68, 1324),
+ (16, 29, 1108),
+ (36, 80, 395),
+ (67, 18, 803),
+ (63, 88, 1717),
+ (68, 21, 914),
+ (75, 82, 306),
+ (49, 82, 1292),
+ (73, 45, 1876),
+ (89, 82, 409),
+ (45, 47, 272),
+ (22, 83, 597),
+ (61, 12, 1791),
+ (44, 68, 1229),
+ (50, 51, 917),
+ (14, 53, 355),
+ (77, 41, 138),
+ (54, 21, 1870),
+ (93, 70, 1582),
+ (76, 2, 1658),
+ (83, 73, 1162),
+ (6, 1, 482),
+ (11, 65, 983),
+ (81, 90, 1024),
+ (19, 1, 970),
+ (8, 58, 1131),
+ (60, 42, 477),
+ (86, 29, 258),
+ (69, 59, 903),
+ (34, 15, 807),
+ (37, 2, 1451),
+ (7, 73, 754),
+ (47, 86, 184),
+ (67, 17, 449),
+ (18, 67, 803),
+ (25, 4, 595),
+ (3, 31, 1337),
+ (64, 31, 1928),
+ (9, 43, 237),
+ (83, 63, 1604),
+ (47, 45, 272),
+ (86, 88, 574),
+ (87, 74, 934),
+ (98, 94, 646),
+ (20, 1, 642),
+ (26, 92, 1344),
+ (18, 17, 565),
+ (47, 11, 595),
+ (10, 59, 1558),
+ (2, 76, 1658),
+ (77, 74, 1277),
+ (42, 60, 477),
+ (80, 36, 395),
+ (35, 23, 589),
+ (50, 37, 203),
+ (6, 96, 481),
+ (78, 65, 1052),
+ (1, 52, 127),
+ (65, 23, 1932),
+ (46, 51, 213),
+ (59, 89, 89),
+ (15, 93, 1462),
+ (69, 3, 1305),
+ (17, 37, 1177),
+ (30, 3, 193),
+ (9, 15, 818),
+ (75, 95, 977),
+ (86, 47, 184),
+ (10, 12, 1736),
+ (80, 27, 1010),
+ (12, 10, 1736),
+ (86, 1, 1958),
+ (60, 12, 1240),
+ (43, 71, 683),
+ (91, 65, 1519),
+ (33, 86, 1649),
+ (62, 26, 1773),
+ (1, 13, 1187),
+ (2, 10, 1018),
+ (91, 29, 351),
+ (69, 12, 136),
+ (43, 9, 237),
+ (29, 86, 258),
+ (17, 48, 1807),
+ (31, 64, 1928),
+ (68, 61, 1936),
+ (76, 38, 1724),
+ (1, 6, 482),
+ (53, 14, 355),
+ (51, 50, 917),
+ (54, 13, 815),
+ (19, 29, 883),
+ (35, 87, 974),
+ (70, 96, 511),
+ (23, 35, 589),
+ (39, 69, 1588),
+ (93, 73, 1093),
+ (13, 73, 435),
+ (5, 60, 1619),
+ (42, 41, 1523),
+ (66, 58, 1596),
+ (1, 67, 431),
+ (17, 67, 449),
+ (30, 95, 906),
+ (71, 43, 683),
+ (5, 87, 190),
+ (12, 78, 891),
+ (30, 97, 402),
+ (28, 17, 1131),
+ (7, 97, 1356),
+ (58, 66, 1596),
+ (20, 37, 1294),
+ (73, 76, 514),
+ (54, 8, 613),
+ (68, 35, 1252),
+ (92, 32, 701),
+ (3, 90, 652),
+ (99, 46, 1576),
+ (13, 54, 815),
+ (20, 87, 1390),
+ (36, 18, 1626),
+ (51, 26, 1146),
+ (2, 23, 581),
+ (29, 7, 1558),
+ (88, 59, 173),
+ (17, 1, 1071),
+ (37, 49, 1011),
+ (18, 6, 696),
+ (88, 33, 225),
+ (58, 38, 802),
+ (87, 50, 1744),
+ (29, 91, 351),
+ (6, 71, 1053),
+ (45, 24, 1720),
+ (65, 91, 1519),
+ (37, 50, 203),
+ (11, 3, 943),
+ (72, 65, 1330),
+ (45, 50, 339),
+ (25, 20, 971),
+ (15, 9, 818),
+ (14, 54, 1353),
+ (69, 95, 393),
+ (8, 66, 1213),
+ (52, 2, 1608),
+ (50, 14, 690),
+ (50, 45, 339),
+ (1, 37, 1273),
+ (45, 93, 1650),
+ (39, 78, 313),
+ (1, 86, 1958),
+ (17, 28, 1131),
+ (35, 33, 1667),
+ (23, 2, 581),
+ (51, 66, 245),
+ (17, 54, 924),
+ (41, 49, 1629),
+ (60, 5, 1619),
+ (56, 93, 1110),
+ (96, 13, 461),
+ (25, 7, 637),
+ (11, 69, 370),
+ (90, 3, 652),
+ (39, 71, 1485),
+ (65, 51, 1529),
+ (20, 6, 1414),
+ (80, 85, 270),
+ (73, 83, 1162),
+ (0, 97, 1303),
+ (13, 33, 826),
+ (29, 71, 1788),
+ (33, 12, 461),
+ (12, 58, 1273),
+ (69, 39, 1588),
+ (67, 75, 1504),
+ (87, 20, 1390),
+ (88, 97, 526),
+ (33, 88, 225),
+ (95, 69, 393),
+ (2, 52, 1608),
+ (5, 25, 719),
+ (34, 78, 510),
+ (53, 99, 1074),
+ (33, 35, 1667),
+ (57, 30, 361),
+ (87, 58, 1574),
+ (13, 90, 1030),
+ (79, 74, 91),
+ (4, 86, 1107),
+ (64, 94, 1609),
+ (11, 12, 167),
+ (30, 45, 272),
+ (47, 91, 561),
+ (37, 17, 1177),
+ (77, 49, 883),
+ (88, 23, 1747),
+ (70, 80, 995),
+ (62, 77, 907),
+ (18, 4, 371),
+ (73, 93, 1093),
+ (11, 47, 595),
+ (44, 23, 1990),
+ (20, 0, 512),
+ (3, 69, 1305),
+ (82, 3, 1815),
+ (20, 88, 368),
+ (44, 45, 364),
+ (26, 51, 1146),
+ (7, 65, 349),
+ (71, 39, 1485),
+ (56, 88, 1954),
+ (94, 69, 1397),
+ (12, 28, 544),
+ (95, 75, 977),
+ (32, 90, 789),
+ (53, 1, 772),
+ (54, 14, 1353),
+ (49, 77, 883),
+ (92, 26, 1344),
+ (17, 18, 565),
+ (97, 88, 526),
+ (48, 80, 1203),
+ (90, 32, 789),
+ (71, 6, 1053),
+ (87, 35, 974),
+ (55, 90, 1808),
+ (12, 61, 1791),
+ (1, 96, 328),
+ (63, 10, 1681),
+ (76, 34, 871),
+ (41, 64, 926),
+ (42, 97, 482),
+ (25, 5, 719),
+ (23, 65, 1932),
+ (54, 1, 1491),
+ (28, 12, 544),
+ (89, 10, 108),
+ (27, 33, 143),
+ (67, 1, 431),
+ (32, 45, 52),
+ (79, 33, 1871),
+ (6, 55, 717),
+ (10, 58, 459),
+ (67, 39, 393),
+ (10, 4, 1808),
+ (96, 6, 481),
+ (1, 19, 970),
+ (97, 7, 1356),
+ (29, 16, 1108),
+ (1, 53, 772),
+ (30, 15, 1125),
+ (4, 6, 634),
+ (6, 20, 1414),
+ (88, 56, 1954),
+ (87, 64, 1950),
+ (34, 76, 871),
+ (17, 12, 285),
+ (55, 59, 321),
+ (61, 68, 1936),
+ (50, 87, 1744),
+ (84, 44, 952),
+ (41, 33, 993),
+ (59, 18, 1352),
+ (33, 27, 143),
+ (38, 32, 1210),
+ (55, 70, 1264),
+ (38, 58, 802),
+ (1, 20, 642),
+ (73, 13, 435),
+ (80, 48, 1203),
+ (94, 64, 1609),
+ (38, 28, 414),
+ (73, 23, 1113),
+ (78, 12, 891),
+ (26, 62, 1773),
+ (87, 43, 579),
+ (53, 6, 95),
+ (59, 95, 285),
+ (88, 63, 1717),
+ (17, 5, 633),
+ (66, 8, 1213),
+ (41, 42, 1523),
+ (83, 22, 597),
+ (95, 30, 906),
+ (51, 65, 1529),
+ (17, 49, 1727),
+ (64, 87, 1950),
+ (86, 4, 1107),
+ (37, 98, 1102),
+ (32, 92, 701),
+ (60, 94, 198),
+ (73, 98, 1749),
+ (4, 18, 371),
+ (96, 70, 511),
+ (7, 29, 1558),
+ (35, 37, 841),
+ (27, 64, 384),
+ (12, 33, 461),
+ (36, 38, 529),
+ (69, 16, 1183),
+ (91, 47, 561),
+ (85, 29, 1676),
+ (3, 82, 1815),
+ (69, 58, 1579),
+ (93, 45, 1650),
+ (97, 42, 482),
+ (37, 1, 1273),
+ (61, 4, 543),
+ (96, 1, 328),
+ (26, 0, 1993),
+ (70, 64, 878),
+ (3, 30, 193),
+ (58, 69, 1579),
+ (4, 25, 595),
+ (31, 3, 1337),
+ (55, 6, 717),
+ (39, 67, 393),
+ (78, 34, 510),
+ (75, 67, 1504),
+ (6, 53, 95),
+ (51, 79, 175),
+ (28, 91, 1040),
+ (89, 78, 1828),
+ (74, 93, 1587),
+ (45, 32, 52),
+ (10, 2, 1018),
+ (49, 37, 1011),
+ (63, 61, 845),
+ (0, 20, 512),
+ (1, 17, 1071),
+ (99, 53, 1074),
+ (37, 20, 1294),
+ (10, 89, 108),
+ (33, 92, 946),
+ (23, 73, 1113),
+ (23, 88, 1747),
+ (49, 17, 1727),
+ (88, 20, 368),
+ (21, 54, 1870),
+ (70, 93, 1582),
+ (59, 88, 173),
+ (32, 38, 1210),
+ (89, 59, 89),
+ (23, 44, 1990),
+ (38, 76, 1724),
+ (30, 57, 361),
+ (94, 60, 198),
+ (59, 10, 1558),
+ (55, 64, 1996),
+ (12, 11, 167),
+ (36, 24, 1801),
+ (97, 30, 402),
+ (52, 1, 127),
+ (58, 87, 1574),
+ (54, 17, 924),
+ (93, 74, 1587),
+ (24, 36, 1801),
+ (2, 37, 1451),
+ (91, 28, 1040),
+ (59, 55, 321),
+ (69, 11, 370),
+ (8, 54, 613),
+ (29, 85, 1676),
+ (44, 19, 1762),
+ (74, 79, 91),
+ (93, 56, 1110),
+ (58, 10, 459),
+ (41, 50, 1559),
+ (66, 51, 245),
+ (80, 19, 1838),
+ (33, 79, 1871),
+ (76, 73, 514),
+ (98, 37, 1102),
+ (45, 44, 364),
+ (16, 69, 1183),
+ (49, 41, 1629),
+ (19, 80, 1838),
+ (71, 57, 500),
+ (6, 4, 634),
+ (64, 27, 384),
+ (84, 86, 1431),
+ (5, 17, 633),
+ (96, 88, 334),
+ (87, 5, 190),
+ (70, 21, 1619),
+ (55, 33, 1391),
+ (10, 63, 1681),
+ (11, 62, 1339),
+ (33, 13, 826),
+ (64, 70, 878),
+ (65, 72, 1330),
+ (70, 55, 1264),
+ (64, 55, 1996),
+ (50, 41, 1559),
+ (46, 99, 1576),
+ (88, 96, 334),
+ (51, 20, 868),
+ (73, 7, 754),
+ (80, 70, 995),
+ (44, 84, 952),
+ (29, 19, 883),
+ (59, 69, 903),
+ (57, 53, 1575),
+ (90, 13, 1030),
+ (28, 38, 414),
+ (12, 60, 1240),
+ (85, 58, 573),
+ (90, 55, 1808),
+ (4, 10, 1808),
+ (68, 44, 1229),
+ (92, 33, 946),
+ (90, 81, 1024),
+ (53, 75, 545),
+ (45, 30, 272),
+ (41, 77, 138),
+ (21, 70, 1619),
+ (45, 73, 1876),
+ (35, 68, 1252),
+ (13, 96, 461),
+ (53, 57, 1575),
+ (82, 89, 409),
+ (28, 61, 449),
+ (58, 61, 78),
+ (27, 80, 1010),
+ (61, 58, 78),
+ (38, 36, 529),
+ (80, 30, 397),
+ (18, 59, 1352),
+ (62, 11, 1339),
+ (95, 59, 285),
+ (51, 98, 1160),
+ (6, 18, 696),
+ (30, 80, 397),
+ (69, 94, 1397),
+ (58, 85, 573),
+ (48, 99, 410),
+ (51, 46, 213),
+ (57, 71, 500),
+ (91, 30, 104),
+ (65, 7, 349),
+ (79, 51, 175),
+ (47, 26, 921),
+ (4, 61, 543),
+ (98, 73, 1749),
+ (74, 77, 1277),
+ (61, 28, 449),
+ (58, 8, 1131),
+ (61, 45, 1608),
+ (74, 87, 934),
+ (71, 29, 1788),
+ (30, 91, 104),
+ (13, 1, 1187),
+ (0, 26, 1993),
+ (82, 49, 1292),
+ (43, 87, 579),
+ (24, 45, 1720),
+ (20, 51, 868),
+ (77, 62, 907),
+ (82, 75, 306),
+ ]
+
+ // Prepare graph and edge->cost map
+ var graph = Array<GraphNode>()
+ for n in nodes {
+ graph.append(GraphNode(i: n))
+ }
+ var map = Dictionary<Edge, Double>()
+ for tup in edges {
+ map[Edge(start: tup.0, end: tup.1)] = tup.2
+ graph[tup.0].adjList.append(tup.1)
+ }
+
+ // Find spanning tree
+ let treeEdges = Prims(graph, { (start: Int, end: Int) in
+ return map[Edge(start: start, end: end)]!
+ })
+
+ // Compute its cost in order to check results
+ var cost = 0.0
+ for i in 1..<treeEdges.count {
+ if let n = treeEdges[i] { cost += map[Edge(start: n, end: i)]! }
+ }
+ CheckResults(Int(cost) == 49324)
+ }
+}
diff --git a/benchmark/utils/main.swift b/benchmark/utils/main.swift
index 88b7326..eec59ec 100644
--- a/benchmark/utils/main.swift
+++ b/benchmark/utils/main.swift
@@ -90,6 +90,7 @@
import Prefix
import PrefixWhile
import Prims
+import PrimsSplit
import ProtocolDispatch
import ProtocolDispatch2
import RC4
@@ -402,6 +403,7 @@
addTo(&precommitTests, "PrefixWhileSequence", run_PrefixWhileSequence, [.validation, .api, .abstraction])
addTo(&precommitTests, "PrefixWhileSequenceLazy", run_PrefixWhileSequenceLazy, [.validation, .api, .abstraction])
addTo(&precommitTests, "Prims", run_Prims, [.validation, .algorithm])
+addTo(&precommitTests, "PrimsSplit", run_PrimsSplit, [.validation, .algorithm])
addTo(&precommitTests, "ProtocolDispatch", run_ProtocolDispatch, [.validation, .abstraction])
addTo(&precommitTests, "ProtocolDispatch2", run_ProtocolDispatch2, [.validation, .abstraction])
addTo(&precommitTests, "RC4", run_RC4, [.validation, .algorithm])
diff --git a/cmake/modules/SwiftExternalBenchmarkBuild.cmake b/cmake/modules/SwiftExternalBenchmarkBuild.cmake
new file mode 100644
index 0000000..64db306
--- /dev/null
+++ b/cmake/modules/SwiftExternalBenchmarkBuild.cmake
@@ -0,0 +1,89 @@
+
+include(CMakeParseArguments)
+include(LLVMExternalProjectUtils)
+include(SwiftUtils)
+
+# This is the name of the target on the parent cmake side that is associated
+# with an external project target.
+#
+# If LLVMExternalProjectUtils refactors its external target code, so we can
+# easily add individual forwarded targets with different dependencies, this can
+# be removed.
+function(compute_external_target_name target_name_out target)
+ string(REPLACE ":" ";" target_list ${target})
+ list(GET target_list 0 target)
+ list(LENGTH target_list target_list_len)
+ if(${target_list_len} GREATER 1)
+ list(GET target_list 1 target_name)
+ else()
+ set(target_name "${target}")
+ endif()
+
+ set(${target_name_out} "${target_name}" PARENT_SCOPE)
+endfunction()
+
+function(compute_stdlib_dependencies stdlib_dependencies_out platform)
+ foreach(stdlib_dependency ${UNIVERSAL_LIBRARY_NAMES_${platform}})
+ string(FIND "${stdlib_dependency}" "Unittest" find_output)
+ if("${find_output}" STREQUAL "-1")
+ list(APPEND stdlib_dependencies "${stdlib_dependency}")
+ endif()
+ endforeach()
+ set(${stdlib_dependencies_out} "${stdlib_dependencies}" PARENT_SCOPE)
+endfunction()
+
+set(ONLY_PLATFORMS "macosx" "iphoneos" "appletvos" "watchos")
+
+function (get_platform_from_target target_platform_out target)
+ foreach (platform ${ONLY_PLATFORMS})
+ string(FIND "${target}" "${platform}" FOUND_TARGET_PLATFORM)
+ if (NOT FOUND_TARGET_PLATFORM)
+ continue()
+ endif()
+
+ set(${target_platform_out} "${platform}" PARENT_SCOPE)
+ break()
+ endforeach()
+endfunction()
+
+function (compute_target_stdlib_dependencies dependencies_out target)
+ get_platform_from_target(target_platform ${target})
+ precondition(target_platform
+ MESSAGE "Failed to find a platform for ${target_platform}")
+ compute_stdlib_dependencies(stdlib_dependencies ${target_platform})
+ set(${dependencies_out} ${stdlib_dependencies} PARENT_SCOPE)
+endfunction()
+
+function (add_external_benchmark_suite)
+ set(name swift-benchmark)
+ set(src_dir ${SWIFT_SOURCE_DIR}/benchmark)
+ set(bin_dir ${SWIFT_BINARY_DIR}/external-benchmark/binary)
+ set(stamp_dir ${SWIFT_BINARY_DIR}/external-benchmark/stamps)
+ set(prefix_dir ${SWIFT_BINARY_DIR}/external-benchmark/prefix)
+
+ set(bench_targets Benchmark_O Benchmark_Onone Benchmark_Ounchecked)
+ set(library_targets swift-benchmark-macosx-x86_64-external)
+
+ set(all_stdlib_dependencies)
+ foreach (target ${library_targets})
+ compute_target_stdlib_dependencies(stdlib_dependencies ${target})
+ precondition(stdlib_dependencies)
+ # Add dependencies from all of our stdlib dependencies to
+ # swift-bench-configure. This will ensure the stdlib is ready to be poked at
+ # in the configure script if we ever want to do so.
+ list(APPEND all_stdlib_dependencies ${stdlib_dependencies})
+ endforeach()
+
+ llvm_ExternalProject_add(swift-bench ${src_dir}
+ SOURCE_DIR ${src_dir}
+ EXCLUDE_FROM_ALL
+ DEPENDS swift ${all_stdlib_dependencies}
+ EXTRA_TARGETS ${bench_targets} ${library_targets}
+ CMAKE_ARGS
+ -DSWIFT_EXEC=${SWIFT_BINARY_DIR}/bin/swiftc
+ -DSWIFT_LIBRARY_PATH=${SWIFT_BINARY_DIR}/lib/swift
+ -DCMAKE_C_COMPILER=${PATH_TO_CLANG_BUILD}/bin/clang
+ -DCMAKE_CXX_COMPILER=${PATH_TO_CLANG_BUILD}/bin/clang++
+ PASSTHROUGH_PREFIXES SWIFT_BENCHMARK
+ )
+endfunction()
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index 1d53b34..0259ba7 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -305,11 +305,9 @@
/// Flags in a generic nominal type descriptor.
class GenericParameterDescriptorFlags {
- typedef uint32_t int_type;
+ typedef uint16_t int_type;
enum : int_type {
- HasParent = 0x01,
- HasGenericParent = 0x02,
- HasVTable = 0x04,
+ HasVTable = 0x0004,
};
int_type Data;
@@ -317,38 +315,11 @@
public:
constexpr GenericParameterDescriptorFlags() : Data(0) {}
- constexpr GenericParameterDescriptorFlags withHasParent(bool b) const {
- return GenericParameterDescriptorFlags(b ? (Data | HasParent)
- : (Data & ~HasParent));
- }
-
- constexpr GenericParameterDescriptorFlags withHasGenericParent(bool b) const {
- return GenericParameterDescriptorFlags(b ? (Data | HasGenericParent)
- : (Data & ~HasGenericParent));
- }
-
constexpr GenericParameterDescriptorFlags withHasVTable(bool b) const {
return GenericParameterDescriptorFlags(b ? (Data | HasVTable)
: (Data & ~HasVTable));
}
- /// Does this type have a lexical parent type?
- ///
- /// For class metadata, if this is true, the storage for the parent type
- /// appears immediately prior to the first generic argument. Other
- /// metadata always have a slot for their parent type.
- bool hasParent() const {
- return Data & HasParent;
- }
-
- /// Given that this type has a parent type, is that type generic? If so,
- /// it forms part of the key distinguishing this metadata from other
- /// metadata, and the parent metadata will be the first argument to
- /// the generic metadata access function.
- bool hasGenericParent() const {
- return Data & HasGenericParent;
- }
-
/// If this type is a class, does it have a vtable? If so, the number
/// of vtable entries immediately follows the generic requirement
/// descriptor.
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index 359a7bd..19937a3 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -259,8 +259,8 @@
// FIXME: Replace with improved @available attribute.
SIMPLE_DECL_ATTR(_versioned, Versioned,
OnFunc | OnVar | OnSubscript | OnConstructor |
- OnStruct | OnEnum | OnClass | OnProtocol |
- LongAttribute | UserInaccessible,
+ OnDestructor | OnStruct | OnEnum | OnClass |
+ OnProtocol | LongAttribute | UserInaccessible,
64)
SIMPLE_DECL_ATTR(discardableResult, DiscardableResult,
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index 8eecc19..ddf8ebe 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -215,15 +215,6 @@
/// a superclass requirement.
bool isConformanceSatisfiedBySuperclass(ProtocolDecl *proto) const;
- /// Lookup a nested type with the given name within this equivalence
- /// class.
- ///
- /// \param otherConcreteTypes If non-null, will be filled in the all of the
- /// concrete types we found (other than the result) with the same name.
- TypeDecl *lookupNestedType(
- Identifier name,
- SmallVectorImpl<TypeDecl *> *otherConcreteTypes = nullptr);
-
/// Dump a debugging representation of this equivalence class.
void dump(llvm::raw_ostream &out) const;
@@ -241,17 +232,6 @@
/// anchor was cached.
unsigned numMembers;
} archetypeAnchorCache;
-
- /// Describes a cached nested type.
- struct CachedNestedType {
- unsigned numConformancesPresent;
- CanType superclassPresent;
- llvm::TinyPtrVector<TypeDecl *> types;
- };
-
- /// Cached nested-type information, which contains the best declaration
- /// for a given name.
- llvm::SmallDenseMap<Identifier, CachedNestedType> nestedTypeNameCache;
};
friend class RequirementSource;
@@ -542,6 +522,9 @@
/// \brief Add all of a generic signature's parameters and requirements.
void addGenericSignature(GenericSignature *sig);
+ /// \brief Build the generic signature.
+ GenericSignature *getGenericSignature();
+
/// Infer requirements from the given type, recursively.
///
/// This routine infers requirements from a type that occurs within the
@@ -575,13 +558,11 @@
/// \brief Finalize the set of requirements and compute the generic
/// signature.
///
- /// After this point, one cannot introduce new requirements, and the
- /// generic signature builder no longer has valid state.
+ /// After this point, one cannot introduce new requirements.
GenericSignature *computeGenericSignature(
SourceLoc loc,
- bool allowConcreteGenericParams = false) &&;
+ bool allowConcreteGenericParams = false);
-private:
/// Finalize the set of requirements, performing any remaining checking
/// required before generating archetypes.
///
@@ -591,7 +572,6 @@
ArrayRef<GenericTypeParamType *> genericParams,
bool allowConcreteGenericParams=false);
-public:
/// Process any delayed requirements that can be handled now.
void processDelayedRequirements();
@@ -1510,12 +1490,6 @@
return parentOrBuilder.dyn_cast<PotentialArchetype *>();
}
- /// Retrieve the type declaration to which this nested type was resolved.
- TypeDecl *getResolvedType() const {
- assert(getParent() && "Not an associated type");
- return identifier.assocTypeOrConcrete;
- }
-
/// Retrieve the associated type to which this potential archetype
/// has been resolved.
AssociatedTypeDecl *getResolvedAssociatedType() const {
@@ -1658,8 +1632,13 @@
ArchetypeResolutionKind kind,
GenericSignatureBuilder &builder);
- /// \brief Retrieve (or create) a nested type with a known type.
- PotentialArchetype *getNestedType(TypeDecl *type,
+ /// \brief Retrieve (or create) a nested type with a known associated type.
+ PotentialArchetype *getNestedType(AssociatedTypeDecl *assocType,
+ GenericSignatureBuilder &builder);
+
+ /// \brief Retrieve (or create) a nested type with a known concrete type
+ /// declaration.
+ PotentialArchetype *getNestedType(TypeDecl *concreteDecl,
GenericSignatureBuilder &builder);
/// \brief Retrieve (or create) a nested type that is the current best
@@ -1679,8 +1658,8 @@
/// type or typealias of the given protocol, unless the \c kind implies that
/// a potential archetype should not be created if it's missing.
PotentialArchetype *updateNestedTypeForConformance(
- TypeDecl *type,
- ArchetypeResolutionKind kind);
+ PointerUnion<AssociatedTypeDecl *, TypeDecl *> type,
+ ArchetypeResolutionKind kind);
/// Update the named nested type when we know this type conforms to the given
/// protocol.
diff --git a/include/swift/AST/Type.h b/include/swift/AST/Type.h
index 453fab4..f0408a7 100644
--- a/include/swift/AST/Type.h
+++ b/include/swift/AST/Type.h
@@ -356,11 +356,11 @@
/// join of D and A (or D and B, or D and C) because there is no common
/// superclass. One would have to jump to an existential (e.g., \c AnyObject)
/// to find a common type.
- ///
- /// \returns the join of the two types, if there is a concrete type that can
- /// express the join, or a null type if the only join would be a more-general
- /// existential type (e.g., \c Any).
- static Type join(Type type1, Type type2);
+ ///
+ /// \returns the join of the two types, if there is a concrete type
+ /// that can express the join, or Any if the only join would be a
+ /// more-general existential type
+ static Type join(Type first, Type second);
private:
// Direct comparison is disabled for types, because they may not be canonical.
diff --git a/include/swift/Reflection/MetadataSource.h b/include/swift/Reflection/MetadataSource.h
index 7b234b0..5fa9706 100644
--- a/include/swift/Reflection/MetadataSource.h
+++ b/include/swift/Reflection/MetadataSource.h
@@ -147,25 +147,6 @@
}
template <typename Allocator>
- static const MetadataSource*
- decodeParent(Allocator &A,
- std::string::const_iterator &it,
- const std::string::const_iterator &end) {
- if (it == end || *it != 'P')
- return nullptr;
-
- ++it;
- auto Child = decode(A, it, end);
- if (!Child)
- return nullptr;
-
- if (it == end || *it != '_')
- return nullptr;
-
- return A.createParent(Child);
- }
-
- template <typename Allocator>
static const MetadataSource *decode(Allocator &A,
std::string::const_iterator &it,
const std::string::const_iterator &end) {
@@ -180,8 +161,6 @@
return decodeMetadataCapture(A, it, end);
case 'G':
return decodeGenericArgument(A, it, end);
- case 'P':
- return decodeParent(A, it, end);
case 'S':
++it;
return A.createSelf();
@@ -318,29 +297,6 @@
}
};
-/// Metadata gotten through the parent of a nominal type's metadata.
-class ParentMetadataSource final : public MetadataSource {
- const MetadataSource *Child;
-public:
- ParentMetadataSource(const MetadataSource *Child)
- : MetadataSource(MetadataSourceKind::Parent),
- Child(Child) {}
-
- template <typename Allocator>
- static const ParentMetadataSource*
- create(Allocator &A, const MetadataSource *Child) {
- return A.template make_source<ParentMetadataSource>(Child);
- }
-
- const MetadataSource *getChild() const {
- return Child;
- }
-
- static bool classof(const MetadataSource *MS) {
- return MS->getKind() == MetadataSourceKind::Parent;
- }
-};
-
/// A source of metadata from the Self metadata parameter passed via
/// a witness_method convention function.
class SelfMetadataSource final : public MetadataSource {
diff --git a/include/swift/Reflection/MetadataSourceBuilder.h b/include/swift/Reflection/MetadataSourceBuilder.h
index 2df9d85..3117b10 100644
--- a/include/swift/Reflection/MetadataSourceBuilder.h
+++ b/include/swift/Reflection/MetadataSourceBuilder.h
@@ -59,11 +59,6 @@
return ClosureBindingMetadataSource::create(*this, Index);
}
- const ParentMetadataSource *
- createParent(const MetadataSource *Child) {
- return ParentMetadataSource::create(*this, Child);
- }
-
const SelfMetadataSource *
createSelf() {
return SelfMetadataSource::create(*this);
diff --git a/include/swift/Reflection/MetadataSources.def b/include/swift/Reflection/MetadataSources.def
index 60fe4ef..b4dfe28 100644
--- a/include/swift/Reflection/MetadataSources.def
+++ b/include/swift/Reflection/MetadataSources.def
@@ -20,6 +20,5 @@
METADATA_SOURCE(ReferenceCapture, MetadataSource)
METADATA_SOURCE(MetadataCapture, MetadataSource)
METADATA_SOURCE(GenericArgument, MetadataSource)
-METADATA_SOURCE(Parent, MetadataSource)
METADATA_SOURCE(Self, MetadataSource)
METADATA_SOURCE(SelfWitnessTable, MetadataSource)
diff --git a/include/swift/Reflection/ReflectionContext.h b/include/swift/Reflection/ReflectionContext.h
index bc7a5c3..920c1d2 100644
--- a/include/swift/Reflection/ReflectionContext.h
+++ b/include/swift/Reflection/ReflectionContext.h
@@ -50,7 +50,6 @@
using super::getBuilder;
using super::readIsaMask;
using super::readTypeFromMetadata;
- using super::readParentFromMetadata;
using super::readGenericArgFromMetadata;
using super::readMetadataFromInstance;
using typename super::StoredPointer;
@@ -460,10 +459,6 @@
auto Base = cast<GenericArgumentMetadataSource>(MS)->getSource();
return isMetadataSourceReady(Base, Builder);
}
- case MetadataSourceKind::Parent: {
- auto Base = cast<ParentMetadataSource>(MS)->getChild();
- return isMetadataSourceReady(Base, Builder);
- }
case MetadataSourceKind::Self:
case MetadataSourceKind::SelfWitnessTable:
return true;
@@ -548,19 +543,6 @@
return Arg;
}
- case MetadataSourceKind::Parent: {
- auto Base = readMetadataSource(Context,
- cast<ParentMetadataSource>(MS)->getChild(),
- Builder);
- if (!Base.first)
- break;
-
- auto Parent = readParentFromMetadata(Base.second);
- if (!Parent.first)
- break;
-
- return Parent;
- }
case MetadataSourceKind::Self:
case MetadataSourceKind::SelfWitnessTable:
break;
diff --git a/include/swift/Reflection/TypeRefBuilder.h b/include/swift/Reflection/TypeRefBuilder.h
index 2be00c3..b339432 100644
--- a/include/swift/Reflection/TypeRefBuilder.h
+++ b/include/swift/Reflection/TypeRefBuilder.h
@@ -178,6 +178,11 @@
}
const NominalTypeRef *createNominalType(
+ const Optional<std::string> &mangledName) {
+ return NominalTypeRef::create(*this, *mangledName, nullptr);
+ }
+
+ const NominalTypeRef *createNominalType(
const Optional<std::string> &mangledName,
const TypeRef *parent) {
return NominalTypeRef::create(*this, *mangledName, parent);
@@ -185,6 +190,12 @@
const BoundGenericTypeRef *
createBoundGenericType(const Optional<std::string> &mangledName,
+ const std::vector<const TypeRef *> &args) {
+ return BoundGenericTypeRef::create(*this, *mangledName, args, nullptr);
+ }
+
+ const BoundGenericTypeRef *
+ createBoundGenericType(const Optional<std::string> &mangledName,
const std::vector<const TypeRef *> &args,
const TypeRef *parent) {
return BoundGenericTypeRef::create(*this, *mangledName, args, parent);
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index 396e964..d26bc9f 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -934,33 +934,6 @@
swift_runtime_unreachable("Unhandled IsaEncodingKind in switch.");
}
- /// Read the parent type metadata from a nested nominal type metadata.
- std::pair<bool, StoredPointer>
- readParentFromMetadata(StoredPointer metadata) {
- auto Meta = readMetadata(metadata);
- if (!Meta)
- return std::make_pair(false, 0);
-
- auto descriptorAddress = readAddressOfNominalTypeDescriptor(Meta);
- if (!descriptorAddress)
- return std::make_pair(false, 0);
-
- // Read the nominal type descriptor.
- auto descriptor = readNominalTypeDescriptor(descriptorAddress);
- if (!descriptor)
- return std::make_pair(false, 0);
-
- // Read the parent type if the type has one.
- if (descriptor->GenericParams.Flags.hasParent()) {
- StoredPointer parentAddress = getNominalParent(Meta, descriptor);
- if (!parentAddress)
- return std::make_pair(false, 0);
- return std::make_pair(true, parentAddress);
- }
-
- return std::make_pair(false, 0);
- }
-
/// Read a single generic type argument from a bound generic type
/// metadata.
std::pair<bool, StoredPointer>
@@ -1308,32 +1281,6 @@
return OwnedProtocolDescriptorRef(Casted);
}
- StoredPointer getNominalParent(MetadataRef metadata,
- NominalTypeDescriptorRef descriptor) {
- // If this is metadata for some sort of value type, the parent type
- // is at a fixed offset.
- if (auto valueMetadata = dyn_cast<TargetValueMetadata<Runtime>>(metadata)) {
- return valueMetadata->Parent;
- }
-
- // If this is metadata for a class type, the parent type for the
- // most-derived class is at an offset stored in the most-derived
- // nominal type descriptor.
- if (auto classMetadata = dyn_cast<TargetClassMetadata<Runtime>>(metadata)) {
- // If it does, it's immediately before the generic parameters.
- auto offsetToParent
- = sizeof(StoredPointer) * (descriptor->GenericParams.Offset - 1);
- RemoteAddress addressOfParent(metadata.getAddress() + offsetToParent);
- StoredPointer parentAddress;
- if (!Reader->readInteger(addressOfParent, &parentAddress))
- return StoredPointer();
- return parentAddress;
- }
-
- // Otherwise, we don't know how to access its parent. This is a failure.
- return StoredPointer();
- }
-
std::vector<BuiltType>
getGenericSubst(MetadataRef metadata, NominalTypeDescriptorRef descriptor) {
std::vector<BuiltType> substitutions;
@@ -1387,23 +1334,13 @@
if (!typeDecl)
return BuiltType();
- // Read the parent type if the type has one.
- BuiltType parent = BuiltType();
- if (descriptor->GenericParams.Flags.hasParent()) {
- StoredPointer parentAddress = getNominalParent(metadata, descriptor);
- if (!parentAddress)
- return BuiltType();
- parent = readTypeFromMetadata(parentAddress);
- if (!parent) return BuiltType();
- }
-
BuiltType nominal;
if (descriptor->GenericParams.NumPrimaryParams) {
auto args = getGenericSubst(metadata, descriptor);
if (args.empty()) return BuiltType();
- nominal = Builder.createBoundGenericType(typeDecl, args, parent);
+ nominal = Builder.createBoundGenericType(typeDecl, args);
} else {
- nominal = Builder.createNominalType(typeDecl, parent);
+ nominal = Builder.createNominalType(typeDecl);
}
if (!nominal) return BuiltType();
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index 87ccf64..5207f0c 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -1102,6 +1102,13 @@
};
using HeapMetadata = TargetHeapMetadata<InProcess>;
+struct GenericContextDescriptor {
+ /// The number of primary type parameters. This is always less than or equal
+ /// to NumGenericRequirements; it counts only the type parameters
+ /// and not any required witness tables.
+ uint32_t NumPrimaryParams;
+};
+
/// Header for a generic parameter descriptor. This is a variable-sized
/// structure that describes how to find and parse a generic parameter vector
/// within the type metadata for an instance of a nominal type.
@@ -1109,8 +1116,7 @@
/// The offset to the first generic argument from the start of
/// metadata record.
///
- /// This is meaningful if either NumGenericRequirements is nonzero or
- /// (for classes) if Flags.hasParent() is true.
+ /// This is meaningful if NumGenericRequirements is nonzero.
uint32_t Offset;
/// The amount of generic requirement data in the metadata record, in
@@ -1126,6 +1132,10 @@
/// and not any required witness tables.
uint32_t NumPrimaryParams;
+ /// The number of types that this type is nested inside of, including itself
+ /// (so this value is at least 1).
+ uint16_t NestingDepth;
+
/// Flags for this generic parameter descriptor.
GenericParameterDescriptorFlags Flags;
@@ -1135,7 +1145,12 @@
/// True if the nominal type is generic in any way.
bool isGeneric() const {
- return hasGenericRequirements() || Flags.hasGenericParent();
+ return hasGenericRequirements();
+ }
+
+ GenericContextDescriptor getContext(unsigned depth) const {
+ assert(depth < NestingDepth);
+ return ((const GenericContextDescriptor *)(this + 1))[depth];
}
// TODO: add meaningful descriptions of the generic requirements.
@@ -1316,12 +1331,13 @@
!GenericParams.Flags.hasVTable())
return nullptr;
- auto asWords = reinterpret_cast<const void * const*>(this + 1);
+ auto asWords = reinterpret_cast<const uint32_t *>(this + 1);
// TODO: Once we emit reflective descriptions of generic requirements,
// skip the right number of words here.
- return reinterpret_cast<const VTableDescriptor *>(asWords);
+ return reinterpret_cast<const VTableDescriptor *>(asWords
+ + GenericParams.NestingDepth);
}
/// The generic parameter descriptor header. This describes how to find and
@@ -1567,17 +1583,6 @@
return getter(this);
}
- /// Return the parent type for a given level in the class hierarchy, or
- /// null if that level does not have a parent type.
- const TargetMetadata<Runtime> *
- getParentType(const TargetNominalTypeDescriptor<Runtime> *theClass) const {
- if (!theClass->GenericParams.Flags.hasParent())
- return nullptr;
-
- auto metadataAsWords = reinterpret_cast<const Metadata * const *>(this);
- return metadataAsWords[theClass->GenericParams.Offset - 1];
- }
-
StoredPointer offsetToDescriptorOffset() const {
return offsetof(TargetClassMetadata<Runtime>, Description);
}
@@ -1745,22 +1750,15 @@
using StoredPointer = typename Runtime::StoredPointer;
TargetValueMetadata(MetadataKind Kind,
ConstTargetMetadataPointer<Runtime, TargetNominalTypeDescriptor>
- description,
- ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> parent)
+ description)
: TargetMetadata<Runtime>(Kind),
- Description(description),
- Parent(parent)
+ Description(description)
{}
/// An out-of-line description of the type.
ConstTargetFarRelativeDirectPointer<Runtime, TargetNominalTypeDescriptor>
Description;
- /// The parent type of this member type, or null if this is not a
- /// member type. It's acceptable to make this a direct pointer because
- /// parent types are relatively uncommon.
- TargetPointer<Runtime, const TargetMetadata<Runtime>> Parent;
-
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Struct
|| metadata->getKind() == MetadataKind::Enum
@@ -1785,11 +1783,6 @@
StoredPointer offsetToDescriptorOffset() const {
return offsetof(TargetValueMetadata<Runtime>, Description);
}
-
- StoredPointer offsetToParentOffset() const {
- return offsetof(TargetValueMetadata<Runtime>, Parent);
- }
-
};
using ValueMetadata = TargetValueMetadata<InProcess>;
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index 5fea838..d716522 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -524,6 +524,8 @@
// Redeclare because lldb currently doesn't know about using-declarations
void dump() const;
+ void operator delete(void *Ptr, size_t) SWIFT_DELETE_OPERATOR_DELETED
+
ValueKind getValueKind() const {
return ValueBase::getKind();
}
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 5bb5519..7917da8 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -4591,7 +4591,7 @@
GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
builder.addRequirement(requirement, source, nullptr);
- CanGenericSignature genericSig(std::move(builder).computeGenericSignature(SourceLoc()));
+ CanGenericSignature genericSig(builder.computeGenericSignature(SourceLoc()));
auto result = Impl.ExistentialSignatures.insert(
std::make_pair(existential, genericSig));
diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp
index f9af2d2..a7c473a 100644
--- a/lib/AST/Builtins.cpp
+++ b/lib/AST/Builtins.cpp
@@ -491,8 +491,7 @@
Builder.addGenericParameter(gp);
}
- auto GenericSig =
- std::move(Builder).computeGenericSignature(SourceLoc());
+ auto GenericSig = Builder.computeGenericSignature(SourceLoc());
GenericEnv = GenericSig->createGenericEnvironment(*ctx.TheBuiltinModule);
}
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index e7e7f55..bcb698a 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -3419,8 +3419,7 @@
nullptr);
// Compute and record the signature.
- auto requirementSig =
- std::move(builder).computeGenericSignature(SourceLoc());
+ auto requirementSig = builder.computeGenericSignature(SourceLoc());
RequirementSignature = requirementSig->getRequirements().data();
assert(RequirementSignature != nullptr);
NumRequirementsInSignature = requirementSig->getRequirements().size();
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index 32f8d63..f0b85ea 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -76,10 +76,6 @@
"# of hits in the archetype anchor cache");
STATISTIC(NumArchetypeAnchorCacheMisses,
"# of misses in the archetype anchor cache");
-STATISTIC(NumNestedTypeCacheHits,
- "# of hits in the equivalence class nested type cache");
-STATISTIC(NumNestedTypeCacheMisses,
- "# of misses in the equivalence class nested type cache");
STATISTIC(NumProcessDelayedRequirements,
"# of times we process delayed requirements");
STATISTIC(NumProcessDelayedRequirementsUnchanged,
@@ -1558,159 +1554,6 @@
return false;
}
-/// Compare two associated types.
-static int compareAssociatedTypes(AssociatedTypeDecl *assocType1,
- AssociatedTypeDecl *assocType2) {
- // - by name.
- if (int result = assocType1->getName().str().compare(
- assocType2->getName().str()))
- return result;
-
- // - by protocol, so t_n_m.`P.T` < t_n_m.`Q.T` (given P < Q)
- auto proto1 = assocType1->getProtocol();
- auto proto2 = assocType2->getProtocol();
- if (int compareProtocols = ProtocolType::compareProtocols(&proto1, &proto2))
- return compareProtocols;
-
- // Error case: if we have two associated types with the same name in the
- // same protocol, just tie-break based on address.
- if (assocType1 != assocType2)
- return assocType1 < assocType2 ? -1 : +1;
-
- return 0;
-}
-
-TypeDecl *EquivalenceClass::lookupNestedType(
- Identifier name,
- SmallVectorImpl<TypeDecl *> *otherConcreteTypes) {
- // Populates the result structures from the given cache entry.
- auto populateResult = [&](const CachedNestedType &cache) -> TypeDecl * {
- if (otherConcreteTypes)
- otherConcreteTypes->clear();
-
- // If there aren't any types in the cache, we're done.
- if (cache.types.empty()) return nullptr;
-
- // The first type in the cache is always the final result.
- // Collect the rest in the concrete-declarations list, if needed.
- if (otherConcreteTypes) {
- for (auto type : ArrayRef<TypeDecl *>(cache.types).slice(1)) {
- otherConcreteTypes->push_back(type);
- }
- }
-
- return cache.types.front();
- };
-
- // If we have a cached value that is up-to-date, use that.
- auto cached = nestedTypeNameCache.find(name);
- if (cached != nestedTypeNameCache.end() &&
- cached->second.numConformancesPresent == conformsTo.size() &&
- (!superclass ||
- cached->second.superclassPresent == superclass->getCanonicalType())) {
- ++NumNestedTypeCacheHits;
- return populateResult(cached->second);
- }
-
- // Cache miss; go compute the result.
- ++NumNestedTypeCacheMisses;
-
- // Look for types with the given name in protocols that we know about.
- AssociatedTypeDecl *bestAssocType = nullptr;
- SmallVector<TypeDecl *, 4> concreteDecls;
- for (const auto &conforms : conformsTo) {
- ProtocolDecl *proto = conforms.first;
-
- // Look for an associated type and/or concrete type with this name.
- for (auto member : proto->lookupDirect(name,
- /*ignoreNewExtensions=*/true)) {
- // If this is an associated type, record whether it is the best
- // associated type we've seen thus far.
- if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
- if (!bestAssocType ||
- compareAssociatedTypes(assocType, bestAssocType) < 0)
- bestAssocType = assocType;
-
- continue;
- }
-
- // If this is another type declaration, determine whether we should
- // record it.
- if (auto type = dyn_cast<TypeDecl>(member)) {
- // FIXME: Filter out type declarations that aren't in the same
- // module as the protocol itself. This is an unprincipled hack, but
- // provides consistent lookup semantics for the generic signature
- // builder in all contents.
- if (type->getDeclContext()->getParentModule()
- != proto->getParentModule())
- continue;
-
- // Resolve the signature of this type.
- if (!type->hasInterfaceType()) {
- type->getASTContext().getLazyResolver()->resolveDeclSignature(type);
- if (!type->hasInterfaceType())
- continue;
- }
-
- concreteDecls.push_back(type);
- continue;
- }
- }
- }
-
- // If we haven't found anything yet but have a superclass, look for a type
- // in the superclass.
- // FIXME: Shouldn't we always look in the superclass?
- if (!bestAssocType && concreteDecls.empty() && superclass) {
- if (auto classDecl = superclass->getClassOrBoundGenericClass()) {
- SmallVector<ValueDecl *, 2> superclassMembers;
- classDecl->getParentModule()->lookupQualified(
- superclass, name,
- NL_QualifiedDefault | NL_OnlyTypes | NL_ProtocolMembers, nullptr,
- superclassMembers);
- for (auto member : superclassMembers) {
- if (auto type = dyn_cast<TypeDecl>(member)) {
- // Resolve the signature of this type.
- if (!type->hasInterfaceType()) {
- type->getASTContext().getLazyResolver()->resolveDeclSignature(type);
- if (!type->hasInterfaceType())
- continue;
- }
-
- concreteDecls.push_back(type);
- }
- }
- }
- }
-
- // Form the new cache entry.
- CachedNestedType entry;
- entry.numConformancesPresent = conformsTo.size();
- entry.superclassPresent =
- superclass ? superclass->getCanonicalType() : CanType();
- if (bestAssocType) {
- entry.types.push_back(bestAssocType);
- entry.types.insert(entry.types.end(),
- concreteDecls.begin(), concreteDecls.end());
- } else if (!concreteDecls.empty()) {
- // Find the best concrete type.
- auto bestConcreteTypeIter =
- std::min_element(concreteDecls.begin(), concreteDecls.end(),
- [](TypeDecl *type1, TypeDecl *type2) {
- return TypeDecl::compare(type1, type2) < 0;
- });
-
- // Put the best concrete type first; the rest will follow.
- entry.types.push_back(*bestConcreteTypeIter);
- entry.types.insert(entry.types.end(),
- concreteDecls.begin(), bestConcreteTypeIter);
- entry.types.insert(entry.types.end(),
- bestConcreteTypeIter + 1, concreteDecls.end());
- }
-
- return populateResult((nestedTypeNameCache[name] = std::move(entry)));
-}
-
void EquivalenceClass::dump(llvm::raw_ostream &out) const {
out << "Equivalence class represented by "
<< members.front()->getRepresentative()->getDebugName() << ":\n";
@@ -2118,6 +1961,28 @@
return result;
}
+/// Compare two associated types.
+static int compareAssociatedTypes(AssociatedTypeDecl *assocType1,
+ AssociatedTypeDecl *assocType2) {
+ // - by name.
+ if (int result = assocType1->getName().str().compare(
+ assocType2->getName().str()))
+ return result;
+
+ // - by protocol, so t_n_m.`P.T` < t_n_m.`Q.T` (given P < Q)
+ auto proto1 = assocType1->getProtocol();
+ auto proto2 = assocType2->getProtocol();
+ if (int compareProtocols = ProtocolType::compareProtocols(&proto1, &proto2))
+ return compareProtocols;
+
+ // Error case: if we have two associated types with the same name in the
+ // same protocol, just tie-break based on address.
+ if (assocType1 != assocType2)
+ return assocType1 < assocType2 ? -1 : +1;
+
+ return 0;
+}
+
/// Whether there are any concrete type declarations in the potential archetype.
static bool hasConcreteDecls(const PotentialArchetype *pa) {
auto parent = pa->getParent();
@@ -2345,9 +2210,16 @@
}
PotentialArchetype *PotentialArchetype::getNestedType(
- TypeDecl *type,
+ AssociatedTypeDecl *assocType,
GenericSignatureBuilder &builder) {
- return updateNestedTypeForConformance(type,
+ return updateNestedTypeForConformance(assocType,
+ ArchetypeResolutionKind::WellFormed);
+}
+
+PotentialArchetype *PotentialArchetype::getNestedType(
+ TypeDecl *getConcreteTypeDecl,
+ GenericSignatureBuilder &builder) {
+ return updateNestedTypeForConformance(getConcreteTypeDecl,
ArchetypeResolutionKind::WellFormed);
}
@@ -2355,21 +2227,94 @@
Identifier name,
GenericSignatureBuilder &builder,
ArchetypeResolutionKind kind) {
+ // Look for the best associated type or concrete type within the protocols
+ // we know about.
+ AssociatedTypeDecl *bestAssocType = nullptr;
+ TypeDecl *bestConcreteDecl = nullptr;
SmallVector<TypeDecl *, 4> concreteDecls;
- auto bestType =
- getOrCreateEquivalenceClass()->lookupNestedType(name, &concreteDecls);
+ auto rep = getRepresentative();
+ for (auto proto : rep->getConformsTo()) {
+ // Look for an associated type and/or concrete type with this name.
+ AssociatedTypeDecl *assocType = nullptr;
+ TypeDecl *concreteDecl = nullptr;
+ for (auto member : proto->lookupDirect(name,
+ /*ignoreNewExtensions=*/true)) {
+ if (!assocType)
+ assocType = dyn_cast<AssociatedTypeDecl>(member);
- // We didn't find any type with this name.
- if (!bestType) return nullptr;
+ // FIXME: Filter out type declarations that aren't in the protocol itself?
+ if (!concreteDecl && !isa<AssociatedTypeDecl>(member)) {
+ if (!member->hasInterfaceType())
+ builder.getLazyResolver()->resolveDeclSignature(member);
+ if (member->hasInterfaceType())
+ concreteDecl = dyn_cast<TypeDecl>(member);
+ }
+ }
- // Resolve the nested type.
- auto resultPA = updateNestedTypeForConformance(bestType, kind);
+ if (assocType &&
+ (!bestAssocType ||
+ compareAssociatedTypes(assocType, bestAssocType) < 0))
+ bestAssocType = assocType;
+
+ if (concreteDecl) {
+ // Record every concrete type.
+ concreteDecls.push_back(concreteDecl);
+
+ // Track the best concrete type.
+ if (!bestConcreteDecl ||
+ TypeDecl::compare(concreteDecl, bestConcreteDecl) < 0)
+ bestConcreteDecl = concreteDecl;
+ }
+ }
+
+ // If we found an associated type, use it.
+ PotentialArchetype *resultPA = nullptr;
+ if (bestAssocType) {
+ resultPA = updateNestedTypeForConformance(bestAssocType, kind);
+ }
+
+ // If we have an associated type, drop any concrete decls that aren't in
+ // the same module as the protocol.
+ // FIXME: This is an unprincipled hack for an unprincipled feature.
+ concreteDecls.erase(
+ std::remove_if(concreteDecls.begin(), concreteDecls.end(),
+ [&](TypeDecl *concreteDecl) {
+ return concreteDecl->getDeclContext()->getParentModule() !=
+ concreteDecl->getDeclContext()
+ ->getAsNominalTypeOrNominalTypeExtensionContext()->getParentModule();
+ }),
+ concreteDecls.end());
+
+ // If we haven't found anything yet but have a superclass, look for a type
+ // in the superclass.
+ if (!resultPA && concreteDecls.empty()) {
+ if (auto superclass = getSuperclass()) {
+ if (auto classDecl = superclass->getClassOrBoundGenericClass()) {
+ SmallVector<ValueDecl *, 2> superclassMembers;
+ classDecl->getParentModule()->lookupQualified(superclass, name, NL_QualifiedDefault | NL_OnlyTypes | NL_ProtocolMembers, nullptr,
+ superclassMembers);
+ for (auto member : superclassMembers) {
+ if (auto concreteDecl = dyn_cast<TypeDecl>(member)) {
+ // Track the best concrete type.
+ if (!bestConcreteDecl ||
+ TypeDecl::compare(concreteDecl, bestConcreteDecl) < 0)
+ bestConcreteDecl = concreteDecl;
+
+ concreteDecls.push_back(concreteDecl);
+ }
+ }
+ }
+ }
+ }
// Update for all of the concrete decls with this name, which will introduce
// various same-type constraints.
for (auto concreteDecl : concreteDecls) {
- (void)updateNestedTypeForConformance(concreteDecl,
- ArchetypeResolutionKind::WellFormed);
+ auto concreteDeclPA = updateNestedTypeForConformance(
+ concreteDecl,
+ ArchetypeResolutionKind::WellFormed);
+ if (!resultPA && concreteDecl == bestConcreteDecl)
+ resultPA = concreteDeclPA;
}
return resultPA;
@@ -2380,22 +2325,43 @@
Identifier name,
ProtocolDecl *proto,
ArchetypeResolutionKind kind) {
- // Lookup the best type for this name.
- auto bestType =
- getOrCreateEquivalenceClass()->lookupNestedType(name, nullptr);
- if (!bestType) return nullptr;
+ /// Determine whether there is an associated type or concrete type with this
+ /// name in this protocol. If not, there's nothing to do.
+ AssociatedTypeDecl *assocType = nullptr;
+ TypeDecl *concreteDecl = nullptr;
+ for (auto member : proto->lookupDirect(name, /*ignoreNewExtensions=*/true)) {
+ if (!assocType)
+ assocType = dyn_cast<AssociatedTypeDecl>(member);
- // Form the potential archetype.
- return updateNestedTypeForConformance(bestType, kind);
+ // FIXME: Filter out concrete types that aren't in the protocol itself?
+ if (!concreteDecl && !isa<AssociatedTypeDecl>(member)) {
+ if (!member->hasInterfaceType())
+ proto->getASTContext().getLazyResolver()->resolveDeclSignature(member);
+ if (member->hasInterfaceType())
+ concreteDecl = dyn_cast<TypeDecl>(member);
+ }
+ }
+
+ // There is no associated type or concrete type with this name in this
+ // protocol
+ if (!assocType && !concreteDecl)
+ return nullptr;
+
+ // If we had both an associated type and a concrete type, ignore the latter.
+ // This is for ill-formed code.
+ if (assocType)
+ return updateNestedTypeForConformance(assocType, kind);
+
+ return updateNestedTypeForConformance(concreteDecl, kind);
}
PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
- TypeDecl *type,
- ArchetypeResolutionKind kind) {
- if (!type) return nullptr;
-
- AssociatedTypeDecl *assocType = dyn_cast<AssociatedTypeDecl>(type);
- TypeDecl *concreteDecl = assocType ? nullptr : type;
+ PointerUnion<AssociatedTypeDecl *, TypeDecl *> type,
+ ArchetypeResolutionKind kind) {
+ auto *assocType = type.dyn_cast<AssociatedTypeDecl *>();
+ auto *concreteDecl = type.dyn_cast<TypeDecl *>();
+ if (!assocType && !concreteDecl)
+ return nullptr;
// If we were asked for a complete, well-formed archetype, make sure we
// process delayed requirements if anything changed.
@@ -3667,8 +3633,13 @@
auto parentRepPA = parentPA->getRepresentative();
if (parentPA == parentRepPA) return;
- PotentialArchetype *existingPA =
- parentRepPA->getNestedType(nestedPA->getResolvedType(), *this);
+ PotentialArchetype *existingPA;
+ if (auto assocType = nestedPA->getResolvedAssociatedType()) {
+ existingPA = parentRepPA->getNestedType(assocType, *this);
+ } else {
+ existingPA = parentRepPA->getNestedType(nestedPA->getConcreteTypeDecl(),
+ *this);
+ }
auto sameNamedSource =
FloatingRequirementSource::forNestedTypeNameMatch(
@@ -3922,10 +3893,8 @@
UnresolvedHandlingKind unresolvedHandling) {
return addSameTypeRequirement(paOrT1, paOrT2, source, unresolvedHandling,
[&](Type type1, Type type2) {
- if (source.getLoc().isValid()) {
- Diags.diagnose(source.getLoc(), diag::requires_same_concrete_type,
- type1, type2);
- }
+ Diags.diagnose(source.getLoc(), diag::requires_same_concrete_type,
+ type1, type2);
});
}
@@ -4201,10 +4170,9 @@
firstType, secondType, source,
UnresolvedHandlingKind::GenerateConstraints,
[&](Type type1, Type type2) {
- if (source.getLoc().isValid()) {
+ if (source.getLoc().isValid())
Diags.diagnose(source.getLoc(), diag::requires_same_concrete_type,
type1, type2);
- }
});
}
}
@@ -6325,23 +6293,21 @@
});
}
-GenericSignature *GenericSignatureBuilder::computeGenericSignature(
- SourceLoc loc,
- bool allowConcreteGenericParams) && {
- // Finalize the builder, producing any necessary diagnostics.
- finalize(loc, Impl->GenericParams, allowConcreteGenericParams);
+GenericSignature *GenericSignatureBuilder::getGenericSignature() {
+ assert(Impl->finalized && "Must finalize builder first");
// Collect the requirements placed on the generic parameter types.
SmallVector<Requirement, 4> requirements;
collectRequirements(*this, Impl->GenericParams, requirements);
- // Form the generic signature.
auto sig = GenericSignature::get(Impl->GenericParams, requirements);
-
- // Wipe out the internal state, ensuring that nobody uses this builder for
- // anything more.
- Impl.reset();
-
return sig;
}
+GenericSignature *GenericSignatureBuilder::computeGenericSignature(
+ SourceLoc loc,
+ bool allowConcreteGenericParams) {
+ finalize(loc, Impl->GenericParams, allowConcreteGenericParams);
+ return getGenericSignature();
+}
+
diff --git a/lib/AST/TypeJoinMeet.cpp b/lib/AST/TypeJoinMeet.cpp
index 3620c4a..ac5284a 100644
--- a/lib/AST/TypeJoinMeet.cpp
+++ b/lib/AST/TypeJoinMeet.cpp
@@ -15,9 +15,9 @@
//
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTContext.h"
+#include "swift/AST/CanTypeVisitor.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Type.h"
-#include "swift/AST/TypeVisitor.h"
#include "swift/AST/Types.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace swift;
@@ -26,43 +26,33 @@
// used for optimizing away extra exploratory work in the constraint
// solver. It should eventually encompass all of the subtyping rules
// of the language.
-struct TypeJoin : TypeVisitor<TypeJoin, Type> {
- Type First;
+struct TypeJoin : CanTypeVisitor<TypeJoin, CanType> {
+ CanType First;
- TypeJoin(Type First) : First(First) {
+ TypeJoin(CanType First) : First(First) {
assert(First && "Unexpected null type!");
}
- static Type getSuperclassJoin(Type first, Type second);
+ static CanType getSuperclassJoin(CanType first, CanType second);
- Type visitClassType(Type second);
- Type visitBoundGenericClassType(Type second);
- Type visitArchetypeType(Type second);
- Type visitDynamicSelfType(Type second);
- Type visitMetatypeType(Type second);
- Type visitExistentialMetatypeType(Type second);
- Type visitBoundGenericEnumType(Type second);
+ CanType visitClassType(CanType second);
+ CanType visitBoundGenericClassType(CanType second);
+ CanType visitArchetypeType(CanType second);
+ CanType visitDynamicSelfType(CanType second);
+ CanType visitMetatypeType(CanType second);
+ CanType visitExistentialMetatypeType(CanType second);
+ CanType visitBoundGenericEnumType(CanType second);
- Type visitOptionalType(Type second);
+ CanType visitOptionalType(CanType second);
- Type visitType(Type second) {
+ CanType visitType(CanType second) {
// FIXME: Implement all the visitors.
// llvm_unreachable("Unimplemented type visitor!");
return First->getASTContext().TheAnyType;
}
public:
- static Type join(Type first, Type second) {
- if (!first || !second) {
- if (first)
- return ErrorType::get(first->getASTContext());
-
- if (second)
- return ErrorType::get(second->getASTContext());
-
- return Type();
- }
-
+ static CanType join(CanType first, CanType second) {
assert(!first->hasTypeVariable() && !second->hasTypeVariable() &&
"Cannot compute join of types involving type variables");
@@ -72,7 +62,7 @@
"Expected simple type!");
// If the types are equivalent, the join is obvious.
- if (first->isEqual(second))
+ if (first == second)
return first;
// Until we handle all the combinations of joins, we need to make
@@ -85,23 +75,19 @@
}
};
-Type TypeJoin::getSuperclassJoin(Type first, Type second) {
- if (!first || !second)
- return TypeJoin::join(first, second);
-
+CanType TypeJoin::getSuperclassJoin(CanType first, CanType second) {
if (!first->mayHaveSuperclass() || !second->mayHaveSuperclass())
return first->getASTContext().TheAnyType;
/// Walk the superclasses of `first` looking for `second`. Record them
/// for our second step.
llvm::SmallPtrSet<CanType, 8> superclassesOfFirst;
- CanType canSecond = second->getCanonicalType();
for (Type super = first; super; super = super->getSuperclass()) {
- CanType canSuper = super->getCanonicalType();
+ auto canSuper = super->getCanonicalType();
// If we have found the second type, we're done.
- if (canSuper == canSecond)
- return super;
+ if (canSuper == second)
+ return canSuper;
superclassesOfFirst.insert(canSuper);
}
@@ -109,94 +95,104 @@
// Look through the superclasses of second to determine if any were also
// superclasses of first.
for (Type super = second; super; super = super->getSuperclass()) {
- CanType canSuper = super->getCanonicalType();
+ auto canSuper = super->getCanonicalType();
// If we found the first type, we're done.
if (superclassesOfFirst.count(canSuper))
- return super;
+ return canSuper;
}
// There is no common superclass; we're done.
return first->getASTContext().TheAnyType;
}
-Type TypeJoin::visitClassType(Type second) {
+CanType TypeJoin::visitClassType(CanType second) {
return getSuperclassJoin(First, second);
}
-Type TypeJoin::visitBoundGenericClassType(Type second) {
+CanType TypeJoin::visitBoundGenericClassType(CanType second) {
return getSuperclassJoin(First, second);
}
-Type TypeJoin::visitArchetypeType(Type second) {
+CanType TypeJoin::visitArchetypeType(CanType second) {
return getSuperclassJoin(First, second);
}
-Type TypeJoin::visitDynamicSelfType(Type second) {
+CanType TypeJoin::visitDynamicSelfType(CanType second) {
return getSuperclassJoin(First, second);
}
-Type TypeJoin::visitMetatypeType(Type second) {
+CanType TypeJoin::visitMetatypeType(CanType second) {
if (First->getKind() != second->getKind())
return First->getASTContext().TheAnyType;
- auto firstInstance = First->castTo<AnyMetatypeType>()->getInstanceType();
- auto secondInstance = second->castTo<AnyMetatypeType>()->getInstanceType();
+ auto firstInstance =
+ First->castTo<AnyMetatypeType>()->getInstanceType()->getCanonicalType();
+ auto secondInstance =
+ second->castTo<AnyMetatypeType>()->getInstanceType()->getCanonicalType();
auto joinInstance = join(firstInstance, secondInstance);
if (!joinInstance)
return First->getASTContext().TheAnyType;
- return MetatypeType::get(joinInstance);
+ return MetatypeType::get(joinInstance)->getCanonicalType();
}
-Type TypeJoin::visitExistentialMetatypeType(Type second) {
+CanType TypeJoin::visitExistentialMetatypeType(CanType second) {
if (First->getKind() != second->getKind())
return First->getASTContext().TheAnyType;
- auto firstInstance = First->castTo<AnyMetatypeType>()->getInstanceType();
- auto secondInstance = second->castTo<AnyMetatypeType>()->getInstanceType();
+ auto firstInstance =
+ First->castTo<AnyMetatypeType>()->getInstanceType()->getCanonicalType();
+ auto secondInstance =
+ second->castTo<AnyMetatypeType>()->getInstanceType()->getCanonicalType();
auto joinInstance = join(firstInstance, secondInstance);
if (!joinInstance)
return First->getASTContext().TheAnyType;
- return ExistentialMetatypeType::get(joinInstance);
+ return ExistentialMetatypeType::get(joinInstance)->getCanonicalType();
}
-Type TypeJoin::visitBoundGenericEnumType(Type second) {
+CanType TypeJoin::visitBoundGenericEnumType(CanType second) {
if (First->getKind() != second->getKind())
return First->getASTContext().TheAnyType;
OptionalTypeKind otk1, otk2;
- Type objectType1 = First->getAnyOptionalObjectType(otk1);
- Type objectType2 = second->getAnyOptionalObjectType(otk2);
+ auto firstObject = First->getAnyOptionalObjectType(otk1);
+ auto secondObject = second->getAnyOptionalObjectType(otk2);
if (otk1 == OTK_Optional || otk2 == OTK_Optional) {
+ auto canFirst = firstObject->getCanonicalType();
+ auto canSecond = secondObject->getCanonicalType();
+
// Compute the join of the unwrapped type. If there is none, we're done.
- Type unwrappedJoin = join(objectType1 ? objectType1 : First,
- objectType2 ? objectType2 : second);
+ auto unwrappedJoin =
+ join(canFirst ? canFirst : First, canSecond ? canSecond : second);
// FIXME: More general joins of enums need to be handled.
if (!unwrappedJoin)
return First->getASTContext().TheAnyType;
- return OptionalType::get(unwrappedJoin);
+ return OptionalType::get(unwrappedJoin)->getCanonicalType();
}
// FIXME: More general joins of enums need to be handled.
return First->getASTContext().TheAnyType;
}
-Type TypeJoin::visitOptionalType(Type second) {
- auto canFirst = First->getCanonicalType();
- auto canSecond = second->getCanonicalType();
+Type Type::join(Type first, Type second) {
+ assert(first && second && "Unexpected null type!");
- return TypeJoin::join(canFirst, canSecond);
-}
+ if (!first || !second) {
+ if (first)
+ return Type(ErrorType::get(first->getASTContext()));
-Type Type::join(Type type1, Type type2) {
- assert(type1 && type2 && "Unexpected null type!");
+ if (second)
+ return Type(ErrorType::get(second->getASTContext()));
- return TypeJoin::join(type1, type2);
+ return Type();
+ }
+
+ return TypeJoin::join(first->getCanonicalType(), second->getCanonicalType());
}
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 66a8338..16f22e8 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -7654,7 +7654,7 @@
(void) result;
}
- return std::move(builder).computeGenericSignature(SourceLoc());
+ return builder.computeGenericSignature(SourceLoc());
}
// Calculate the generic environment from an imported generic param list.
diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp
index f6bba17..c9e3c12 100644
--- a/lib/IDE/Refactoring.cpp
+++ b/lib/IDE/Refactoring.cpp
@@ -619,21 +619,17 @@
class TokenBasedRefactoringAction : public RefactoringAction {
protected:
ResolvedCursorInfo CursorInfo;
- bool CanProceed;
public:
TokenBasedRefactoringAction(ModuleDecl *MD, RefactoringOptions &Opts,
SourceEditConsumer &EditConsumer,
DiagnosticConsumer &DiagConsumer) :
RefactoringAction(MD, Opts, EditConsumer, DiagConsumer) {
// We can only proceed with valid location and source file.
- CanProceed = StartLoc.isValid() && TheFile;
- if (!CanProceed)
- return;
-
- // Resolve the sema token and save it for later use.
- CursorInfoResolver Resolver(*TheFile);
- CursorInfo = Resolver.resolve(StartLoc);
- CanProceed = CursorInfo.isValid();
+ if (StartLoc.isValid() && TheFile) {
+ // Resolve the sema token and save it for later use.
+ CursorInfoResolver Resolver(*TheFile);
+ CursorInfo = Resolver.resolve(StartLoc);
+ }
}
};
@@ -644,8 +640,11 @@
SourceEditConsumer &EditConsumer, \
DiagnosticConsumer &DiagConsumer) : \
TokenBasedRefactoringAction(MD, Opts, EditConsumer, DiagConsumer) {} \
- static bool isApplicable(ResolvedCursorInfo Tok); \
bool performChange() override; \
+ static bool isApplicable(ResolvedCursorInfo Tok, DiagnosticEngine &Diag); \
+ bool isApplicable() { \
+ return RefactoringAction##KIND::isApplicable(CursorInfo, DiagEngine) ; \
+ } \
};
#include "swift/IDE/RefactoringKinds.def"
@@ -671,10 +670,14 @@
RangeBasedRefactoringAction(MD, Opts, EditConsumer, DiagConsumer) {} \
bool performChange() override; \
static bool isApplicable(ResolvedRangeInfo Info, DiagnosticEngine &Diag); \
+ bool isApplicable() { \
+ return RefactoringAction##KIND::isApplicable(RangeInfo, DiagEngine) ; \
+ } \
};
#include "swift/IDE/RefactoringKinds.def"
-bool RefactoringActionLocalRename::isApplicable(ResolvedCursorInfo CursorInfo) {
+bool RefactoringActionLocalRename::
+isApplicable(ResolvedCursorInfo CursorInfo, DiagnosticEngine &Diag) {
if (CursorInfo.Kind != CursorInfoKind::ValueRef)
return false;
auto RenameOp = getAvailableRenameForDecl(CursorInfo.ValueD);
@@ -1036,8 +1039,6 @@
}
bool RefactoringActionExtractFunction::performChange() {
- if (!isApplicable(RangeInfo, DiagEngine))
- return true;
// Check if the new name is ok.
if (!Lexer::isIdentifier(PreferredName)) {
DiagEngine.diagnose(SourceLoc(), diag::invalid_name, PreferredName);
@@ -1420,8 +1421,6 @@
}
bool RefactoringActionExtractExpr::performChange() {
- if (!isApplicable(RangeInfo, DiagEngine))
- return true;
return RefactoringActionExtractExprBase(TheFile, RangeInfo,
DiagEngine, false, PreferredName,
EditConsumer).performChange();
@@ -1442,8 +1441,6 @@
}
}
bool RefactoringActionExtractRepeatedExpr::performChange() {
- if (!isApplicable(RangeInfo, DiagEngine))
- return true;
return RefactoringActionExtractExprBase(TheFile, RangeInfo,
DiagEngine, true, PreferredName,
EditConsumer).performChange();
@@ -1523,7 +1520,8 @@
return Walker.IfInfo;
}
-bool RefactoringActionCollapseNestedIfExpr::isApplicable(ResolvedCursorInfo Tok) {
+bool RefactoringActionCollapseNestedIfExpr::
+isApplicable(ResolvedCursorInfo Tok, DiagnosticEngine &Diag) {
return findCollapseNestedIfTarget(Tok).isValid();
}
@@ -1752,22 +1750,17 @@
return NonWitnessedReqs;
}
-bool RefactoringActionFillProtocolStub::isApplicable(ResolvedCursorInfo Tok) {
+bool RefactoringActionFillProtocolStub::
+isApplicable(ResolvedCursorInfo Tok, DiagnosticEngine &Diag) {
return FillProtocolStubContext::getContextFromCursorInfo(Tok).canProceed();
};
bool RefactoringActionFillProtocolStub::performChange() {
- // If the base class says no proceeding, respect it.
- if (!CanProceed)
- return true;
-
// Get the filling protocol context from the input token.
FillProtocolStubContext Context = FillProtocolStubContext::
- getContextFromCursorInfo(CursorInfo);
+ getContextFromCursorInfo(CursorInfo);
- // If the filling context disallows continue, abort.
- if (!Context.canProceed())
- return true;
+ assert(Context.canProceed());
assert(!Context.getFillingContents().empty());
assert(Context.getFillingContext());
llvm::SmallString<128> Text;
@@ -1807,21 +1800,22 @@
return collectAvailableRefactorings(SF, Tok, Scratch, /*Exclude rename*/false);
}
-bool RefactoringActionExpandDefault::isApplicable(ResolvedCursorInfo CursorInfo) {
+bool RefactoringActionExpandDefault::
+isApplicable(ResolvedCursorInfo CursorInfo, DiagnosticEngine &Diag) {
+ auto Exit = [&](bool Applicable) {
+ if (!Applicable)
+ Diag.diagnose(SourceLoc(), diag::invalid_default_location);
+ return Applicable;
+ };
if (CursorInfo.Kind != CursorInfoKind::StmtStart)
- return false;
+ return Exit(false);
if (auto *CS = dyn_cast<CaseStmt>(CursorInfo.TrailingStmt)) {
- return CS->isDefault();
+ return Exit(CS->isDefault());
}
- return false;
+ return Exit(false);
}
bool RefactoringActionExpandDefault::performChange() {
- if (!isApplicable(CursorInfo)) {
- DiagEngine.diagnose(SourceLoc(), diag::invalid_default_location);
- return true;
- }
-
// Try to find the switch statement enclosing the default statement.
auto *CS = static_cast<CaseStmt*>(CursorInfo.TrailingStmt);
auto IsSwitch = [](ASTNode Node) {
@@ -1911,7 +1905,8 @@
return Walker.Target;
}
-bool RefactoringActionLocalizeString::isApplicable(ResolvedCursorInfo Tok) {
+bool RefactoringActionLocalizeString::
+isApplicable(ResolvedCursorInfo Tok, DiagnosticEngine &Diag) {
return findLocalizeTarget(Tok);
}
@@ -1954,7 +1949,8 @@
return ConvertToCharRange(TargetNode.getSourceRange());
}
-bool RefactoringActionConvertToDoCatch::isApplicable(ResolvedCursorInfo Tok) {
+bool RefactoringActionConvertToDoCatch::
+isApplicable(ResolvedCursorInfo Tok, DiagnosticEngine &Diag) {
if (!Tok.TrailingExpr)
return false;
return isa<ForceTryExpr>(Tok.TrailingExpr);
@@ -1962,8 +1958,7 @@
bool RefactoringActionConvertToDoCatch::performChange() {
auto *TryExpr = dyn_cast<ForceTryExpr>(CursorInfo.TrailingExpr);
- if (!TryExpr)
- return true;
+ assert(TryExpr);
auto Range = findSourceRangeToWrapInCatch(CursorInfo, TheFile, SM);
if (!Range.isValid())
return true;
@@ -2042,7 +2037,7 @@
}
bool RefactoringActionSimplifyNumberLiteral::
-isApplicable(ResolvedCursorInfo Tok) {
+isApplicable(ResolvedCursorInfo Tok, DiagnosticEngine &Diag) {
if (auto *Literal = getTrailingNumberLiteral(Tok)) {
llvm::SmallString<64> Buffer;
llvm::raw_svector_ostream OS(Buffer);
@@ -2257,8 +2252,9 @@
AllKinds.push_back(RenameOp.getValue());
}
}
+ DiagnosticEngine DiagEngine(SF->getASTContext().SourceMgr);
#define CURSOR_REFACTORING(KIND, NAME, ID) \
- if (RefactoringAction##KIND::isApplicable(CursorInfo)) \
+ if (RefactoringAction##KIND::isApplicable(CursorInfo, DiagEngine)) \
AllKinds.push_back(RefactoringKind::KIND);
#include "swift/IDE/RefactoringKinds.def"
@@ -2323,8 +2319,13 @@
switch (Opts.Kind) {
#define SEMANTIC_REFACTORING(KIND, NAME, ID) \
- case RefactoringKind::KIND: return RefactoringAction##KIND(M, Opts, \
- EditConsumer, DiagConsumer).performChange();
+case RefactoringKind::KIND: { \
+ RefactoringAction##KIND Action(M, Opts, EditConsumer, DiagConsumer); \
+ if (RefactoringKind::KIND == RefactoringKind::LocalRename || \
+ Action.isApplicable()) \
+ return Action.performChange(); \
+ return true; \
+ }
#include "swift/IDE/RefactoringKinds.def"
case RefactoringKind::GlobalRename:
case RefactoringKind::FindGlobalRenameRanges:
diff --git a/lib/IRGen/ClassMetadataVisitor.h b/lib/IRGen/ClassMetadataVisitor.h
index 7d70d2b..a6faa37 100644
--- a/lib/IRGen/ClassMetadataVisitor.h
+++ b/lib/IRGen/ClassMetadataVisitor.h
@@ -105,11 +105,6 @@
}
}
- // Add a reference to the parent class, if applicable.
- if (theClass->getDeclContext()->isTypeContext()) {
- asImpl().addParentMetadataRef(theClass, type);
- }
-
// Add space for the generic parameters, if applicable.
// Note that we only add references for the immediate parameters;
// parameters for the parent context are handled by the parent.
@@ -161,7 +156,6 @@
void addIVarDestroyer() { addPointer(); }
void addValueWitnessTable() { addPointer(); }
void addDestructorFunction() { addPointer(); }
- void addParentMetadataRef(ClassDecl *forClass, Type classType) {addPointer();}
void addSuperClass() { addPointer(); }
void addClassFlags() { addInt32(); }
void addInstanceAddressPoint() { addInt32(); }
diff --git a/lib/IRGen/EnumMetadataVisitor.h b/lib/IRGen/EnumMetadataVisitor.h
index 917c6ca..bc8334a 100644
--- a/lib/IRGen/EnumMetadataVisitor.h
+++ b/lib/IRGen/EnumMetadataVisitor.h
@@ -49,7 +49,6 @@
// EnumMetadata header.
asImpl().addNominalTypeDescriptor();
- asImpl().addParentMetadataRef();
// If changing this layout, you must update the magic number in
// emitParentMetadataRef.
@@ -83,7 +82,6 @@
void addMetadataFlags() { addPointer(); }
void addValueWitnessTable() { addPointer(); }
void addNominalTypeDescriptor() { addPointer(); }
- void addParentMetadataRef() { addPointer(); }
void addGenericArgument(CanType argument) { addPointer(); }
void addGenericWitnessTable(CanType argument, ProtocolConformanceRef conf) {
addPointer();
diff --git a/lib/IRGen/Fulfillment.cpp b/lib/IRGen/Fulfillment.cpp
index 449acb8..739b4f5 100644
--- a/lib/IRGen/Fulfillment.cpp
+++ b/lib/IRGen/Fulfillment.cpp
@@ -70,12 +70,12 @@
case TypeKind::Tuple:
return cast<TupleType>(type)->getNumElements() == 0;
- // Nominal types might have parents.
+ // Nominal types might have generic parents.
case TypeKind::Class:
case TypeKind::Enum:
case TypeKind::Protocol:
case TypeKind::Struct:
- return !cast<NominalType>(type)->getParent();
+ return !cast<NominalType>(type)->getDecl()->isGenericContext();
// Bound generic types have type arguments.
case TypeKind::BoundGenericClass:
@@ -125,14 +125,17 @@
return hadFulfillment;
}
+ if (keys.isInterestingType(type)) {
+ if (auto superclassTy = keys.getSuperclassBound(type)) {
+ return searchNominalTypeMetadata(IGM, superclassTy, source,
+ std::move(path), keys);
+ }
+ }
+
// Inexact metadata will be a problem if we ever try to use this
// to remember that we already have the metadata for something.
- if (auto nomTy = dyn_cast<NominalType>(type)) {
- return searchNominalTypeMetadata(IGM, nomTy, source, std::move(path), keys);
- }
- if (auto boundTy = dyn_cast<BoundGenericType>(type)) {
- return searchBoundGenericTypeMetadata(IGM, boundTy, source,
- std::move(path), keys);
+ if (isa<NominalType>(type) || isa<BoundGenericType>(type)) {
+ return searchNominalTypeMetadata(IGM, type, source, std::move(path), keys);
}
// TODO: tuples
@@ -203,47 +206,27 @@
}
-bool FulfillmentMap::searchParentTypeMetadata(IRGenModule &IGM,
- NominalTypeDecl *decl,
- CanType parent,
- unsigned source,
- MetadataPath &&path,
- const InterestingKeysCallback &keys) {
- // We might not have a parent type.
- if (!parent) return false;
-
- // If we do, it has to be nominal one way or another.
- path.addNominalParentComponent();
- return searchTypeMetadata(IGM, parent, IsExact, source, std::move(path),keys);
-}
-
bool FulfillmentMap::searchNominalTypeMetadata(IRGenModule &IGM,
- CanNominalType type,
+ CanType type,
unsigned source,
MetadataPath &&path,
const InterestingKeysCallback &keys) {
- // Nominal types add no generic arguments themselves, but they
- // may have the arguments of their parents.
- return searchParentTypeMetadata(IGM, type->getDecl(), type.getParent(),
- source, std::move(path), keys);
-}
-
-bool FulfillmentMap::searchBoundGenericTypeMetadata(IRGenModule &IGM,
- CanBoundGenericType type,
- unsigned source,
- MetadataPath &&path,
- const InterestingKeysCallback &keys) {
// Objective-C generics don't preserve their generic parameters at runtime,
// so they aren't able to fulfill type metadata requirements.
- if (type->getDecl()->hasClangNode()) {
+ if (type.getAnyNominal()->hasClangNode()) {
return false;
}
+ auto *nominal = type.getAnyNominal();
+ if (!nominal->isGenericContext() || isa<ProtocolDecl>(nominal)) {
+ return false;
+ }
+
bool hadFulfillment = false;
- GenericTypeRequirements requirements(IGM, type->getDecl());
+ GenericTypeRequirements requirements(IGM, nominal);
requirements.enumerateFulfillments(
- IGM, type->getContextSubstitutionMap(IGM.getSwiftModule(), type->getDecl()),
+ IGM, type->getContextSubstitutionMap(IGM.getSwiftModule(), nominal),
[&](unsigned reqtIndex, CanType arg,
Optional<ProtocolConformanceRef> conf) {
// Skip uninteresting type arguments.
@@ -289,11 +272,6 @@
std::move(argPath), keys, interestingConformances);
});
- // Also match against the parent. The polymorphic type
- // will start with any arguments from the parent.
- hadFulfillment |= searchParentTypeMetadata(IGM, type->getDecl(),
- type.getParent(),
- source, std::move(path), keys);
return hadFulfillment;
}
@@ -318,21 +296,6 @@
}
}
-bool FulfillmentMap::Everything::isInterestingType(CanType type) const {
- return true;
-}
-bool FulfillmentMap::Everything::hasInterestingType(CanType type) const {
- return true;
-}
-bool FulfillmentMap::Everything
- ::hasLimitedInterestingConformances(CanType type) const {
- return false;
-}
-GenericSignature::ConformsToArray
-FulfillmentMap::Everything::getInterestingConformances(CanType type) const{
- return {};
-}
-
void FulfillmentMap::dump() const {
auto &out = llvm::errs();
for (auto &entry : Fulfillments) {
diff --git a/lib/IRGen/Fulfillment.h b/lib/IRGen/Fulfillment.h
index 82b66ba..65737b6 100644
--- a/lib/IRGen/Fulfillment.h
+++ b/lib/IRGen/Fulfillment.h
@@ -66,17 +66,10 @@
virtual GenericSignature::ConformsToArray
getInterestingConformances(CanType type) const = 0;
- virtual ~InterestingKeysCallback() = default;
- };
+ /// Return the limited interesting conformances for an interesting type.
+ virtual CanType getSuperclassBound(CanType type) const = 0;
- /// An implementation of InterestingKeysCallback that returns everything
- /// fulfillable.
- struct Everything : InterestingKeysCallback {
- bool isInterestingType(CanType type) const override;
- bool hasInterestingType(CanType type) const override;
- bool hasLimitedInterestingConformances(CanType type) const override;
- GenericSignature::ConformsToArray
- getInterestingConformances(CanType type) const override;
+ virtual ~InterestingKeysCallback() = default;
};
FulfillmentMap() = default;
@@ -140,19 +133,10 @@
}
private:
- bool searchParentTypeMetadata(IRGenModule &IGM, NominalTypeDecl *typeDecl,
- CanType parent,
- unsigned source, MetadataPath &&path,
- const InterestingKeysCallback &keys);
-
- bool searchNominalTypeMetadata(IRGenModule &IGM, CanNominalType type,
+ bool searchNominalTypeMetadata(IRGenModule &IGM, CanType type,
unsigned source, MetadataPath &&path,
const InterestingKeysCallback &keys);
- bool searchBoundGenericTypeMetadata(IRGenModule &IGM, CanBoundGenericType type,
- unsigned source, MetadataPath &&path,
- const InterestingKeysCallback &keys);
-
/// Search the given witness table for useful fulfillments.
///
/// \return true if any fulfillments were added by this search.
@@ -168,5 +152,3 @@
}
#endif
-
-
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index c2bea3e..fdd329d 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -2561,8 +2561,9 @@
NominalTypeDecl *nominal,
ArrayRef<llvm::Type *> genericArgs,
ForDefinition_t forDefinition) {
- assert(!genericArgs.empty());
assert(nominal->isGenericContext());
+ assert(!genericArgs.empty() ||
+ nominal->getGenericSignature()->areAllParamsConcrete());
IRGen.addLazyTypeMetadata(nominal);
auto type = nominal->getDeclaredType()->getCanonicalType();
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index c9dc1ca..2219b15 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -142,8 +142,7 @@
static unsigned getNumGenericArguments(IRGenModule &IGM,
NominalTypeDecl *nominal) {
GenericTypeRequirements requirements(IGM, nominal);
- return unsigned(requirements.hasParentType())
- + requirements.getNumTypeRequirements();
+ return requirements.getNumTypeRequirements();
}
void collectTypes(IRGenModule &IGM, NominalTypeDecl *nominal) {
@@ -153,10 +152,6 @@
void collectTypes(IRGenModule &IGM,
const GenericTypeRequirements &requirements) {
- if (requirements.hasParentType()) {
- Types.push_back(IGM.TypeMetadataPtrTy);
- }
-
for (auto &requirement : requirements.getRequirements()) {
if (requirement.Protocol) {
Types.push_back(IGM.WitnessTablePtrTy);
@@ -181,10 +176,6 @@
GenericTypeRequirements requirements(IGF.IGM, decl);
- if (requirements.hasParentType()) {
- Values.push_back(IGF.emitTypeMetadataRef(parentType));
- }
-
auto subs =
type->getContextSubstitutionMap(IGF.IGM.getSwiftModule(), decl);
requirements.enumerateFulfillments(IGF.IGM, subs,
@@ -217,14 +208,6 @@
->getCanonicalType();
};
- // If we have a parent type, it's the first parameter.
- if (requirements.hasParentType()) {
- auto parentType = getInContext(requirements.getParentType());
- llvm::Value *parentMetadata = IGF.Builder.CreateLoad(array);
- array = IGF.Builder.CreateConstArrayGEP(array, 1, IGF.IGM.getPointerSize());
- IGF.bindLocalTypeDataFromTypeMetadata(parentType, IsExact, parentMetadata);
- }
-
// Okay, bind everything else from the context.
requirements.bindFromBuffer(IGF, array, getInContext);
}
@@ -372,7 +355,9 @@
// Grab the substitutions.
GenericArguments genericArgs;
genericArgs.collect(IGF, theType);
- assert(genericArgs.Values.size() > 0 && "no generic args?!");
+ assert((genericArgs.Values.size() > 0 ||
+ theDecl->getGenericSignature()->areAllParamsConcrete())
+ && "no generic args?!");
// Call the generic metadata accessor function.
llvm::Function *accessor =
@@ -1147,7 +1132,9 @@
for (auto &arg : IGF.CurFn->args())
genericArgs.Values.push_back(&arg);
assert(genericArgs.Values.size() == genericArgs.Types.size());
- assert(genericArgs.Values.size() > 0 && "no generic args?!");
+ assert((genericArgs.Values.size() > 0 ||
+ nominal->getGenericSignature()->areAllParamsConcrete())
+ && "no generic args?!");
// Slam that information directly into the generic arguments buffer.
auto argsBufferTy =
@@ -2184,23 +2171,58 @@
// GenericParameterDescriptorFlags Flags;
GenericParameterDescriptorFlags flags;
- if (ntd->getDeclContext()->isTypeContext())
- flags = flags.withHasParent(true);
- if (requirements.hasParentType())
- flags = flags.withHasGenericParent(true);
if (auto *cd = dyn_cast<ClassDecl>(ntd)) {
auto &layout = IGM.getMetadataLayout(cd);
if (layout.getVTableSize() > 0)
flags = flags.withHasVTable(true);
}
- B.addInt32(flags.getIntValue());
+
+ // Calculate the number of generic parameters at each nesting depth.
+ unsigned totalGenericParams = 0;
+ SmallVector<unsigned, 2> numPrimaryParams;
+ for (auto *outer = ntd; outer != nullptr;
+ outer = outer->getDeclContext()
+ ->getAsNominalTypeOrNominalTypeExtensionContext()) {
+ unsigned genericParamsAtDepth = 0;
+ if (auto *genericParams = outer->getGenericParams()) {
+ for (auto *paramDecl : *genericParams) {
+ auto contextTy = ntd->mapTypeIntoContext(
+ paramDecl->getDeclaredInterfaceType());
+ // Skip parameters which have been made concrete, because they do
+ // not appear in type metadata.
+ //
+ // FIXME: We should emit information about same-type constraints
+ // as well as conformance constraints, so that clients can
+ // reconstruct the full generic signature of the type, including
+ // fully-concrete parameters.
+ if (contextTy->is<ArchetypeType>()) {
+ totalGenericParams++;
+ genericParamsAtDepth++;
+ }
+ }
+ }
+ numPrimaryParams.push_back(genericParamsAtDepth);
+ }
+
+ // This assertion will fail once we have generic types nested
+ // inside generic functions or other local generic contexts.
+ assert(totalGenericParams == requirements.getNumTypeRequirements());
+
+ // Emit the nesting depth.
+ B.addInt16(numPrimaryParams.size());
+
+ // Emit the flags.
+ B.addInt16(flags.getIntValue());
+
+ // Emit the number of generic parameters at each nesting depth.
+ std::reverse(numPrimaryParams.begin(), numPrimaryParams.end());
+ for (auto count : numPrimaryParams)
+ B.addInt32(count);
// TODO: provide reflective descriptions of the type and
// conformance requirements stored here.
-
- // };
}
-
+
llvm::Constant *emit() {
asImpl().layout();
@@ -3487,7 +3509,6 @@
using super = ClassMetadataBuilderBase<ClassMetadataBuilder>;
bool HasUnfilledSuperclass = false;
- bool HasUnfilledParent = false;
Size AddressPoint;
@@ -3534,22 +3555,6 @@
}
}
- void addParentMetadataRef(ClassDecl *forClass, Type classType) {
- CanType parentType = classType->getCanonicalType().getNominalParent();
-
- if (auto metadata =
- tryEmitConstantTypeMetadataRef(IGM, parentType,
- SymbolReferenceKind::Absolute)) {
- B.add(metadata.getValue());
- } else {
- // Leave a null pointer placeholder to be filled by in-place
- // initialization.
- B.addNullPointer(IGM.TypeMetadataPtrTy);
- if (forClass == Target)
- HasUnfilledParent = true;
- }
- }
-
bool canBeConstant() {
// TODO: the metadata global can actually be constant in a very
// special case: it's not a pattern, ObjC interoperation isn't
@@ -3566,7 +3571,7 @@
[&](IRGenFunction &IGF, llvm::Constant *cacheVar) -> llvm::Value* {
// There's an interesting special case where we can do the
// initialization idempotently and thus avoid the need for a lock.
- if (!HasUnfilledSuperclass && !HasUnfilledParent &&
+ if (!HasUnfilledSuperclass &&
isFinishInitializationIdempotent()) {
auto type = Target->getDeclaredType()->getCanonicalType();
auto metadata =
@@ -3604,18 +3609,6 @@
IGF.Builder.CreateStore(superclassMetadata, superField);
}
- // Initialize the class's own parent pointer if it has one and it
- // wasn't emitted as a constant.
- if (HasUnfilledParent) {
- auto parentType = type.getParent();
- assert(parentType);
- llvm::Value *parentMetadata = IGF.emitTypeMetadataRef(parentType);
-
- auto parentSlot =
- emitAddressOfParentMetadataSlot(IGF, metadata, type->getDecl());
- IGF.Builder.CreateStore(parentMetadata, parentSlot);
- }
-
metadata = emitFinishInitializationOfClassMetadata(IGF, metadata);
return metadata;
@@ -3647,12 +3640,6 @@
HasDependentMetadata = true;
}
- void addParentMetadataRef(ClassDecl *forClass, Type classType) {
- CanType parentType = classType->getCanonicalType().getNominalParent();
- this->addFillOp(parentType, None, /*relative*/ false);
- B.addNullPointer(IGM.TypeMetadataPtrTy);
- }
-
void addSuperClass() {
// Filled in by the runtime.
B.addNullPointer(IGM.TypeMetadataPtrTy);
@@ -4362,71 +4349,13 @@
// Value types (structs and enums)
//===----------------------------------------------------------------------===//
-namespace {
- template <class Impl, class Base>
- class ValueTypeMetadataBuilderBase : public Base {
- using super = Base;
-
- protected:
- using super::asImpl;
- using super::IGM;
- using super::Target;
- ConstantStructBuilder &B;
-
- template <class DeclTy>
- ValueTypeMetadataBuilderBase(IRGenModule &IGM, DeclTy *theDecl,
- ConstantStructBuilder &B)
- : super(IGM, theDecl), B(B) {}
-
- CanType getParentType() const {
- Type type = Target->getDeclaredTypeInContext();
- Type parentType = type->getNominalParent();
- if (parentType)
- return parentType->getCanonicalType();
- return CanType();
- }
-
- public:
- void addParentMetadataRef() {
- llvm::Constant *parentMetadata = nullptr;
- if (auto parentType = getParentType()) {
- parentMetadata =
- tryEmitConstantTypeMetadataRef(IGM, parentType,
- SymbolReferenceKind::Absolute)
- .getDirectValue();
- if (!parentMetadata) {
- asImpl().flagUnfilledParent();
- }
- }
-
- if (!parentMetadata)
- parentMetadata = llvm::ConstantPointerNull::get(IGM.TypeMetadataPtrTy);
- B.add(parentMetadata);
- }
- };
-} // end anonymous namespace
-
static llvm::Value *
emitInPlaceValueTypeMetadataInitialization(IRGenFunction &IGF,
CanNominalType type,
- llvm::Value *metadata,
- bool hasUnfilledParent) {
+ llvm::Value *metadata) {
// All the value types are basically similar.
assert(isa<StructType>(type) || isa<EnumType>(type));
- // Initialize the parent-metadata field if it wasn't done statically.
- if (hasUnfilledParent) {
- CanType parentType = type.getParent();
- assert(parentType);
-
- // Value types hold the parent metadata as a far relative
- // indirectable pointer.
- llvm::Value *parentMetadata = IGF.emitTypeMetadataRef(parentType);
- Address addr =
- emitAddressOfParentMetadataSlot(IGF, metadata, type->getDecl());
- IGF.Builder.CreateStore(parentMetadata, addr);
- }
-
// Set up the value witness table if it's dependent.
SILType loweredType = IGF.IGM.getLoweredType(AbstractionPattern(type), type);
auto &ti = IGF.IGM.getTypeInfo(loweredType);
@@ -4445,8 +4374,7 @@
/// Create an access function for the type metadata of the given
/// non-generic nominal type.
static void createInPlaceValueTypeMetadataAccessFunction(IRGenModule &IGM,
- NominalTypeDecl *typeDecl,
- bool hasUnfilledParent) {
+ NominalTypeDecl *typeDecl) {
assert(!typeDecl->isGenericContext());
auto type =
cast<NominalType>(typeDecl->getDeclaredType()->getCanonicalType());
@@ -4456,8 +4384,7 @@
llvm::Constant *cacheVariable) {
return emitInPlaceTypeMetadataAccessFunctionBody(IGF, type, cacheVariable,
[&](IRGenFunction &IGF, llvm::Value *metadata) {
- return emitInPlaceValueTypeMetadataInitialization(IGF, type, metadata,
- hasUnfilledParent);
+ return emitInPlaceValueTypeMetadataInitialization(IGF, type, metadata);
});
});
}
@@ -4469,19 +4396,18 @@
namespace {
/// An adapter for laying out struct metadata.
template <class Impl>
- class StructMetadataBuilderBase
- : public ValueTypeMetadataBuilderBase<Impl,StructMetadataVisitor<Impl>>{
- using super = ValueTypeMetadataBuilderBase<Impl,StructMetadataVisitor<Impl>>;
+ class StructMetadataBuilderBase : public StructMetadataVisitor<Impl> {
+ using super = StructMetadataVisitor<Impl>;
protected:
+ ConstantStructBuilder &B;
using super::IGM;
using super::Target;
using super::asImpl;
- using super::B;
StructMetadataBuilderBase(IRGenModule &IGM, StructDecl *theStruct,
ConstantStructBuilder &B)
- : super(IGM, theStruct, B) {
+ : super(IGM, theStruct), B(B) {
}
public:
@@ -4525,23 +4451,18 @@
class StructMetadataBuilder :
public StructMetadataBuilderBase<StructMetadataBuilder> {
- bool HasUnfilledParent = false;
bool HasUnfilledFieldOffset = false;
public:
StructMetadataBuilder(IRGenModule &IGM, StructDecl *theStruct,
ConstantStructBuilder &B)
: StructMetadataBuilderBase(IGM, theStruct, B) {}
- void flagUnfilledParent() {
- HasUnfilledParent = true;
- }
-
void flagUnfilledFieldOffset() {
HasUnfilledFieldOffset = true;
}
bool canBeConstant() {
- return !HasUnfilledParent && !HasUnfilledFieldOffset;
+ return !HasUnfilledFieldOffset;
}
void addValueWitnessTable() {
@@ -4550,8 +4471,7 @@
}
void createMetadataAccessFunction() {
- createInPlaceValueTypeMetadataAccessFunction(IGM, Target,
- HasUnfilledParent);
+ createInPlaceValueTypeMetadataAccessFunction(IGM, Target);
}
};
@@ -4591,15 +4511,6 @@
{metadataPattern, arguments});
}
- void addParentMetadataRef() {
- // Override to always use a fill op instead of a relocation.
- if (CanType parentType = getParentType()) {
- addFillOp(parentType, None, /*relative*/ false);
- }
-
- B.addInt(IGM.IntPtrTy, 0);
- }
-
void flagUnfilledFieldOffset() {
// We just assume this might happen.
}
@@ -4665,19 +4576,18 @@
namespace {
template<class Impl>
-class EnumMetadataBuilderBase
- : public ValueTypeMetadataBuilderBase<Impl, EnumMetadataVisitor<Impl>> {
- using super = ValueTypeMetadataBuilderBase<Impl, EnumMetadataVisitor<Impl>>;
+class EnumMetadataBuilderBase : public EnumMetadataVisitor<Impl> {
+ using super = EnumMetadataVisitor<Impl>;
protected:
+ ConstantStructBuilder &B;
using super::IGM;
using super::Target;
- using super::B;
public:
EnumMetadataBuilderBase(IRGenModule &IGM, EnumDecl *theEnum,
ConstantStructBuilder &B)
- : super(IGM, theEnum, B) {
+ : super(IGM, theEnum), B(B) {
}
void addMetadataFlags() {
@@ -4705,7 +4615,6 @@
class EnumMetadataBuilder
: public EnumMetadataBuilderBase<EnumMetadataBuilder> {
- bool HasUnfilledParent = false;
bool HasUnfilledPayloadSize = false;
public:
@@ -4733,17 +4642,12 @@
B.addInt(IGM.IntPtrTy, strategy.getPayloadSizeForMetadata());
}
- void flagUnfilledParent() {
- HasUnfilledParent = true;
- }
-
bool canBeConstant() {
- return !HasUnfilledParent && !HasUnfilledPayloadSize;
+ return !HasUnfilledPayloadSize;
}
void createMetadataAccessFunction() {
- createInPlaceValueTypeMetadataAccessFunction(IGM, Target,
- HasUnfilledParent);
+ createInPlaceValueTypeMetadataAccessFunction(IGM, Target);
}
};
@@ -4763,15 +4667,6 @@
{metadataPattern, arguments});
}
- void addParentMetadataRef() {
- // Override to always use a fill op instead of a relocation.
- if (CanType parentType = getParentType()) {
- addFillOp(parentType, None, /*relative*/ false);
- }
-
- B.addInt(IGM.IntPtrTy, 0);
- }
-
void addValueWitnessTable() {
B.add(getValueWitnessTableForGenericValueType(IGM, Target,
HasDependentVWT));
@@ -4905,14 +4800,6 @@
Size AddressPoint = Size::invalid();
- bool computeUnfilledParent() {
- if (auto parentType = asImpl().getTargetType().getNominalParent()) {
- return !tryEmitConstantTypeMetadataRef(IGM, parentType,
- SymbolReferenceKind::Absolute);
- }
- return false;
- }
-
public:
void layout() {
if (asImpl().requiresInitializationFunction())
@@ -5027,41 +4914,25 @@
public ForeignMetadataBuilderBase<ForeignStructMetadataBuilder,
StructMetadataBuilderBase<ForeignStructMetadataBuilder>>
{
- bool HasUnfilledParent = false;
public:
ForeignStructMetadataBuilder(IRGenModule &IGM, StructDecl *target,
ConstantStructBuilder &builder)
- : ForeignMetadataBuilderBase(IGM, target, builder) {
- HasUnfilledParent = computeUnfilledParent();
- }
+ : ForeignMetadataBuilderBase(IGM, target, builder) {}
CanType getTargetType() const {
return Target->getDeclaredType()->getCanonicalType();
}
bool requiresInitializationFunction() const {
- return HasUnfilledParent;
+ return false;
}
- void emitInitialization(IRGenFunction &IGF, llvm::Value *metadata) {
- if (HasUnfilledParent) {
- auto parentType = getTargetType().getNominalParent();
- auto parentMetadata = IGF.emitTypeMetadataRef(parentType);
-
- Address slot =
- emitAddressOfParentMetadataSlot(IGF, metadata, this->Target);
- IGF.Builder.CreateStore(parentMetadata, slot);
- }
- }
+ void emitInitialization(IRGenFunction &IGF, llvm::Value *metadata) {}
void addValueWitnessTable() {
auto type = this->Target->getDeclaredType()->getCanonicalType();
B.add(emitValueWitnessTable(IGM, type));
}
- void flagUnfilledParent() {
- assert(HasUnfilledParent);
- }
-
void flagUnfilledFieldOffset() {
llvm_unreachable("foreign type with non-fixed layout?");
}
@@ -5072,31 +4943,19 @@
public ForeignMetadataBuilderBase<ForeignEnumMetadataBuilder,
EnumMetadataBuilderBase<ForeignEnumMetadataBuilder>>
{
- bool HasUnfilledParent = false;
public:
ForeignEnumMetadataBuilder(IRGenModule &IGM, EnumDecl *target,
ConstantStructBuilder &builder)
- : ForeignMetadataBuilderBase(IGM, target, builder) {
- HasUnfilledParent = computeUnfilledParent();
- }
+ : ForeignMetadataBuilderBase(IGM, target, builder) {}
CanType getTargetType() const {
return Target->getDeclaredType()->getCanonicalType();
}
bool requiresInitializationFunction() const {
- return HasUnfilledParent;
+ return false;
}
- void emitInitialization(IRGenFunction &IGF, llvm::Value *metadata) {
- if (HasUnfilledParent) {
- auto parentType = getTargetType().getNominalParent();
- auto parentMetadata = IGF.emitTypeMetadataRef(parentType);
-
- Address slot =
- emitAddressOfParentMetadataSlot(IGF, metadata, this->Target);
- IGF.Builder.CreateStore(parentMetadata, slot);
- }
- }
+ void emitInitialization(IRGenFunction &IGF, llvm::Value *metadata) {}
void addValueWitnessTable() {
auto type = this->Target->getDeclaredType()->getCanonicalType();
@@ -5106,10 +4965,6 @@
void addPayloadSize() const {
llvm_unreachable("nongeneric enums shouldn't need payload size in metadata");
}
-
- void flagUnfilledParent() {
- assert(HasUnfilledParent);
- }
};
} // end anonymous namespace
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 7ddf897..3982e34 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -95,6 +95,12 @@
return Generics->getConformsTo(t, M);
}
+ CanType getSuperclassBound(Type t) {
+ if (auto superclassTy = Generics->getSuperclassBound(t, M))
+ return superclassTy->getCanonicalType();
+ return CanType();
+ }
+
public:
PolymorphicConvention(IRGenModule &IGM, CanSILFunctionType fnType);
@@ -291,6 +297,9 @@
getInterestingConformances(CanType type) const override {
return Self.getConformsTo(type);
}
+ CanType getSuperclassBound(CanType type) const override {
+ return Self.getSuperclassBound(type);
+ }
} callbacks(*this);
return Fulfillments.searchTypeMetadata(IGM, type, isExact, sourceIndex,
std::move(path), callbacks);
@@ -367,6 +376,15 @@
return;
}
+ if (isa<GenericTypeParamType>(type)) {
+ if (auto superclassTy = getSuperclassBound(type)) {
+ considerNewTypeSource(MetadataSource::Kind::ClassPointer,
+ paramIndex, superclassTy, IsInexact);
+ return;
+
+ }
+ }
+
// Thick metatypes are sources of metadata.
if (auto metatypeTy = dyn_cast<MetatypeType>(type)) {
if (metatypeTy->getRepresentation() != MetatypeRepresentation::Thick)
@@ -1284,6 +1302,11 @@
getInterestingConformances(CanType type) const override {
llvm_unreachable("no limits");
}
+ CanType getSuperclassBound(CanType type) const override {
+ if (auto superclassTy = cast<ArchetypeType>(type)->getSuperclass())
+ return superclassTy->getCanonicalType();
+ return CanType();
+ }
} callback;
Fulfillments->searchTypeMetadata(IGM, ConcreteType, IsExact,
/*sourceIndex*/ 0, MetadataPath(),
@@ -2023,15 +2046,17 @@
case Component::Kind::NominalTypeArgument:
case Component::Kind::NominalTypeArgumentConformance: {
assert(sourceKey.Kind == LocalTypeDataKind::forTypeMetadata());
- auto generic = cast<BoundGenericType>(sourceKey.Type);
+ auto type = sourceKey.Type;
+ if (auto archetypeTy = dyn_cast<ArchetypeType>(type))
+ type = archetypeTy->getSuperclass()->getCanonicalType();
+ auto *nominal = type.getAnyNominal();
auto reqtIndex = component.getPrimaryIndex();
- GenericTypeRequirements requirements(IGF.IGM, generic->getDecl());
+ GenericTypeRequirements requirements(IGF.IGM, nominal);
auto &requirement = requirements.getRequirements()[reqtIndex];
auto module = IGF.getSwiftModule();
- auto subs = generic->getContextSubstitutionMap(module,
- generic->getDecl());
+ auto subs = sourceKey.Type->getContextSubstitutionMap(module, nominal);
auto sub = requirement.TypeParameter.subst(subs)->getCanonicalType();
// In either case, we need to change the type.
@@ -2041,7 +2066,7 @@
if (component.getKind() == Component::Kind::NominalTypeArgument) {
assert(!requirement.Protocol && "index mismatch!");
if (source) {
- source = emitArgumentMetadataRef(IGF, generic->getDecl(),
+ source = emitArgumentMetadataRef(IGF, nominal,
requirements, reqtIndex, source);
setTypeMetadataName(IGF.IGM, source, sourceKey.Type);
}
@@ -2057,7 +2082,7 @@
if (source) {
auto protocol = conformance.getRequirement();
- source = emitArgumentWitnessTableRef(IGF, generic->getDecl(),
+ source = emitArgumentWitnessTableRef(IGF, nominal,
requirements, reqtIndex, source);
setProtocolWitnessTableName(IGF.IGM, source, sourceKey.Type, protocol);
}
@@ -2066,25 +2091,6 @@
return source;
}
- case Component::Kind::NominalParent: {
- assert(sourceKey.Kind == LocalTypeDataKind::forTypeMetadata());
- NominalTypeDecl *nominalDecl;
- if (auto nominal = dyn_cast<NominalType>(sourceKey.Type)) {
- nominalDecl = nominal->getDecl();
- sourceKey.Type = nominal.getParent();
- } else {
- auto generic = cast<BoundGenericType>(sourceKey.Type);
- nominalDecl = generic->getDecl();
- sourceKey.Type = generic.getParent();
- }
-
- if (source) {
- source = emitParentMetadataRef(IGF, nominalDecl, source);
- setTypeMetadataName(IGF.IGM, source, sourceKey.Type);
- }
- return source;
- }
-
case Component::Kind::OutOfLineBaseProtocol: {
auto conformance = sourceKey.Kind.getProtocolConformance();
auto protocol = conformance.getRequirement();
@@ -2184,9 +2190,6 @@
out << "nominal_type_argument_conformance["
<< component.getPrimaryIndex() << "]";
break;
- case Component::Kind::NominalParent:
- out << "nominal_parent";
- break;
case Component::Kind::Impossible:
out << "impossible";
break;
@@ -2573,28 +2576,9 @@
// Construct a representative function type.
auto generics = ncGenerics->getCanonicalSignature();
CanSILFunctionType fnType = [&]() -> CanSILFunctionType {
- CanType type = typeDecl->getDeclaredInterfaceType()->getCanonicalType();
- if (auto nominal = dyn_cast<NominalType>(type)) {
- ParentType = nominal.getParent();
- } else {
- ParentType = cast<BoundGenericType>(type).getParent();
- }
-
- // Ignore the existence of the parent type if it has no type parameters.
- if (ParentType && !ParentType->hasTypeParameter())
- ParentType = CanType();
-
- SmallVector<SILParameterInfo, 1> params;
- if (ParentType) {
- auto parentMetatype =
- CanMetatypeType::get(ParentType, MetatypeRepresentation::Thick);
- params.push_back(SILParameterInfo(parentMetatype,
- ParameterConvention::Direct_Unowned));
- }
-
return SILFunctionType::get(generics, SILFunctionType::ExtInfo(),
/*callee*/ ParameterConvention::Direct_Unowned,
- params, /*results*/ {}, /*error*/ None,
+ /*params*/ {}, /*results*/ {}, /*error*/ None,
IGM.Context);
}();
diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp
index 98ece80..f282d27 100644
--- a/lib/IRGen/GenReflection.cpp
+++ b/lib/IRGen/GenReflection.cpp
@@ -71,12 +71,6 @@
OS << '_';
}
- void visitParentMetadataSource(const ParentMetadataSource *P) {
- OS << 'P';
- visit(P->getChild());
- OS << '_';
- }
-
void visitSelfMetadataSource(const SelfMetadataSource *S) {
OS << 'S';
}
@@ -158,13 +152,6 @@
}
void
- visitParentMetadataSource(const ParentMetadataSource *P) {
- printHeader("parent-of");
- printRec(P->getChild());
- closeForm();
- }
-
- void
visitSelfMetadataSource(const SelfMetadataSource *S) {
printHeader("self");
closeForm();
diff --git a/lib/IRGen/GenericRequirement.h b/lib/IRGen/GenericRequirement.h
index 9839224..48cdccd 100644
--- a/lib/IRGen/GenericRequirement.h
+++ b/lib/IRGen/GenericRequirement.h
@@ -97,7 +97,6 @@
/// anything fulfillable from its parent type metadata).
class GenericTypeRequirements {
NominalTypeDecl *TheDecl;
- CanType ParentType;
llvm::SmallVector<GenericRequirement, 4> Requirements;
public:
@@ -108,15 +107,6 @@
return Requirements;
}
- /// Does this generic type have
- bool hasParentType() const {
- return bool(ParentType);
- }
-
- CanType getParentType() const {
- return ParentType;
- }
-
/// Return the number of entries required in order to store this data.
unsigned getStorageSizeInWords() const {
return Requirements.size();
diff --git a/lib/IRGen/LocalTypeData.cpp b/lib/IRGen/LocalTypeData.cpp
index 3deddfb..fe2fc05 100644
--- a/lib/IRGen/LocalTypeData.cpp
+++ b/lib/IRGen/LocalTypeData.cpp
@@ -254,12 +254,34 @@
CanType type,
IsExact_t isExact,
llvm::Value *metadata) {
+ struct Callback : FulfillmentMap::InterestingKeysCallback {
+ bool isInterestingType(CanType type) const override {
+ return true;
+ }
+ bool hasInterestingType(CanType type) const override {
+ return true;
+ }
+ bool hasLimitedInterestingConformances(CanType type) const override {
+ return false;
+ }
+ GenericSignature::ConformsToArray
+ getInterestingConformances(CanType type) const override {
+ llvm_unreachable("no limits");
+ }
+ CanType getSuperclassBound(CanType type) const override {
+ if (auto arch = dyn_cast<ArchetypeType>(type))
+ if (auto superclassTy = arch->getSuperclass())
+ return superclassTy->getCanonicalType();
+ return CanType();
+ }
+ } callbacks;
+
// Look for anything at all that's fulfilled by this. If we don't find
// anything, stop.
FulfillmentMap fulfillments;
if (!fulfillments.searchTypeMetadata(IGF.IGM, type, isExact,
/*source*/ 0, MetadataPath(),
- FulfillmentMap::Everything())) {
+ callbacks)) {
return;
}
diff --git a/lib/IRGen/MetadataLayout.cpp b/lib/IRGen/MetadataLayout.cpp
index 8fde127..fcda034 100644
--- a/lib/IRGen/MetadataLayout.cpp
+++ b/lib/IRGen/MetadataLayout.cpp
@@ -126,12 +126,6 @@
/******************************* NOMINAL TYPES ********************************/
-Offset NominalMetadataLayout::getParentOffset(IRGenFunction &IGF) const {
- assert(Parent.isValid());
- assert(Parent.isStatic() && "resilient metadata layout unsupported!");
- return Offset(Parent.getStaticOffset());
-}
-
Size
NominalMetadataLayout::getStaticGenericRequirementsOffset() const {
assert(GenericRequirements.isValid());
@@ -146,24 +140,6 @@
return Offset(GenericRequirements.getStaticOffset());
}
-/// Given a reference to some metadata, derive a reference to the
-/// type's parent type.
-llvm::Value *irgen::emitParentMetadataRef(IRGenFunction &IGF,
- NominalTypeDecl *decl,
- llvm::Value *metadata) {
- auto slot = emitAddressOfParentMetadataSlot(IGF, metadata, decl);
- return IGF.emitInvariantLoad(slot);
-}
-
-Address irgen::emitAddressOfParentMetadataSlot(IRGenFunction &IGF,
- llvm::Value *metadata,
- NominalTypeDecl *decl) {
- auto offset = IGF.IGM.getMetadataLayout(decl).getParentOffset(IGF);
- return IGF.emitAddressAtOffset(metadata, offset,
- IGF.IGM.TypeMetadataPtrTy,
- IGF.IGM.getPointerAlignment());
-}
-
static llvm::Value *emitLoadOfGenericRequirement(IRGenFunction &IGF,
llvm::Value *metadata,
NominalTypeDecl *decl,
@@ -246,12 +222,6 @@
super::addInstanceAlignMask();
}
- void addParentMetadataRef(ClassDecl *forClass, Type classType) {
- if (forClass == Target)
- Layout.Parent = getNextOffset();
- super::addParentMetadataRef(forClass, classType);
- }
-
void noteStartOfGenericRequirements(ClassDecl *forClass) {
if (forClass == Target)
Layout.GenericRequirements = getNextOffset();
@@ -404,11 +374,6 @@
super::addPayloadSize();
}
- void addParentMetadataRef() {
- Layout.Parent = getNextOffset();
- super::addParentMetadataRef();
- }
-
void noteStartOfGenericRequirements() {
Layout.GenericRequirements = getNextOffset();
super::noteStartOfGenericRequirements();
@@ -441,11 +406,6 @@
Scanner(IRGenModule &IGM, StructDecl *decl, StructMetadataLayout &layout)
: super(IGM, decl), Layout(layout) {}
- void addParentMetadataRef() {
- Layout.Parent = getNextOffset();
- super::addParentMetadataRef();
- }
-
void noteStartOfGenericRequirements() {
Layout.GenericRequirements = getNextOffset();
super::noteStartOfGenericRequirements();
diff --git a/lib/IRGen/MetadataLayout.h b/lib/IRGen/MetadataLayout.h
index 1c817ad..42ec292 100644
--- a/lib/IRGen/MetadataLayout.h
+++ b/lib/IRGen/MetadataLayout.h
@@ -120,7 +120,6 @@
class NominalMetadataLayout : public MetadataLayout {
protected:
StoredOffset GenericRequirements;
- StoredOffset Parent;
NominalMetadataLayout(Kind kind) : MetadataLayout(kind) {}
@@ -134,8 +133,6 @@
Offset getGenericRequirementsOffset(IRGenFunction &IGF) const;
- Offset getParentOffset(IRGenFunction &IGF) const;
-
static bool classof(const MetadataLayout *layout) {
return true; // No non-nominal metadata for now.
}
@@ -287,11 +284,6 @@
}
};
-/// Emit the address of the 'parent' slot in the given nominal-type metadata.
-Address emitAddressOfParentMetadataSlot(IRGenFunction &IGF,
- llvm::Value *metadata,
- NominalTypeDecl *decl);
-
/// Emit the address of the field-offset slot in the given class metadata.
Address emitAddressOfClassFieldOffset(IRGenFunction &IGF,
llvm::Value *metadata,
diff --git a/lib/IRGen/MetadataPath.h b/lib/IRGen/MetadataPath.h
index 001cae0..0dd1566 100644
--- a/lib/IRGen/MetadataPath.h
+++ b/lib/IRGen/MetadataPath.h
@@ -61,9 +61,6 @@
// Everything past this point has no index.
- /// The parent metadata of a nominal type.
- NominalParent,
-
/// An impossible path.
Impossible,
};
@@ -102,7 +99,6 @@
case Kind::OutOfLineBaseProtocol:
case Kind::NominalTypeArgumentConformance:
case Kind::NominalTypeArgument:
- case Kind::NominalParent:
return OperationCost::Load;
case Kind::AssociatedConformance:
@@ -144,11 +140,6 @@
Path.push_back(Component(Component::Kind::Impossible));
}
- /// Add a step to this path which gets the parent metadata.
- void addNominalParentComponent() {
- Path.push_back(Component(Component::Kind::NominalParent));
- }
-
/// Add a step to this path which gets the type metadata stored at
/// requirement index n in a generic type metadata.
void addNominalTypeArgumentComponent(unsigned index) {
@@ -208,9 +199,6 @@
for (auto C : Path) {
switch (C.getKind()) {
- case Component::Kind::NominalParent:
- Root = A.createParent(Root);
- continue;
case Component::Kind::NominalTypeArgument:
Root = A.createGenericArgument(C.getPrimaryIndex(), Root);
continue;
diff --git a/lib/IRGen/NominalMetadataVisitor.h b/lib/IRGen/NominalMetadataVisitor.h
index 214032f..3944a4e 100644
--- a/lib/IRGen/NominalMetadataVisitor.h
+++ b/lib/IRGen/NominalMetadataVisitor.h
@@ -67,8 +67,7 @@
GenericTypeRequirements requirements(IGM, typeDecl);
if (requirements.empty()) return;
- auto subs = type->castTo<BoundGenericType>()
- ->getContextSubstitutionMap(IGM.getSwiftModule(),
+ auto subs = type->getContextSubstitutionMap(IGM.getSwiftModule(),
typeDecl);
requirements.enumerateFulfillments(IGM, subs,
[&](unsigned reqtIndex, CanType argType,
diff --git a/lib/IRGen/StructMetadataVisitor.h b/lib/IRGen/StructMetadataVisitor.h
index 3910b75..17dc558 100644
--- a/lib/IRGen/StructMetadataVisitor.h
+++ b/lib/IRGen/StructMetadataVisitor.h
@@ -47,7 +47,6 @@
// StructMetadata header.
asImpl().addNominalTypeDescriptor();
- asImpl().addParentMetadataRef();
// If changing this layout, you must update the magic number in
// emitParentMetadataRef.
@@ -80,7 +79,6 @@
void addMetadataFlags() { addPointer(); }
void addValueWitnessTable() { addPointer(); }
void addNominalTypeDescriptor() { addPointer(); }
- void addParentMetadataRef() { addPointer(); }
void addFieldOffset(VarDecl*) { addPointer(); }
void addGenericArgument(CanType argument) { addPointer(); }
void addGenericWitnessTable(CanType argument, ProtocolConformanceRef conf) {
diff --git a/lib/RemoteAST/RemoteAST.cpp b/lib/RemoteAST/RemoteAST.cpp
index 508f84d..7501eee 100644
--- a/lib/RemoteAST/RemoteAST.cpp
+++ b/lib/RemoteAST/RemoteAST.cpp
@@ -21,6 +21,7 @@
#include "swift/AST/Decl.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
+#include "swift/AST/SubstitutionMap.h"
#include "swift/AST/Types.h"
#include "swift/AST/TypeRepr.h"
#include "swift/Basic/Mangler.h"
@@ -133,6 +134,14 @@
NominalTypeDecl *createNominalTypeDecl(const Demangle::NodePointer &node);
+ Type createNominalType(NominalTypeDecl *decl) {
+ // If the declaration is generic, fail.
+ if (decl->isGenericContext())
+ return Type();
+
+ return decl->getDeclaredType();
+ }
+
Type createNominalType(NominalTypeDecl *decl, Type parent) {
// If the declaration is generic, fail.
if (decl->getGenericParams())
@@ -145,6 +154,36 @@
return NominalType::get(decl, parent, Ctx);
}
+ Type createBoundGenericType(NominalTypeDecl *decl, ArrayRef<Type> args) {
+ // If the declaration isn't generic, fail.
+ if (!decl->isGenericContext())
+ return Type();
+
+ // Build a SubstitutionMap.
+ auto *genericSig = decl->getGenericSignature();
+ auto genericParams = genericSig->getSubstitutableParams();
+ if (genericParams.size() != args.size())
+ return Type();
+
+ auto subMap = genericSig->getSubstitutionMap(
+ [&](SubstitutableType *t) -> Type {
+ for (unsigned i = 0, e = genericParams.size(); i < e; ++i) {
+ if (t->isEqual(genericParams[i]))
+ return args[i];
+ }
+ return Type();
+ },
+ // FIXME: Wrong module
+ LookUpConformanceInModule(decl->getParentModule()));
+
+ auto origType = decl->getDeclaredInterfaceType();
+
+ // FIXME: We're not checking that the type satisfies the generic
+ // requirements of the signature here.
+ auto substType = origType.subst(subMap);
+ return substType;
+ }
+
Type createBoundGenericType(NominalTypeDecl *decl, ArrayRef<Type> args,
Type parent) {
// If the declaration isn't generic, fail.
diff --git a/lib/SIL/SILBuilder.cpp b/lib/SIL/SILBuilder.cpp
index 6916902..06d7bff 100644
--- a/lib/SIL/SILBuilder.cpp
+++ b/lib/SIL/SILBuilder.cpp
@@ -416,6 +416,12 @@
I->getNumTypeDependentOperands() == 0) {
// All the open instructions are single-value instructions.
auto SVI = dyn_cast<SingleValueInstruction>(I->getOperand(0));
+ // Within SimplifyCFG this function may be called for an instruction
+ // within unreachable code. And within an unreachable block it can happen
+ // that defs do not dominate uses (because there is no dominance defined).
+ // To avoid the infinite loop when following the chain of instructions via
+ // their operands, bail if the operand is not an instruction or this
+ // instruction was seen already.
if (!SVI || !Visited.insert(SVI).second)
return;
// If it is a definition of an opened archetype,
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index 4a51087..dbb400d 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -100,6 +100,9 @@
assert(getRepresentation() == SILFunctionTypeRepresentation::WitnessMethod);
auto selfTy = getSelfInstanceType();
if (auto paramTy = dyn_cast<GenericTypeParamType>(selfTy)) {
+ auto superclass = GenericSig->getSuperclassBound(paramTy, M);
+ if (superclass)
+ return nullptr;
assert(paramTy->getDepth() == 0 && paramTy->getIndex() == 0);
auto protos = GenericSig->getConformsTo(paramTy, M);
assert(protos.size() == 1);
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 9871d2f..829c219 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -2695,7 +2695,7 @@
builder.addRequirement(newRequirement, source, nullptr);
GenericSignature *genericSig =
- std::move(builder).computeGenericSignature(SourceLoc(),
+ builder.computeGenericSignature(SourceLoc(),
/*allowConcreteGenericParams=*/true);
genericEnv = genericSig->createGenericEnvironment(*mod);
diff --git a/lib/SILOptimizer/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp
index cf413e4..736ca54 100644
--- a/lib/SILOptimizer/PassManager/PassManager.cpp
+++ b/lib/SILOptimizer/PassManager/PassManager.cpp
@@ -291,12 +291,12 @@
assert(analysesUnlocked() && "Expected all analyses to be unlocked!");
- PrettyStackTraceSILFunctionTransform X(SFT, NumPassesRun);
- DebugPrintEnabler DebugPrint(NumPassesRun);
-
SFT->injectPassManager(this);
SFT->injectFunction(F);
+ PrettyStackTraceSILFunctionTransform X(SFT, NumPassesRun);
+ DebugPrintEnabler DebugPrint(NumPassesRun);
+
// If nothing changed since the last run of this pass, we can skip this
// pass.
CompletedPasses &completedPasses = CompletedPassesMap[F];
@@ -440,12 +440,12 @@
const SILOptions &Options = getOptions();
- PrettyStackTraceSILModuleTransform X(SMT, NumPassesRun);
- DebugPrintEnabler DebugPrint(NumPassesRun);
-
SMT->injectPassManager(this);
SMT->injectModule(Mod);
+ PrettyStackTraceSILModuleTransform X(SMT, NumPassesRun);
+ DebugPrintEnabler DebugPrint(NumPassesRun);
+
updateSILModuleStatsBeforeTransform(*Mod, SMT, *this, NumPassesRun);
CurrentPassHasInvalidated = false;
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index b2fa942..d841f25 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -800,7 +800,7 @@
}
auto NewGenSig =
- std::move(Builder).computeGenericSignature(SourceLoc(),
+ Builder.computeGenericSignature(SourceLoc(),
/*allowConcreteGenericParams=*/true);
auto NewGenEnv = NewGenSig->createGenericEnvironment(*M.getSwiftModule());
return { NewGenEnv, NewGenSig };
@@ -1490,7 +1490,7 @@
// Finalize the archetype builder.
auto GenSig =
- std::move(Builder).computeGenericSignature(SourceLoc(),
+ Builder.computeGenericSignature(SourceLoc(),
/*allowConcreteGenericParams=*/true);
auto GenEnv = GenSig->createGenericEnvironment(*M.getSwiftModule());
return { GenEnv, GenSig };
diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp
index a175413..c6aa9fa 100644
--- a/lib/Sema/CSBindings.cpp
+++ b/lib/Sema/CSBindings.cpp
@@ -123,6 +123,40 @@
llvm_unreachable("Unhandled ConstraintKind in switch.");
}
+void ConstraintSystem::PotentialBindings::addPotentialBinding(
+ PotentialBinding binding, bool allowJoinMeet) {
+ assert(!binding.BindingType->is<ErrorType>());
+
+ // If this is a non-defaulted supertype binding,
+ // check whether we can combine it with another
+ // supertype binding by computing the 'join' of the types.
+ if (binding.Kind == AllowedBindingKind::Supertypes &&
+ !binding.BindingType->hasTypeVariable() && !binding.DefaultedProtocol &&
+ !binding.isDefaultableBinding() && allowJoinMeet) {
+ if (lastSupertypeIndex) {
+ // Can we compute a join?
+ auto &lastBinding = Bindings[*lastSupertypeIndex];
+ auto lastType = lastBinding.BindingType->getWithoutSpecifierType();
+ auto bindingType = binding.BindingType->getWithoutSpecifierType();
+ auto join = Type::join(lastType, bindingType);
+ if (join) {
+ auto anyType = join->getASTContext().TheAnyType;
+ if (!join->isEqual(anyType) || lastType->isEqual(anyType) ||
+ bindingType->isEqual(anyType)) {
+ // Replace the last supertype binding with the join. We're done.
+ lastBinding.BindingType = join;
+ return;
+ }
+ }
+ }
+
+ // Record this as the most recent supertype index.
+ lastSupertypeIndex = Bindings.size();
+ }
+
+ Bindings.push_back(std::move(binding));
+}
+
/// \brief Retrieve the set of potential type bindings for the given
/// representative type variable, along with flags indicating whether
/// those types should be opened.
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index bea32ae..d2b84a8 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -3289,18 +3289,42 @@
patternElt.first->setType(patternElt.second);
for (auto paramDeclElt : ParamDeclTypes)
- if (!paramDeclElt.first->hasType())
- paramDeclElt.first->setType(paramDeclElt.second);
+ if (!paramDeclElt.first->hasType()) {
+ paramDeclElt.first->setType(getParamBaseType(paramDeclElt));
+ }
for (auto paramDeclIfaceElt : ParamDeclInterfaceTypes)
- if (!paramDeclIfaceElt.first->hasInterfaceType())
- paramDeclIfaceElt.first->setInterfaceType(paramDeclIfaceElt.second);
+ if (!paramDeclIfaceElt.first->hasInterfaceType()) {
+ paramDeclIfaceElt.first->setInterfaceType(
+ getParamBaseType(paramDeclIfaceElt));
+ }
if (!PossiblyInvalidDecls.empty())
for (auto D : PossiblyInvalidDecls)
if (D->hasInterfaceType())
D->setInvalid(D->getInterfaceType()->hasError());
}
+
+ private:
+ static Type getParamBaseType(std::pair<ParamDecl *, Type> &storedParam) {
+ ParamDecl *param;
+ Type storedType;
+
+ std::tie(param, storedType) = storedParam;
+
+ // FIXME: We are currently in process of removing `InOutType`
+ // so `VarDecl::get{Interface}Type` is going to wrap base
+ // type into `InOutType` if its flag indicates that it's
+ // an `inout` parameter declaration. But such type can't
+ // be restored directly using `VarDecl::set{Interface}Type`
+ // caller needs additional logic to extract base type.
+ if (auto *IOT = storedType->getAs<InOutType>()) {
+ assert(param->isInOut());
+ return IOT->getObjectType();
+ }
+
+ return storedType;
+ }
};
} // end anonymous namespace
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 727f365..24c5854 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -2118,6 +2118,12 @@
ctor->getAttrs().add(clonedAttr);
}
+ // Inherit the @_inlineable attribute.
+ if (superclassCtor->getAttrs().hasAttribute<InlineableAttr>()) {
+ auto *clonedAttr = new (ctx) InlineableAttr(/*implicit=*/true);
+ ctor->getAttrs().add(clonedAttr);
+ }
+
// Make sure the constructor is only as available as its superclass's
// constructor.
AvailabilityInference::applyInferredAvailableAttrs(ctor, superclassCtor, ctx);
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index c106aa4..a5cae21 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -2629,39 +2629,7 @@
/// \brief Add a potential binding to the list of bindings,
/// coalescing supertype bounds when we are able to compute the meet.
void addPotentialBinding(PotentialBinding binding,
- bool allowJoinMeet = true) {
- assert(!binding.BindingType->is<ErrorType>());
-
- // If this is a non-defaulted supertype binding,
- // check whether we can combine it with another
- // supertype binding by computing the 'join' of the types.
- if (binding.Kind == AllowedBindingKind::Supertypes &&
- !binding.BindingType->hasTypeVariable() &&
- !binding.DefaultedProtocol && !binding.isDefaultableBinding() &&
- allowJoinMeet) {
- if (lastSupertypeIndex) {
- // Can we compute a join?
- auto &lastBinding = Bindings[*lastSupertypeIndex];
- auto lastType = lastBinding.BindingType->getWithoutSpecifierType();
- auto bindingType = binding.BindingType->getWithoutSpecifierType();
- auto join = Type::join(lastType, bindingType);
- if (join) {
- auto anyType = join->getASTContext().TheAnyType;
- if (!join->isEqual(anyType) || lastType->isEqual(anyType) ||
- bindingType->isEqual(anyType)) {
- // Replace the last supertype binding with the join. We're done.
- lastBinding.BindingType = join;
- return;
- }
- }
- }
-
- // Record this as the most recent supertype index.
- lastSupertypeIndex = Bindings.size();
- }
-
- Bindings.push_back(std::move(binding));
- }
+ bool allowJoinMeet = true);
void dump(llvm::raw_ostream &out,
unsigned indent = 0) const LLVM_ATTRIBUTE_USED {
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index 072e9ae..63d7375 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -1851,8 +1851,7 @@
Builder.addRequirement(&req, DC->getParentModule());
// Check the result.
- (void)std::move(Builder).computeGenericSignature(
- attr->getLocation(),
+ (void)Builder.computeGenericSignature(attr->getLocation(),
/*allowConcreteGenericParams=*/true);
}
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index a9db914..e85686f 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -7117,8 +7117,11 @@
}
void visitDestructorDecl(DestructorDecl *DD) {
- if (DD->isInvalid()) {
+ auto enclosingClass = dyn_cast<ClassDecl>(DD->getDeclContext());
+ if (DD->isInvalid() ||
+ enclosingClass == nullptr) {
DD->setInterfaceType(ErrorType::get(TC.Context));
+ DD->setInvalid();
return;
}
@@ -7140,10 +7143,13 @@
TC.checkDeclAttributesEarly(DD);
if (!DD->hasAccess()) {
- auto enclosingClass = cast<ClassDecl>(DD->getParent());
DD->setAccess(enclosingClass->getFormalAccess());
}
+ if (enclosingClass->getAttrs().hasAttribute<VersionedAttr>()) {
+ DD->getAttrs().add(new (TC.Context) VersionedAttr(/*implicit=*/true));
+ }
+
configureImplicitSelf(TC, DD);
if (DD->getDeclContext()->getGenericSignatureOfContext()) {
@@ -7664,25 +7670,13 @@
break;
}
-
- case DeclKind::Func: {
- typeCheckDecl(D, true);
- break;
- }
+ case DeclKind::Func:
case DeclKind::Subscript:
case DeclKind::Constructor:
- typeCheckDecl(D, true);
- break;
-
case DeclKind::Destructor:
case DeclKind::EnumElement: {
- if (auto container = dyn_cast<NominalTypeDecl>(D->getDeclContext())) {
- validateDecl(container);
- typeCheckDecl(D, true);
- } else {
- D->setInterfaceType(ErrorType::get(Context));
- }
+ typeCheckDecl(D, true);
break;
}
}
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index 25b90cd..949f618 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -136,19 +136,20 @@
DeclContext *DC,
SourceRange baseRange,
ComponentIdentTypeRepr *ref) {
- auto baseEquivClass =
- builder.resolveEquivalenceClass(
- baseTy,
- ArchetypeResolutionKind::CompleteWellFormed);
- assert(baseEquivClass && "Unknown base type?");
+ // Resolve the base to a potential archetype.
+ auto basePA =
+ builder.resolveArchetype(baseTy,
+ ArchetypeResolutionKind::CompleteWellFormed);
+ assert(basePA && "Missing potential archetype for base");
- // Look for a nested type with the given name.
- if (auto nestedType =
- baseEquivClass->lookupNestedType(ref->getIdentifier())) {
- // Record the type we found.
- ref->setValue(nestedType, nullptr);
- } else {
- // Resolve the base to a potential archetype.
+ // Retrieve the potential archetype for the nested type.
+ auto nestedPA =
+ basePA->getNestedType(ref->getIdentifier(),
+ ArchetypeResolutionKind::CompleteWellFormed,
+ builder);
+
+ // If there was no such nested type, produce an error.
+ if (!nestedPA) {
// Perform typo correction.
LookupResult corrections;
tc.performTypoCorrection(DC, DeclRefKind::Ordinary,
@@ -188,6 +189,11 @@
// Correct to the single type result.
ref->overwriteIdentifier(singleType->getBaseName().getIdentifier());
ref->setValue(singleType, nullptr);
+ } else if (auto assocType = nestedPA->getResolvedAssociatedType()) {
+ ref->setValue(assocType, nullptr);
+ } else {
+ assert(nestedPA->getConcreteTypeDecl());
+ ref->setValue(nestedPA->getConcreteTypeDecl(), nullptr);
}
// If the nested type has been resolved to an associated type, use it.
@@ -211,7 +217,7 @@
return concrete->getDeclaredInterfaceType().subst(subMap);
}
- if (auto superclass = baseEquivClass->superclass) {
+ if (auto superclass = basePA->getSuperclass()) {
return superclass->getTypeOfMember(
DC->getParentModule(), concrete,
concrete->getDeclaredInterfaceType());
@@ -746,6 +752,13 @@
if (auto gp = func->getGenericParams()) {
prepareGenericParamList(gp, func);
+ // Collect the generic parameters.
+ SmallVector<GenericTypeParamType *, 4> allGenericParams;
+ if (auto parentSig = func->getDeclContext()->getGenericSignatureOfContext())
+ allGenericParams.append(parentSig->getGenericParams().begin(),
+ parentSig->getGenericParams().end());
+ addGenericParamTypes(gp, allGenericParams);
+
// Create the generic signature builder.
GenericSignatureBuilder builder(Context, LookUpConformance(*this, func));
@@ -755,9 +768,8 @@
if (checkGenericFuncSignature(*this, &builder, func, dependentResolver))
invalid = true;
- // The generic function signature is complete and well-formed. Determine
- // the type of the generic function.
- sig = std::move(builder).computeGenericSignature(func->getLoc());
+ // Finalize the generic requirements.
+ (void)builder.finalize(func->getLoc(), allGenericParams);
// The generic signature builder now has all of the requirements, although
// there might still be errors that have not yet been diagnosed. Revert the
@@ -766,10 +778,16 @@
if (gp)
revertGenericParamList(gp);
- // Debugging of the generic signature.
+ // The generic function signature is complete and well-formed. Determine
+ // the type of the generic function.
+ sig = builder.getGenericSignature();
+
+ // Debugging of the generic signature builder and generic signature
+ // generation.
if (Context.LangOpts.DebugGenericSignatures) {
func->dumpRef(llvm::errs());
llvm::errs() << "\n";
+ builder.dump(llvm::errs());
llvm::errs() << "Generic signature: ";
sig->print(llvm::errs());
llvm::errs() << "\n";
@@ -969,9 +987,15 @@
if (auto *gp = subscript->getGenericParams()) {
prepareGenericParamList(gp, subscript);
+ // Collect the generic parameters.
+ SmallVector<GenericTypeParamType *, 4> allGenericParams;
+ if (auto parentSig = subscript->getDeclContext()->getGenericSignatureOfContext())
+ allGenericParams.append(parentSig->getGenericParams().begin(),
+ parentSig->getGenericParams().end());
+ addGenericParamTypes(gp, allGenericParams);
+
// Create the generic signature builder.
- GenericSignatureBuilder builder(Context,
- LookUpConformance(*this, subscript));
+ GenericSignatureBuilder builder(Context, LookUpConformance(*this, subscript));
// Type check the function declaration, treating all generic type
// parameters as dependent, unresolved.
@@ -980,9 +1004,8 @@
dependentResolver))
invalid = true;
- // The generic subscript signature is complete and well-formed. Determine
- // the type of the generic subscript.
- sig = std::move(builder).computeGenericSignature(subscript->getLoc());
+ // Finalize the generic requirements.
+ (void)builder.finalize(subscript->getLoc(), allGenericParams);
// The generic signature builder now has all of the requirements, although
// there might still be errors that have not yet been diagnosed. Revert the
@@ -990,10 +1013,16 @@
revertGenericSubscriptSignature(subscript);
revertGenericParamList(gp);
- // Debugging of generic signature generation.
+ // The generic subscript signature is complete and well-formed. Determine
+ // the type of the generic subscript.
+ sig = builder.getGenericSignature();
+
+ // Debugging of the generic signature builder and generic signature
+ // generation.
if (Context.LangOpts.DebugGenericSignatures) {
subscript->dumpRef(llvm::errs());
llvm::errs() << "\n";
+ builder.dump(llvm::errs());
llvm::errs() << "Generic signature: ";
sig->print(llvm::errs());
llvm::errs() << "\n";
@@ -1119,10 +1148,10 @@
/// Perform any necessary requirement inference.
inferRequirements(builder);
- // Record the generic type parameter types and the requirements.
- sig = std::move(builder).computeGenericSignature(
- genericParams->getSourceRange().Start,
- allowConcreteGenericParams);
+ // Finalize the generic requirements.
+ (void)builder.finalize(genericParams->getSourceRange().Start,
+ allGenericParams,
+ allowConcreteGenericParams);
// The generic signature builder now has all of the requirements, although
// there might still be errors that have not yet been diagnosed. Revert the
@@ -1136,11 +1165,15 @@
revertGenericParamList(genericParams);
}
+ // Record the generic type parameter types and the requirements.
+ sig = builder.getGenericSignature();
+
// Debugging of the generic signature builder and generic signature
// generation.
if (Context.LangOpts.DebugGenericSignatures) {
dc->printContext(llvm::errs());
llvm::errs() << "\n";
+ builder.dump(llvm::errs());
llvm::errs() << "Generic signature: ";
sig->print(llvm::errs());
llvm::errs() << "\n";
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 686557d..d730a4a 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -1156,8 +1156,7 @@
// Produce the generic signature and environment.
// FIXME: Pass in a source location for the conformance, perhaps? It seems
// like this could fail.
- syntheticSignature =
- std::move(builder).computeGenericSignature(SourceLoc());
+ syntheticSignature = builder.computeGenericSignature(SourceLoc());
syntheticEnvironment = syntheticSignature->createGenericEnvironment(
*conformanceDC->getParentModule());
}
diff --git a/stdlib/public/Reflection/MetadataSource.cpp b/stdlib/public/Reflection/MetadataSource.cpp
index 59c989c..7278c53 100644
--- a/stdlib/public/Reflection/MetadataSource.cpp
+++ b/stdlib/public/Reflection/MetadataSource.cpp
@@ -87,13 +87,6 @@
closeForm();
}
- void
- visitParentMetadataSource(const ParentMetadataSource *P) {
- printHeader("parent_of");
- printRec(P->getChild());
- closeForm();
- }
-
void visitSelfMetadataSource(const SelfMetadataSource *S) {
printHeader("self");
closeForm();
diff --git a/stdlib/public/core/Equatable.swift b/stdlib/public/core/Equatable.swift
index a72e3a2..a00c38d 100644
--- a/stdlib/public/core/Equatable.swift
+++ b/stdlib/public/core/Equatable.swift
@@ -236,10 +236,7 @@
public func === (lhs: AnyObject?, rhs: AnyObject?) -> Bool {
switch (lhs, rhs) {
case let (l?, r?):
- return Bool(Builtin.cmp_eq_RawPointer(
- Builtin.bridgeToRawPointer(Builtin.castToUnknownObject(l)),
- Builtin.bridgeToRawPointer(Builtin.castToUnknownObject(r))
- ))
+ return ObjectIdentifier(l) == ObjectIdentifier(r)
case (nil, nil):
return true
default:
diff --git a/stdlib/public/core/VarArgs.swift b/stdlib/public/core/VarArgs.swift
index b521f81..5a2adb8 100644
--- a/stdlib/public/core/VarArgs.swift
+++ b/stdlib/public/core/VarArgs.swift
@@ -168,6 +168,12 @@
}
}
+extension Bool : CVarArg {
+ public var _cVarArgEncoding: [Int] {
+ return _encodeBitsAsWords(Int32(self ? 1:0))
+ }
+}
+
extension Int64 : CVarArg, _CVarArgAligned {
/// Transform `self` into a series of machine words that can be
/// appropriately interpreted by C varargs.
diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp
index d36c04f..423b096 100644
--- a/stdlib/public/runtime/Demangle.cpp
+++ b/stdlib/public/runtime/Demangle.cpp
@@ -30,13 +30,107 @@
swift::_swift_buildDemanglingForMetadata(const Metadata *type,
Demangle::Demangler &Dem);
+static Demangle::NodePointer
+_applyGenericArguments(const Metadata * const *genericArgs,
+ const NominalTypeDescriptor *description,
+ Demangle::NodePointer node, unsigned depth,
+ Demangle::Demangler &Dem) {
+ assert(depth > 0);
+
+ auto typeNode = node;
+ if (typeNode->getKind() == Node::Kind::Type)
+ typeNode = typeNode->getChild(0);
+
+ auto parentNode = typeNode->getChild(0);
+
+ // It might be more accurate to keep this sugar, but the old version
+ // of this function dropped it, and I want to keep things compatible.
+ if (parentNode->getKind() == Node::Kind::Extension) {
+ parentNode = parentNode->getChild(1);
+ }
+
+ switch (parentNode->getKind()) {
+ case Node::Kind::Class:
+ case Node::Kind::Structure:
+ case Node::Kind::Enum: {
+ // The parent type is a nominal type which may have its own generic
+ // arguments.
+ auto newParentNode = _applyGenericArguments(genericArgs, description,
+ parentNode, depth - 1,
+ Dem);
+ if (newParentNode == nullptr)
+ return nullptr;
+
+ auto newTypeNode = Dem.createNode(typeNode->getKind());
+ newTypeNode->addChild(newParentNode, Dem);
+ newTypeNode->addChild(typeNode->getChild(1), Dem);
+
+ typeNode = newTypeNode;
+ break;
+ }
+ default:
+ // Parent is a local context or module. Leave it as-is, and just apply
+ // generic arguments below.
+ break;
+ }
+
+ // See if we have any generic arguments at this depth.
+ unsigned numArgumentsAtDepth =
+ description->GenericParams.getContext(depth - 1).NumPrimaryParams;
+ if (numArgumentsAtDepth == 0) {
+ // No arguments here, just return the original node (except we may have
+ // replaced its parent type above).
+ return typeNode;
+ }
+
+ // Ok, we have generic arguments. Figure out where the arguments for this
+ // depth begin in the generic type metadata.
+ unsigned firstArgumentAtDepth = 0;
+ for (unsigned i = 0; i < depth - 1; i++) {
+ firstArgumentAtDepth +=
+ description->GenericParams.getContext(i).NumPrimaryParams;
+ }
+
+ // Demangle them.
+ auto typeParams = Dem.createNode(Node::Kind::TypeList);
+ for (unsigned i = firstArgumentAtDepth,
+ e = firstArgumentAtDepth + numArgumentsAtDepth;
+ i < e; ++i) {
+ auto demangling = _swift_buildDemanglingForMetadata(genericArgs[i], Dem);
+ if (demangling == nullptr)
+ return nullptr;
+ typeParams->addChild(demangling, Dem);
+ }
+
+ Node::Kind boundGenericKind;
+ switch (typeNode->getKind()) {
+ case Node::Kind::Class:
+ boundGenericKind = Node::Kind::BoundGenericClass;
+ break;
+ case Node::Kind::Structure:
+ boundGenericKind = Node::Kind::BoundGenericStructure;
+ break;
+ case Node::Kind::Enum:
+ boundGenericKind = Node::Kind::BoundGenericEnum;
+ break;
+ default:
+ return nullptr;
+ }
+
+ auto newNode = Dem.createNode(Node::Kind::Type);
+ newNode->addChild(typeNode, Dem);
+
+ auto genericNode = Dem.createNode(boundGenericKind);
+ genericNode->addChild(newNode, Dem);
+ genericNode->addChild(typeParams, Dem);
+ return genericNode;
+}
+
// Build a demangled type tree for a nominal type.
static Demangle::NodePointer
_buildDemanglingForNominalType(const Metadata *type, Demangle::Demangler &Dem) {
using namespace Demangle;
- const Metadata *parent;
- Node::Kind boundGenericKind;
const NominalTypeDescriptor *description;
// Demangle the parent type, if any.
@@ -48,23 +142,17 @@
while (classType->isTypeMetadata() && classType->isArtificialSubclass())
classType = classType->SuperClass;
#endif
- parent = classType->getParentType(classType->getDescription());
- boundGenericKind = Node::Kind::BoundGenericClass;
description = classType->getDescription();
break;
}
case MetadataKind::Enum:
case MetadataKind::Optional: {
auto enumType = static_cast<const EnumMetadata *>(type);
- parent = enumType->Parent;
- boundGenericKind = Node::Kind::BoundGenericEnum;
description = enumType->Description;
break;
}
case MetadataKind::Struct: {
auto structType = static_cast<const StructMetadata *>(type);
- parent = structType->Parent;
- boundGenericKind = Node::Kind::BoundGenericStructure;
description = structType->Description;
break;
}
@@ -76,42 +164,13 @@
auto node = Dem.demangleType(StringRef(description->Name));
assert(node->getKind() == Node::Kind::Type);
- // Demangle the parent.
- if (parent) {
- auto parentNode = _swift_buildDemanglingForMetadata(parent, Dem);
- if (parentNode->getKind() == Node::Kind::Type)
- parentNode = parentNode->getChild(0);
+ auto typeBytes = reinterpret_cast<const char *>(type);
+ auto genericArgs = reinterpret_cast<const Metadata * const *>(
+ typeBytes + sizeof(void*) * description->GenericParams.Offset);
- auto typeNode = node->getChild(0);
- auto newTypeNode = Dem.createNode(typeNode->getKind());
- newTypeNode->addChild(parentNode, Dem);
- newTypeNode->addChild(typeNode->getChild(1), Dem);
-
- auto newNode = Dem.createNode(Node::Kind::Type);
- newNode->addChild(newTypeNode, Dem);
- node = newNode;
- }
-
- // If generic, demangle the type parameters.
- if (description->GenericParams.NumPrimaryParams > 0) {
- auto typeParams = Dem.createNode(Node::Kind::TypeList);
- auto typeBytes = reinterpret_cast<const char *>(type);
- auto genericParam = reinterpret_cast<const Metadata * const *>(
- typeBytes + sizeof(void*) * description->GenericParams.Offset);
- for (unsigned i = 0, e = description->GenericParams.NumPrimaryParams;
- i < e; ++i, ++genericParam) {
- auto demangling = _swift_buildDemanglingForMetadata(*genericParam, Dem);
- if (demangling == nullptr)
- return nullptr;
- typeParams->addChild(demangling, Dem);
- }
-
- auto genericNode = Dem.createNode(boundGenericKind);
- genericNode->addChild(node, Dem);
- genericNode->addChild(typeParams, Dem);
- return genericNode;
- }
- return node;
+ return _applyGenericArguments(genericArgs, description, node,
+ description->GenericParams.NestingDepth,
+ Dem);
}
// Build a demangled type tree for a type.
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index d5875ac..fbfad19 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -221,8 +221,7 @@
pattern->AddressPoint;
auto patternMetadata = reinterpret_cast<const ValueMetadata*>(patternBytes);
metadata->Description = patternMetadata->Description.get();
- metadata->Parent = patternMetadata->Parent;
-
+
return metadata;
}
@@ -1329,13 +1328,6 @@
auto &description = ancestor->getDescription();
auto &genericParams = description->GenericParams;
- // Copy the parent type.
- if (genericParams.Flags.hasParent()) {
- memcpy(classWords + genericParams.Offset - 1,
- superWords + genericParams.Offset - 1,
- sizeof(uintptr_t));
- }
-
// Copy the generic requirements.
if (genericParams.hasGenericRequirements()) {
unsigned numParamWords = genericParams.NumGenericRequirements;
diff --git a/test/Generics/associated_type_typo.swift b/test/Generics/associated_type_typo.swift
index 4ac5b86..f023418 100644
--- a/test/Generics/associated_type_typo.swift
+++ b/test/Generics/associated_type_typo.swift
@@ -34,6 +34,13 @@
// expected-error@+1{{'T' does not have a member type named 'Assocp2'; did you mean 'AssocP2'?}}{{39-46=AssocP2}}
func typoAssoc4<T : P2>(_: T) where T.Assocp2.assoc : P3 {}
+
+// CHECK-GENERIC-LABEL: .typoAssoc4@
+// CHECK-GENERIC-NEXT: Requirements:
+// CHECK-GENERIC-NEXT: τ_0_0 : P2 [τ_0_0: Explicit @ {{.*}}:21]
+// CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2 : P1 [τ_0_0: Explicit @ {{.*}}:21 -> Protocol requirement (via Self.AssocP2 in P2)
+// CHECK-GENERIC-NEXT: Potential archetypes
+
// <rdar://problem/19620340>
func typoFunc1<T : P1>(x: TypoType) { // expected-error{{use of undeclared type 'TypoType'}}
diff --git a/test/Generics/protocol_type_aliases.swift b/test/Generics/protocol_type_aliases.swift
index 9c083d4..afb2661 100644
--- a/test/Generics/protocol_type_aliases.swift
+++ b/test/Generics/protocol_type_aliases.swift
@@ -14,6 +14,10 @@
}
// CHECK-LABEL: .requirementOnNestedTypeAlias@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : Q [τ_0_0: Explicit @ 22:51]
+// CHECK-NEXT: τ_0_0[.Q].B : P [τ_0_0: Explicit @ 22:51 -> Protocol requirement (via Self.B in Q)
+// CHECK-NEXT: τ_0_0[.Q].B[.P].A == Int [τ_0_0[.Q].B[.P].X: Explicit @ 22:62]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q, τ_0_0.B.A == Int>
func requirementOnNestedTypeAlias<T>(_: T) where T: Q, T.B.X == Int {}
@@ -29,10 +33,20 @@
}
// CHECK-LABEL: .requirementOnConcreteNestedTypeAlias@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : Q2 [τ_0_0: Explicit @ 42:59]
+// CHECK-NEXT: τ_0_0[.Q2].B : P2 [τ_0_0: Explicit @ 42:59 -> Protocol requirement (via Self.B in Q2)
+// CHECK-NEXT: τ_0_0[.Q2].C == S<T.B.A> [τ_0_0[.Q2].C: Explicit]
+// CHECK-NEXT: τ_0_0[.Q2].B[.P2].X == S<T.B.A> [τ_0_0[.Q2].B[.P2].X: Concrete type binding]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0.C == S<τ_0_0.B.A>>
func requirementOnConcreteNestedTypeAlias<T>(_: T) where T: Q2, T.C == T.B.X {}
// CHECK-LABEL: .concreteRequirementOnConcreteNestedTypeAlias@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : Q2 [τ_0_0: Explicit @ 51:67]
+// CHECK-NEXT: τ_0_0[.Q2].B : P2 [τ_0_0: Explicit @ 51:67 -> Protocol requirement (via Self.B in Q2)
+// CHECK-NEXT: τ_0_0[.Q2].C == τ_0_0[.Q2].B[.P2].A [τ_0_0[.Q2].C: Explicit]
+// CHECK-NEXT: τ_0_0[.Q2].B[.P2].X == S<T.B.A> [τ_0_0[.Q2].B[.P2].X: Concrete type binding]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0.C == τ_0_0.B.A>
func concreteRequirementOnConcreteNestedTypeAlias<T>(_: T) where T: Q2, S<T.C> == T.B.X {}
diff --git a/test/Generics/requirement_inference.swift b/test/Generics/requirement_inference.swift
index 391c9b4..ac124ae 100644
--- a/test/Generics/requirement_inference.swift
+++ b/test/Generics/requirement_inference.swift
@@ -72,14 +72,16 @@
struct V<T : Canidae> {}
// CHECK-LABEL: .inferSuperclassRequirement1@
-// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Canidae>
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : Canidae
func inferSuperclassRequirement1<T : Carnivora>(
_ v: V<T>) {}
// expected-warning@-2{{redundant superclass constraint 'T' : 'Carnivora'}}
// expected-note@-2{{superclass constraint 'T' : 'Canidae' inferred from type here}}
// CHECK-LABEL: .inferSuperclassRequirement2@
-// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Canidae>
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : Canidae
func inferSuperclassRequirement2<T : Canidae>(_ v: U<T>) {}
// ----------------------------------------------------------------------------
@@ -108,17 +110,33 @@
struct Model_P3_P4_Eq<T : P3, U : P4> where T.P3Assoc == U.P4Assoc {}
-func inferSameType1<T, U>(_ x: Model_P3_P4_Eq<T, U>) {
- let u: U.P4Assoc? = nil
- let _: T.P3Assoc? = u!
-}
+// CHECK-LABEL: .inferSameType1@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Inferred @ {{.*}}:32]
+// CHECK-NEXT: τ_0_1 : P4 [τ_0_1: Inferred @ {{.*}}:32]
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [τ_0_1: Inferred @ {{.*}}:32 -> Protocol requirement (via Self.P4Assoc in P4)
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Inferred @ {{.*}}:32 -> Protocol requirement (via Self.P3Assoc in P3)
+// FIXME: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [τ_0_0: Inferred]
+func inferSameType1<T, U>(_ x: Model_P3_P4_Eq<T, U>) { }
+// CHECK-LABEL: .inferSameType2@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:25]
+// CHECK-NEXT: τ_0_1 : P4 [τ_0_1: Explicit @ {{.*}}:33]
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [τ_0_1: Explicit @ {{.*}}:33 -> Protocol requirement (via Self.P4Assoc in P4)
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Explicit @ {{.*}}:25 -> Protocol requirement (via Self.P3Assoc in P3)
+// CHECK-NEXT: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [τ_0_0[.P3].P3Assoc: Explicit]
func inferSameType2<T : P3, U : P4>(_: T, _: U) where U.P4Assoc : P2, T.P3Assoc == U.P4Assoc {}
// expected-warning@-1{{redundant conformance constraint 'T.P3Assoc': 'P2'}}
// expected-note@-2{{conformance constraint 'T.P3Assoc': 'P2' implied here}}
-func inferSameType3<T : PCommonAssoc1>(_: T) where T.CommonAssoc : P1, T : PCommonAssoc2 {
-}
+// CHECK-LABEL: .inferSameType3@
+// CHECK-NEXT: Requirements:
+// CHECK-NEXT: τ_0_0 : PCommonAssoc1 [τ_0_0: Explicit @ {{.*}}:25]
+// CHECK-NEXT: τ_0_0 : PCommonAssoc2 [τ_0_0: Explicit @ {{.*}}:74]
+// CHECK-NEXT: τ_0_0[.PCommonAssoc1].CommonAssoc : P1 [τ_0_0[.PCommonAssoc1].CommonAssoc: Explicit @ {{.*}}:66]
+// CHECK-NEXT: Potential archetypes
+func inferSameType3<T : PCommonAssoc1>(_: T) where T.CommonAssoc : P1, T : PCommonAssoc2 {}
protocol P5 {
associatedtype Element
diff --git a/test/Generics/superclass_constraint.swift b/test/Generics/superclass_constraint.swift
index b27d7af..d02efc5 100644
--- a/test/Generics/superclass_constraint.swift
+++ b/test/Generics/superclass_constraint.swift
@@ -67,6 +67,10 @@
}
// CHECK: superclassConformance1
+// CHECK: Requirements:
+// CHECK-NEXT: τ_0_0 : C [τ_0_0: Explicit @ {{.*}}:11]
+// CHECK-NEXT: τ_0_0 : _NativeClass [τ_0_0: Explicit @ {{.*}}:11 -> Derived]
+// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:11 -> Superclass (C: P3)]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C>
func superclassConformance1<T>(t: T)
where T : C, // expected-note{{conformance constraint 'T': 'P3' implied here}}
@@ -75,6 +79,10 @@
// CHECK: superclassConformance2
+// CHECK: Requirements:
+// CHECK-NEXT: τ_0_0 : C [τ_0_0: Explicit @ {{.*}}:11]
+// CHECK-NEXT: τ_0_0 : _NativeClass [τ_0_0: Explicit @ {{.*}}:11 -> Derived]
+// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:11 -> Superclass (C: P3)]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C>
func superclassConformance2<T>(t: T)
where T : C, // expected-note{{conformance constraint 'T': 'P3' implied here}}
@@ -85,6 +93,10 @@
class C2 : C, P4 { }
// CHECK: superclassConformance3
+// CHECK: Requirements:
+// CHECK-NEXT: τ_0_0 : C2 [τ_0_0: Explicit @ {{.*}}:61]
+// CHECK-NEXT: τ_0_0 : _NativeClass [τ_0_0: Explicit @ {{.*}}:46 -> Derived]
+// CHECK-NEXT: τ_0_0 : P4 [τ_0_0: Explicit @ {{.*}}:61 -> Superclass (C2: P4)]
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : C2>
func superclassConformance3<T>(t: T) where T : C, T : P4, T : C2 {}
// expected-warning@-1{{redundant superclass constraint 'T' : 'C'}}
diff --git a/test/IRGen/associated_type_witness.swift b/test/IRGen/associated_type_witness.swift
index 47e64cf..5b1f25e 100644
--- a/test/IRGen/associated_type_witness.swift
+++ b/test/IRGen/associated_type_witness.swift
@@ -51,21 +51,21 @@
// Associated type metadata access function for Fulfilled.Assoc.
// CHECK-LABEL: define internal %swift.type* @_T023associated_type_witness9FulfilledVyxGAA8AssockedA2A1PRzAA1QRzl5AssocWt(%swift.type* %"Fulfilled<T>", i8** %"Fulfilled<T>.Assocked")
// CHECK: [[T0:%.*]] = bitcast %swift.type* %"Fulfilled<T>" to %swift.type**
-// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 3
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 2
// CHECK-NEXT: [[T2:%.*]] = load %swift.type*, %swift.type** [[T1]], align 8, !invariant.load
// CHECK-NEXT: ret %swift.type* [[T2]]
// Associated type witness table access function for Fulfilled.Assoc : P.
// CHECK-LABEL: define internal i8** @_T023associated_type_witness9FulfilledVyxGAA8AssockedA2A1PRzAA1QRzl5AssocAaFPWT(%swift.type* %"Fulfilled<T>.Assoc", %swift.type* %"Fulfilled<T>", i8** %"Fulfilled<T>.Assocked")
// CHECK: [[T0:%.*]] = bitcast %swift.type* %"Fulfilled<T>" to i8***
-// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 4
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 3
// CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** [[T1]], align 8, !invariant.load
// CHECK-NEXT: ret i8** [[T2]]
// Associated type witness table access function for Fulfilled.Assoc : Q.
// CHECK-LABEL: define internal i8** @_T023associated_type_witness9FulfilledVyxGAA8AssockedA2A1PRzAA1QRzl5AssocAaGPWT(%swift.type* %"Fulfilled<T>.Assoc", %swift.type* %"Fulfilled<T>", i8** %"Fulfilled<T>.Assocked")
// CHECK: [[T0:%.*]] = bitcast %swift.type* %"Fulfilled<T>" to i8***
-// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 5
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 4
// CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** [[T1]], align 8, !invariant.load
// CHECK-NEXT: ret i8** [[T2]]
@@ -108,10 +108,10 @@
// CHECK-NEXT: ret %swift.type* [[T0]]
// CHECK: fetch:
// CHECK-NEXT: [[T0:%.*]] = bitcast %swift.type* %"Computed<T, U>" to %swift.type**
-// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 3
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 2
// CHECK-NEXT: [[T:%.*]] = load %swift.type*, %swift.type** [[T1]], align 8, !invariant.load
// CHECK: [[T0:%.*]] = bitcast %swift.type* %"Computed<T, U>" to %swift.type**
-// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 4
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 3
// CHECK-NEXT: [[U:%.*]] = load %swift.type*, %swift.type** [[T1]], align 8, !invariant.load
// CHECK-NEXT: [[FETCH_RESULT]] = call %swift.type* @_T023associated_type_witness4PairVMa(%swift.type* [[T]], %swift.type* [[U]])
// CHECK-NEXT: store atomic %swift.type* [[FETCH_RESULT]], %swift.type** [[CACHE]] release, align 8
diff --git a/test/IRGen/class_bounded_generics.swift b/test/IRGen/class_bounded_generics.swift
index 184f8ae..573a13b 100644
--- a/test/IRGen/class_bounded_generics.swift
+++ b/test/IRGen/class_bounded_generics.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir -primary-file %s -disable-objc-attr-requires-foundation-module | %FileCheck %s
+// RUN: %target-swift-frontend -emit-ir -primary-file %s -disable-objc-attr-requires-foundation-module | %FileCheck %s
// REQUIRES: CPU=x86_64
// XFAIL: linux
@@ -9,7 +9,7 @@
protocol ClassBound2 : class {
func classBoundMethod2()
}
-protocol ClassBoundBinary : class, ClassBound {
+protocol ClassBoundBinary : ClassBound {
func classBoundBinaryMethod(_ x: Self)
}
@objc protocol ObjCClassBound {
@@ -214,7 +214,7 @@
}
// CHECK-LABEL: define hidden swiftcc { i64, %objc_object*, i64 } @_T022class_bounded_generics0A28_generic_field_struct_fields{{[_0-9a-zA-Z]*}}F(i64, %objc_object*, i64, %swift.type* %T, i8** %T.ClassBound)
-func class_generic_field_struct_fields<T : ClassBound>
+func class_generic_field_struct_fields<T>
(_ x:ClassGenericFieldStruct<T>) -> (Int, T, Int) {
return (x.x, x.y, x.z)
}
@@ -226,7 +226,7 @@
}
// CHECK-LABEL: define hidden swiftcc { i64, %objc_object*, i64 } @_T022class_bounded_generics0a15_generic_field_A7_fields{{[_0-9a-zA-Z]*}}F(%T22class_bounded_generics017ClassGenericFieldD0C*)
-func class_generic_field_class_fields<T : ClassBound>
+func class_generic_field_class_fields<T>
(_ x:ClassGenericFieldClass<T>) -> (Int, T, Int) {
return (x.x, x.y, x.z)
// CHECK: getelementptr inbounds %T22class_bounded_generics017ClassGenericFieldD0C, %T22class_bounded_generics017ClassGenericFieldD0C* %0, i32 0, i32 1
@@ -273,3 +273,36 @@
s = S.init()
}
}
+
+// CHECK-LABEL: define hidden swiftcc void @_T022class_bounded_generics14takes_metatypeyxmlF(%swift.type*, %swift.type* %T)
+func takes_metatype<T>(_: T.Type) {}
+
+// CHECK-LABEL: define hidden swiftcc void @_T022class_bounded_generics023archetype_with_generic_A11_constraintyx1t_tAA1ACyq_GRbzr0_lF(%T22class_bounded_generics1AC.2*, %swift.type* %T)
+// CHECK: [[ISA_ADDR:%.*]] = bitcast %T22class_bounded_generics1AC.2* %0 to %swift.type**
+// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
+// CHECK-NEXT: call swiftcc void @_T022class_bounded_generics14takes_metatypeyxmlF(%swift.type* %T, %swift.type* %T)
+// CHECK-NEXT: [[ISA_PTR:%.*]] = bitcast %swift.type* [[ISA]] to %swift.type**
+// CHECK-NEXT: [[U_ADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[ISA_PTR]], i64 10
+// CHECK-NEXT: [[U:%.*]] = load %swift.type*, %swift.type** [[U_ADDR]]
+// CHECK-NEXT: call swiftcc void @_T022class_bounded_generics14takes_metatypeyxmlF(%swift.type* %U, %swift.type* %U)
+// CHECK: ret void
+
+func archetype_with_generic_class_constraint<T, U>(t: T) where T : A<U> {
+ takes_metatype(T.self)
+ takes_metatype(U.self)
+}
+
+// CHECK-LABEL: define hidden swiftcc void @_T022class_bounded_generics029calls_archetype_with_generic_A11_constraintyAA1ACyxG1a_tlF(%T22class_bounded_generics1AC*) #0 {
+// CHECK: [[ISA_ADDR:%.*]] = getelementptr inbounds %T22class_bounded_generics1AC, %T22class_bounded_generics1AC* %0, i32 0, i32 0, i32 0
+// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
+// CHECK: [[SELF:%.*]] = bitcast %T22class_bounded_generics1AC* %0 to %T22class_bounded_generics1AC.2*
+// CHECK-NEXT: [[ISA_PTR:%.*]] = bitcast %swift.type* [[ISA]] to %swift.type**
+// CHECK-NEXT: [[T_ADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[ISA_PTR]], i64 10
+// CHECK-NEXT: [[T:%.*]] = load %swift.type*, %swift.type** [[T_ADDR]]
+// CHECK-NEXT: [[A_OF_T:%.*]] = call %swift.type* @_T022class_bounded_generics1ACMa(%swift.type* [[T]])
+// CHECK-NEXT: call swiftcc void @_T022class_bounded_generics023archetype_with_generic_A11_constraintyx1t_tAA1ACyq_GRbzr0_lF(%T22class_bounded_generics1AC.2* [[SELF]], %swift.type* [[A_OF_T]])
+// CHECK: ret void
+
+func calls_archetype_with_generic_class_constraint<T>(a: A<T>) {
+ archetype_with_generic_class_constraint(t: a)
+}
diff --git a/test/IRGen/enum.sil b/test/IRGen/enum.sil
index 6985832..e6d1f54 100644
--- a/test/IRGen/enum.sil
+++ b/test/IRGen/enum.sil
@@ -107,75 +107,86 @@
// CHECK: [[DYNAMICSINGLETON_FIELD_NAMES:@.*]] = private constant [7 x i8] c"value\00\00"
// CHECK: [[DYNAMICSINGLETON_NAME:@.*]] = private constant [25 x i8] c"4enum16DynamicSingletonO\00"
// CHECK: @_T04enum16DynamicSingletonOMn = hidden constant <{ {{.*}} i32 }> <{
-// CHECK: [25 x i8]* [[DYNAMICSINGLETON_NAME]]
+// CHECK-SAME: [25 x i8]* [[DYNAMICSINGLETON_NAME]]
// -- One payload
-// CHECK: i32 1,
+// CHECK-SAME: i32 1,
// -- No empty cases
-// CHECK: i32 0,
+// CHECK-SAME: i32 0,
// -- Case names
-// CHECK: [[DYNAMICSINGLETON_FIELD_NAMES]]
+// CHECK-SAME: [[DYNAMICSINGLETON_FIELD_NAMES]]
// -- Case type accessor
-// CHECK: @get_field_types_DynamicSingleton
+// CHECK-SAME: @get_field_types_DynamicSingleton
// -- generic parameter vector offset
-// CHECK: i32 3,
+// CHECK-SAME: i32 2,
// -- generic parameter vector length; witness table counts
-// CHECK: i32 1, i32 0
-// CHECK: }>
+// CHECK-SAME: i32 1, i32 1
+// -- nesting depth
+// CHECK-SAME: i16 1
+// -- flags
+// CHECK-SAME: i16 0
+// -- generic parameters at depth 0
+// CHECK-SAME: i32 1
+// CHECK-SAME: }>
// CHECK: @_T04enum16DynamicSingletonOMP = internal global <{ {{.*}}, [16 x i8*] }> <{
-// CHECK: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSingleton
-// CHECK: @_T04enum16DynamicSingletonOMn
-// CHECK: i8* null
-// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum16DynamicSingletonOwxs to i8*)
-// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum16DynamicSingletonOwxg to i8*)
+// CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSingleton
+// CHECK-SAME: @_T04enum16DynamicSingletonOMn
+// CHECK-SAME: i8* null
+// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum16DynamicSingletonOwxs to i8*)
+// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum16DynamicSingletonOwxg to i8*)
// -- No-payload enums have extra inhabitants in
// their value witness table.
// CHECK: @_T04enum10NoPayloadsOWV = internal constant [16 x i8*] [
// -- ...
// -- size
-// CHECK: i8* inttoptr ([[WORD:i32|i64]] 1 to i8*),
+// CHECK-SAME: i8* inttoptr ([[WORD:i32|i64]] 1 to i8*),
// -- flags 0x24_0000 - alignment 1, has extra inhabitants and enum witnesses
-// CHECK: i8* inttoptr ([[WORD]] 2359296 to i8*),
+// CHECK-SAME: i8* inttoptr ([[WORD]] 2359296 to i8*),
// -- stride
-// CHECK: i8* inttoptr ([[WORD]] 1 to i8*),
+// CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*),
// -- num extra inhabitants (256 - 3 valid states)
-// CHECK: i8* inttoptr ([[WORD]] 253 to i8*)
+// CHECK-SAME: i8* inttoptr ([[WORD]] 253 to i8*)
// -- storeExtraInhabitant
-// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum10NoPayloadsOwxs to i8*)
+// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum10NoPayloadsOwxs to i8*)
// -- getExtraInhabitantIndex
-// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum10NoPayloadsOwxg to i8*)
-// CHECK: ]
+// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum10NoPayloadsOwxg to i8*)
+// CHECK-SAME: ]
// -- Single-payload enums take unused extra inhabitants from their payload
// as their own.
// CHECK: @_T04enum19SinglePayloadNestedOWV = internal constant [16 x i8*] [
// -- ...
// -- size
-// CHECK: i8* inttoptr ([[WORD]] 1 to i8*),
+// CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*),
// -- flags 0x4_0000 - alignment 1, has extra inhabitants
-// CHECK: i8* inttoptr ([[WORD]] 2359296 to i8*),
+// CHECK-SAME: i8* inttoptr ([[WORD]] 2359296 to i8*),
// -- stride
-// CHECK: i8* inttoptr ([[WORD]] 1 to i8*),
+// CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*),
// -- num extra inhabitants (253 from payload - 3 empty cases)
-// CHECK: i8* inttoptr ([[WORD]] 250 to i8*)
+// CHECK-SAME: i8* inttoptr ([[WORD]] 250 to i8*)
// -- storeExtraInhabitant
-// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum19SinglePayloadNestedOwxs to i8*)
+// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum19SinglePayloadNestedOwxs to i8*)
// -- getExtraInhabitantIndex
-// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum19SinglePayloadNestedOwxg to i8*)
-// CHECK: ]
+// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum19SinglePayloadNestedOwxg to i8*)
+// CHECK-SAME: ]
// CHECK: @_T04enum20DynamicSinglePayloadOMP = internal global <{ {{.*}}, [16 x i8*] }> <{
-// CHECK: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSinglePayload
-// CHECK: i8* null
-// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum20DynamicSinglePayloadOwxs to i8*)
-// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum20DynamicSinglePayloadOwxg to i8*)
+// CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSinglePayload
+// CHECK-SAME: i8* null
+// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum20DynamicSinglePayloadOwxs to i8*)
+// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum20DynamicSinglePayloadOwxg to i8*)
// CHECK: @_T04enum18MultiPayloadNestedOWV = internal constant [16 x i8*] [
-// CHECK: i8* inttoptr ([[WORD]] 9 to i8*),
-// CHECK: i8* inttoptr ([[WORD]] 16 to i8*)
-// CHECK: ]
+// -- size
+// CHECK-32-SAME: i8* inttoptr ([[WORD]] 5 to i8*),
+// CHECK-64-SAME: i8* inttoptr ([[WORD]] 9 to i8*),
+// -- flags 0x250003 - alignment 4
+// CHECK-32-SAME: i8* inttoptr ([[WORD]] {{2424835|2097155}} to i8*)
+// -- flags 0x200007 - alignment 8
+// CHECK-64-SAME: i8* inttoptr ([[WORD]] 2097159 to i8*)
+// CHECK-SAME: ]
enum Empty {}
@@ -2660,10 +2671,10 @@
// CHECK: [[T:%T]] = load %swift.type*, %swift.type** [[T0]],
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata(%swift.type_pattern* %0, i8** %1)
// CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
-// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 3
+// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 2
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[T]] to i8*
// CHECK: store i8* [[T0]], i8** [[T1]]
-// CHECK: [[VWT:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 5
+// CHECK: [[VWT:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 4
// CHECK: [[T0:%.*]] = bitcast i8** [[VWT]] to i8*
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -1
// CHECK: store i8* [[T0]], i8** [[T1]]
diff --git a/test/IRGen/enum_resilience.swift b/test/IRGen/enum_resilience.swift
index e58ee04..f2f4ece 100644
--- a/test/IRGen/enum_resilience.swift
+++ b/test/IRGen/enum_resilience.swift
@@ -254,7 +254,7 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc %swift.type* @_T014resilient_enum32ResilientMultiPayloadGenericEnumO0B11_resilienceE16getTypeParameterxmyF(%swift.type* %"ResilientMultiPayloadGenericEnum<T>", %swift.opaque* noalias nocapture swiftself)
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* %"ResilientMultiPayloadGenericEnum<T>" to %swift.type**
-// CHECK-NEXT: [[T_ADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[METADATA]], [[INT]] 3
+// CHECK-NEXT: [[T_ADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[METADATA]], [[INT]] 2
// CHECK-NEXT: [[T:%.*]] = load %swift.type*, %swift.type** [[T_ADDR]]
public func getTypeParameter() -> T.Type {
return T.self
diff --git a/test/IRGen/enum_value_semantics.sil b/test/IRGen/enum_value_semantics.sil
index 734169d..1f1800c 100644
--- a/test/IRGen/enum_value_semantics.sil
+++ b/test/IRGen/enum_value_semantics.sil
@@ -119,7 +119,6 @@
// CHECK-SAME: i8** getelementptr inbounds ([16 x i8*], [16 x i8*]* @_T020enum_value_semantics20SinglePayloadTrivialOWV, i32 0, i32 0),
// CHECK-SAME: i64 2,
// CHECK-SAME: {{.*}}* @_T020enum_value_semantics20SinglePayloadTrivialOMn
-// CHECK-SAME: %swift.type* null
// CHECK-SAME: }>
@@ -150,13 +149,12 @@
// CHECK-SAME: i8** getelementptr inbounds ([16 x i8*], [16 x i8*]* @_T020enum_value_semantics23SinglePayloadNontrivialOWV, i32 0, i32 0),
// CHECK-SAME: i64 2,
// CHECK-SAME: {{.*}}* @_T020enum_value_semantics23SinglePayloadNontrivialOMn
-// CHECK-SAME: %swift.type* null
// CHECK-SAME: }>
// CHECK-LABEL: @_T020enum_value_semantics18GenericFixedLayoutOMP = internal global <{{[{].*\* [}]}}> <{
// CHECK: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_GenericFixedLayout
-// CHECK: i32 48, i16 1, i16 8,
+// CHECK: i32 40, i16 1, i16 8,
// CHECK: [16 x i8*] zeroinitializer,
// CHECK: i8** getelementptr inbounds ([16 x i8*], [16 x i8*]* @_T020enum_value_semantics18GenericFixedLayoutOWV, i32 0, i32 0),
// CHECK: i64 2,
diff --git a/test/IRGen/field_type_vectors.sil b/test/IRGen/field_type_vectors.sil
index 9908a8c..e526e07 100644
--- a/test/IRGen/field_type_vectors.sil
+++ b/test/IRGen/field_type_vectors.sil
@@ -13,9 +13,9 @@
// CHECK-LABEL: @_T018field_type_vectors3BarVMn = hidden constant
// CHECK: %swift.type** (%swift.type*)* [[BAR_TYPES_ACCESSOR:@[A-Za-z0-9_]*]]
// CHECK-LABEL: @_T018field_type_vectors3BarVMP = internal global
-// -- There should be 5 words between the address point and the field type
+// -- There should be 4 words between the address point and the field type
// vector slot, with type %swift.type**
-// CHECK: i64, i64, i64, i64, %swift.type*, %swift.type**
+// CHECK: i64, i64, i64, %swift.type*, %swift.type**
struct Bar<T> {
var y: Int
}
@@ -23,9 +23,9 @@
// CHECK-LABEL: @_T018field_type_vectors3BasVMn = hidden constant
// CHECK: %swift.type** (%swift.type*)* [[BAS_TYPES_ACCESSOR:@[A-Za-z0-9_]*]]
// CHECK-LABEL: @_T018field_type_vectors3BasVMP = internal global
-// -- There should be 7 words between the address point and the field type
+// -- There should be 6 words between the address point and the field type
// vector slot, with type %swift.type**
-// CHECK: i64, i64, i64, i64, i64, %swift.type*, %swift.type*, %swift.type**
+// CHECK: i64, i64, i64, %swift.type*, %swift.type*, %swift.type**
struct Bas<T, U> {
var foo: Foo
var bar: Bar<T>
@@ -83,8 +83,8 @@
// CHECK: define{{( protected)?}} private %swift.type** [[BAR_TYPES_ACCESSOR]](%swift.type* %"Bar<T>")
// CHECK: [[T0:%.*]] = bitcast %swift.type* %"Bar<T>" to %swift.type***
-// -- 5 words between the address point and the slot
-// CHECK: [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i32 5
+// -- 4 words between the address point and the slot
+// CHECK: [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i32 4
// CHECK: load %swift.type**, %swift.type*** [[SLOT]], align 8
// CHECK: br
// CHECK-NOT: load %swift.type*,
@@ -93,8 +93,8 @@
// CHECK: define{{( protected)?}} private %swift.type** [[BAS_TYPES_ACCESSOR]](%swift.type* %"Bas<T, U>")
// CHECK: [[T0:%.*]] = bitcast %swift.type* %"Bas<T, U>" to %swift.type***
-// -- 7 words between the address point and the slot
-// CHECK: [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i32 7
+// -- 6 words between the address point and the slot
+// CHECK: [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i32 6
// CHECK: load %swift.type**, %swift.type*** [[SLOT]], align 8
// CHECK: br
// CHECK: store {{.*}} @_T018field_type_vectors3FooVMf
diff --git a/test/IRGen/foreign_types.sil b/test/IRGen/foreign_types.sil
index b52ce5b..ac6281d 100644
--- a/test/IRGen/foreign_types.sil
+++ b/test/IRGen/foreign_types.sil
@@ -4,14 +4,12 @@
import c_layout
// CHECK-LABEL: @_T0SC14HasNestedUnionV18__Unnamed_struct_sVN = linkonce_odr hidden global
-// CHECK-SAME: void (%swift.type*)* @initialize_metadata___Unnamed_struct_s,
// CHECK-SAME: i8* getelementptr inbounds
// CHECK-SAME: %swift.type* null,
-// CHECK-SAME: [[INT:i[0-9]+]] 1,
+// CHECK-SAME: [[INT:i[0-9]+]] 0,
// CHECK-SAME: @_T0SC14HasNestedUnionV18__Unnamed_struct_sVWV
// CHECK-SAME: [[INT]] 1,
// CHECK-SAME: [[INT]] sub ({{.*}}),
-// CHECK-SAME: %swift.type* null,
// CHECK-SAME: [[INT]] 0,
// CHECK-SAME: [[INT]] 4 }
@@ -22,10 +20,3 @@
%ret = tuple ()
return %ret : $()
}
-
-// CHECK-LABEL: define private void @initialize_metadata___Unnamed_struct_s
-// CHECK: [[PARENT:%.*]] = call %swift.type* @_T0SC14HasNestedUnionVMa()
-// CHECK-NEXT: [[T0:%.]] = bitcast %swift.type* %0 to %swift.type**
-// CHECK-NEXT: [[T1:%.]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], [[INT]] 2
-// CHECK-NEXT: store %swift.type* [[PARENT]], %swift.type** [[T1]],
-// CHECK-NEXT: ret void
diff --git a/test/IRGen/generic_classes.sil b/test/IRGen/generic_classes.sil
index e3f4c6f..62ab6c6 100644
--- a/test/IRGen/generic_classes.sil
+++ b/test/IRGen/generic_classes.sil
@@ -27,8 +27,12 @@
// CHECK-SAME: i32 10,
// -- generic parameter count, primary count
// CHECK-SAME: i32 1, i32 1,
+// -- nesting depth
+// CHECK-SAME: i16 1,
// -- flags -- has vtable
-// CHECK-SAME: i32 4,
+// CHECK-SAME: i16 4,
+// -- generic parameters at depth 0
+// CHECK-SAME: i32 1,
// -- vtable offset
// CHECK-SAME: i32 11,
// -- vtable size
diff --git a/test/IRGen/generic_structs.sil b/test/IRGen/generic_structs.sil
index 4d3ee50..1796e4b 100644
--- a/test/IRGen/generic_structs.sil
+++ b/test/IRGen/generic_structs.sil
@@ -12,39 +12,45 @@
// CHECK: [[SINGLEDYNAMIC_FIELDS:@.*]] = private constant [3 x i8] c"x\00\00"
// CHECK: @_T015generic_structs13SingleDynamicVMn = hidden constant <{ {{.*}} i32 }> <{
// -- name
-// CHECK: [34 x i8]* [[SINGLEDYNAMIC_NAME]]
+// CHECK-SAME: [34 x i8]* [[SINGLEDYNAMIC_NAME]]
// -- field count
-// CHECK: i32 1,
+// CHECK-SAME: i32 1,
// -- field offset vector offset
-// CHECK: i32 3,
+// CHECK-SAME: i32 2,
// -- field names
-// CHECK: [3 x i8]* [[SINGLEDYNAMIC_FIELDS]]
+// CHECK-SAME: [3 x i8]* [[SINGLEDYNAMIC_FIELDS]]
// -- generic metadata pattern, kind 1 (struct)
-// CHECK: i32 add ({{.*}}@_T015generic_structs13SingleDynamicVMP{{.*}}, i32 1)
+// CHECK-SAME: i32 add ({{.*}}@_T015generic_structs13SingleDynamicVMP{{.*}}, i32 1)
// -- generic parameter vector offset
-// CHECK: i32 4,
-// -- generic parameter count, primary counts; generic parameter witness counts
-// CHECK: i32 1, i32 1, i32 0
-// CHECK: }>
+// CHECK-SAME: i32 3,
+// -- generic parameter count, primary count
+// CHECK-SAME: i32 1, i32 1
+// -- nesting depth
+// CHECK-SAME: i16 1,
+// -- flags
+// CHECK-SAME: i16 0,
+// -- generic parameters at depth 0
+// CHECK-SAME: i32 1
+// CHECK-SAME: }>
// CHECK: @_T015generic_structs13SingleDynamicVMP = internal global <{ {{.*}} }> <{
// -- template header
-// CHECK: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_SingleDynamic,
-// CHECK: i32 160, i16 1, i16 8, [{{[0-9]+}} x i8*] zeroinitializer,
+// CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_SingleDynamic,
+// CHECK-SAME: i32 152, i16 1, i16 8, [{{[0-9]+}} x i8*] zeroinitializer,
// -- placeholder for vwtable pointer
-// CHECK: i8* null,
+// CHECK-SAME: i8* null,
// -- address point
-// CHECK: i64 1, {{.*}}* @_T015generic_structs13SingleDynamicVMn
+// CHECK-SAME: i64 1, {{.*}}* @_T015generic_structs13SingleDynamicVMn
// -- field offset vector; generic parameter vector
-// CHECK: i64 0, %swift.type* null,
+// CHECK-SAME: i64 0, %swift.type* null,
// -- tail-allocated vwtable pattern
-// CHECK: i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @_T015generic_structs13SingleDynamicVwCP to i8*),
+// CHECK-SAME: i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @_T015generic_structs13SingleDynamicVwCP to i8*),
// -- ...
// -- placeholder for size, flags, stride
-// CHECK: i8* null, i8* null, i8* null
+// CHECK-SAME: i8* null, i8* null, i8* null
// -- extra inhabitants
-// CHECK: i8* null,
-// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T015generic_structs13SingleDynamicVwxs to i8*),
-// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T015generic_structs13SingleDynamicVwxg to i8*)] }>
+// CHECK-SAME: i8* null,
+// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T015generic_structs13SingleDynamicVwxs to i8*),
+// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T015generic_structs13SingleDynamicVwxg to i8*)] }>
// CHECK-NOT: @_T015generic_structs13SingleDynamicVWV
// -- Nominal type descriptor for generic struct with protocol requirements
@@ -57,15 +63,21 @@
// -- field count
// CHECK-SAME: i32 2,
// -- field offset vector offset
-// CHECK-SAME: i32 3,
+// CHECK-SAME: i32 2,
// -- field names
// CHECK-SAME: [5 x i8]* [[DYNAMICWITHREQUIREMENTS_FIELDS]]
// -- generic metadata pattern
// CHECK-SAME: i32 add ({{.*}}@_T015generic_structs23DynamicWithRequirementsVMP{{.*}}, i32 1)
// -- generic parameter vector offset
-// CHECK-SAME: i32 5,
-// -- generic requirements count; generic arguments count; flags; generic parameter witness counts
-// CHECK-SAME: i32 4, i32 2, i32 0
+// CHECK-SAME: i32 4,
+// -- generic requirements count; generic arguments count
+// CHECK-SAME: i32 4, i32 2
+// -- nesting depth
+// CHECK-SAME: i16 1,
+// -- flags
+// CHECK-SAME: i16 0,
+// -- generic parameters at depth 0
+// CHECK-SAME: i32 2
// CHECK-SAME: }>
// CHECK: @_T015generic_structs23DynamicWithRequirementsVMP = internal global <{ {{.*}} }> <{
@@ -75,14 +87,14 @@
// -- Fixed-layout struct metadata contains fixed field offsets
// CHECK: @_T015generic_structs6IntishVMf = internal constant <{ {{.*}} i64 }> <{
-// CHECK: i64 0
-// CHECK: }>
+// CHECK-SAME: i64 0
+// CHECK-SAME: }>
// CHECK: @_T015generic_structs7CharethVMf = internal constant <{ {{.*}} i64 }> <{
-// CHECK: i64 0
-// CHECK: }>
+// CHECK-SAME: i64 0
+// CHECK-SAME: }>
// CHECK: @_T015generic_structs8StringlyVMf = internal constant <{ {{.*}} i64, i64, i64 }> <{
-// CHECK: i64 0, i64 8, i64 16
-// CHECK: }>
+// CHECK-SAME: i64 0, i64 8, i64 16
+// CHECK-SAME: }>
struct SingleDynamic<T> {
var x : T
@@ -134,7 +146,7 @@
%a = struct_element_addr %0 : $*ComplexDynamic<A, B>, #ComplexDynamic.a2
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i64*
- // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 3
+ // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 2
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[FIELD_OFFSET_VECTOR]], i32 2
// CHECK: [[FIELD_OFFSET:%.*]] = load i64, i64* [[FIELD_OFFSET_ADDR]], align 8
// CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8*
@@ -143,7 +155,7 @@
%b = struct_element_addr %0 : $*ComplexDynamic<A, B>, #ComplexDynamic.b
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i64*
- // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 3
+ // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 2
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[FIELD_OFFSET_VECTOR]], i32 3
// CHECK: [[FIELD_OFFSET:%.*]] = load i64, i64* [[FIELD_OFFSET_ADDR]], align 8
// CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8*
@@ -153,7 +165,7 @@
%c = struct_element_addr %5 : $*SingleDynamic<B>, #SingleDynamic.x
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i64*
- // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 3
+ // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 2
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[FIELD_OFFSET_VECTOR]], i32 4
// CHECK: [[FIELD_OFFSET:%.*]] = load i64, i64* [[FIELD_OFFSET_ADDR]], align 8
// CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8*
@@ -204,17 +216,17 @@
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata(%swift.type_pattern* %0, i8** %1)
// CHECK: [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
// Fill type argument.
-// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 4
+// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 3
// CHECK: [[T0:%.*]] = bitcast %swift.type* %T to i8*
// CHECK: store i8* [[T0]], i8** [[T1]], align 8
// Fill vwtable reference.
-// CHECK: [[VWTABLE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 6
+// CHECK: [[VWTABLE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 5
// CHECK: [[VWTABLE_VAL:%.*]] = bitcast i8** [[VWTABLE_ADDR]] to i8*
// CHECK: [[VWTABLE_SLOT_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 -1
// CHECK: store i8* [[VWTABLE_VAL]], i8** [[VWTABLE_SLOT_ADDR]], align 8
// Lay out fields.
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to i64*
-// CHECK: [[T1:%.*]] = getelementptr inbounds i64, i64* [[T0]], i64 3
+// CHECK: [[T1:%.*]] = getelementptr inbounds i64, i64* [[T0]], i64 2
// CHECK: [[T2:%.*]] = getelementptr inbounds i8**, i8*** [[TYPES:%.*]], i32 0
// CHECK: call void @swift_initStructMetadata_UniversalStrategy(i64 1, i8*** [[TYPES]], i64* [[T1]], i8** [[VWTABLE_ADDR]])
// CHECK: ret %swift.type* [[METADATA]]
diff --git a/test/IRGen/generic_vtable.swift b/test/IRGen/generic_vtable.swift
index 00c3cb8..bbba876 100644
--- a/test/IRGen/generic_vtable.swift
+++ b/test/IRGen/generic_vtable.swift
@@ -21,8 +21,12 @@
//// Nominal type descriptor for 'Base' does not have any method descriptors.
// CHECK-LABEL: @_T014generic_vtable4BaseCMn = {{(protected )?}}constant
+// -- nesting depth
+// CHECK-SAME: i16 1,
// -- flags: has vtable
-// CHECK-SAME: i32 4,
+// CHECK-SAME: i16 4,
+// -- generic parameters at depth 0
+// CHECK-SAME: i32 0,
// -- vtable offset
// CHECK-SAME: i32 10,
// -- vtable size
@@ -46,8 +50,12 @@
//// Nominal type descriptor for 'Derived' has method descriptors.
// CHECK-LABEL: @_T014generic_vtable7DerivedCMn = {{(protected )?}}constant
+// -- nesting depth
+// CHECK-SAME: i16 1,
// -- flags: has vtable
-// CHECK-SAME: i32 4,
+// CHECK-SAME: i16 4,
+// -- generic parameters at depth 0
+// CHECK-SAME: i32 1,
// -- vtable offset
// CHECK-SAME: i32 14,
// -- vtable size
@@ -76,8 +84,12 @@
//// Nominal type descriptor for 'Concrete' has method descriptors.
// CHECK-LABEL: @_T014generic_vtable8ConcreteCMn = {{(protected )?}}constant
+// -- nesting depth
+// CHECK-SAME: i16 1,
// -- flags: has vtable
-// CHECK-SAME: i32 4,
+// CHECK-SAME: i16 4,
+// -- generic parameters at depth 0
+// CHECK-SAME: i32 0,
// -- vtable offset
// CHECK-SAME: i32 15,
// -- vtable size
diff --git a/test/IRGen/keypaths.sil b/test/IRGen/keypaths.sil
index b7dbb0e..8e5d64e 100644
--- a/test/IRGen/keypaths.sil
+++ b/test/IRGen/keypaths.sil
@@ -200,8 +200,8 @@
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- struct with runtime-resolved offset
// CHECK-SAME: <i32 0x1ffffffe>,
-// CHECK-32-SAME: i32 12 }>
-// CHECK-64-SAME: i32 24 }>
+// CHECK-32-SAME: i32 8 }>
+// CHECK-64-SAME: i32 16 }>
// -- %j: Gen<A>.y
// CHECK: [[KP_J:@keypath.*]] = private global <{ {{.*}} }> <{
@@ -213,8 +213,8 @@
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- struct with runtime-resolved offset
// CHECK-SAME: <i32 0x1ffffffe>,
-// CHECK-32-SAME: i32 16 }>
-// CHECK-64-SAME: i32 32 }>
+// CHECK-32-SAME: i32 12 }>
+// CHECK-64-SAME: i32 24 }>
// CHECK-LABEL: define{{( protected)?}} swiftcc void @stored_property_fixed_offsets()
sil @stored_property_fixed_offsets : $@convention(thin) () -> () {
diff --git a/test/IRGen/nested_generics.swift b/test/IRGen/nested_generics.swift
new file mode 100644
index 0000000..13bf3e3
--- /dev/null
+++ b/test/IRGen/nested_generics.swift
@@ -0,0 +1,81 @@
+// RUN: %target-swift-frontend %s -emit-ir | %FileCheck %s --check-prefix=CHECK
+
+// REQUIRES: CPU=x86_64
+
+func blah<T>(_: T.Type) {}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T015nested_generics13makeAMetadatayyF()
+public func makeAMetadata() {
+ blah(OuterGenericStruct<Int>.InnerGenericStruct<String>.self)
+ blah(OuterGenericStruct<Int>.InnerConcreteStruct.self)
+
+ blah(OuterGenericClass<Int>.InnerGenericClass<String>.self)
+ blah(OuterGenericClass<Int>.InnerConcreteClass.self)
+}
+
+// Type constructor for OuterGenericStruct<Int>.InnerGenericStruct<String>
+// CHECK-LABEL: define linkonce_odr hidden %swift.type* @_T015nested_generics18OuterGenericStructV05InnerdE0VySi_SSGMa()
+// CHECK: call %swift.type* @_T015nested_generics18OuterGenericStructV05InnerdE0VMa(%swift.type* @_T0SiN, %swift.type* @_T0SSN)
+// CHECK: ret %swift.type
+
+// Type constructor for OuterGenericStruct<T>.InnerGenericStruct<U>
+// CHECK-LABEL: define{{( protected)?}} %swift.type* @_T015nested_generics18OuterGenericStructV05InnerdE0VMa(%swift.type*, %swift.type*)
+
+// Type constructor for OuterGenericStruct<Int>.InnerConcreteStruct
+// CHECK-LABEL: define linkonce_odr hidden %swift.type* @_T015nested_generics18OuterGenericStructV013InnerConcreteE0VySi_GMa()
+// CHECK: call %swift.type* @_T015nested_generics18OuterGenericStructV013InnerConcreteE0VMa(%swift.type* @_T0SiN)
+// CHECK: ret %swift.type
+
+// Type constructor for OuterGenericStruct<T>.InnerConcreteStruct
+// CHECK-LABEL: define{{( protected)?}} %swift.type* @_T015nested_generics18OuterGenericStructV013InnerConcreteE0VMa(%swift.type*)
+
+public struct OuterGenericStruct<T> {
+ public struct InnerGenericStruct<U> {
+ public func method() {
+ blah(T.self)
+ blah(U.self)
+ }
+ }
+
+ public struct InnerConcreteStruct {
+ public func method() {
+ blah(T.self)
+ }
+ }
+}
+
+// Type constructor for OuterGenericClass<Int>.InnerGenericClass<String>
+// CHECK-LABEL: define linkonce_odr hidden %swift.type* @_T015nested_generics17OuterGenericClassC05InnerdE0CySi_SSGMa()
+// CHECK: call %swift.type* @_T015nested_generics17OuterGenericClassC05InnerdE0CMa(%swift.type* @_T0SiN, %swift.type* @_T0SSN)
+
+// Type constructor for OuterGenericClass<T>.InnerGenericClass<U>
+// CHECK-LABEL: define{{( protected)?}} %swift.type* @_T015nested_generics17OuterGenericClassC05InnerdE0CMa(%swift.type*, %swift.type*)
+
+// Type constructor for OuterGenericClass<Int>.InnerConcreteClass
+// CHECK-LABEL: define linkonce_odr hidden %swift.type* @_T015nested_generics17OuterGenericClassC013InnerConcreteE0CySi_GMa()
+// CHECK: call %swift.type* @_T015nested_generics17OuterGenericClassC013InnerConcreteE0CMa(%swift.type* @_T0SiN)
+// CHECK: ret %swift.type
+
+// Type constructor for OuterGenericClass<T>.InnerConcreteClass
+// CHECK-LABEL: define{{( protected)?}} %swift.type* @_T015nested_generics17OuterGenericClassC013InnerConcreteE0CMa(%swift.type*)
+
+// Type constructor for OuterGenericStruct<T>
+// CHECK-LABEL: define{{( protected)?}} %swift.type* @_T015nested_generics18OuterGenericStructVMa(%swift.type*)
+
+// Type constructor for OuterGenericClass<T>
+// CHECK-LABEL: define{{( protected)?}} %swift.type* @_T015nested_generics17OuterGenericClassCMa(%swift.type*)
+
+public class OuterGenericClass<T> {
+ public class InnerGenericClass<U> {
+ public func method() {
+ blah(T.self)
+ blah(U.self)
+ }
+ }
+
+ public class InnerConcreteClass {
+ public func method() {
+ blah(T.self)
+ }
+ }
+}
diff --git a/test/IRGen/nested_types.sil b/test/IRGen/nested_types.sil
index 274a98b..f27fa25 100644
--- a/test/IRGen/nested_types.sil
+++ b/test/IRGen/nested_types.sil
@@ -32,7 +32,5 @@
// CHECK-NEXT: ret %swift.type* [[T4]]
// CHECK-LABEL: define private void @initialize_metadata_Inner
-// CHECK: [[T0:%.*]] = call %swift.type* @_T012nested_types5OuterCMa()
-// CHECK-NEXT: store %swift.type* [[T0]], %swift.type** getelementptr inbounds (%swift.type*, %swift.type** bitcast ({{.*}} @_T012nested_types5OuterC5InnerVMf{{.*}}, [[INT:i[0-9]+]] 2), align
-// CHECK-NEXT: store atomic %swift.type* bitcast ({{.*}} @_T012nested_types5OuterC5InnerVMf{{.*}} to %swift.type*), %swift.type** @_T012nested_types5OuterC5InnerVML release, align
+// CHECK: store atomic %swift.type* bitcast ({{.*}} @_T012nested_types5OuterC5InnerVMf{{.*}} to %swift.type*), %swift.type** @_T012nested_types5OuterC5InnerVML release, align
// CHECK-NEXT: ret void
diff --git a/test/IRGen/struct_resilience.swift b/test/IRGen/struct_resilience.swift
index 7458d97..eed6368 100644
--- a/test/IRGen/struct_resilience.swift
+++ b/test/IRGen/struct_resilience.swift
@@ -59,7 +59,7 @@
// CHECK: [[METADATA:%.*]] = call %swift.type* @_T016resilient_struct9RectangleVMa()
// CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
-// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] 3
+// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] 2
// CHECK-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[FIELD_OFFSET_VECTOR]], i32 2
// CHECK-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
// CHECK-NEXT: [[STRUCT_ADDR:%.*]] = bitcast %T16resilient_struct9RectangleV* %0 to i8*
@@ -116,7 +116,7 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc {{i32|i64}} @_T017struct_resilience26StructWithResilientStorageV1nSivg(%T17struct_resilience26StructWithResilientStorageV* {{.*}})
// CHECK: [[METADATA:%.*]] = call %swift.type* @_T017struct_resilience26StructWithResilientStorageVMa()
// CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
-// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] 3
+// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] 2
// CHECK-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[FIELD_OFFSET_VECTOR]], i32 2
// CHECK-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
// CHECK-NEXT: [[STRUCT_ADDR:%.*]] = bitcast %T17struct_resilience26StructWithResilientStorageV* %0 to i8*
diff --git a/test/SILGen/inlineable_attribute.swift b/test/SILGen/inlineable_attribute.swift
index e747462..9150d51 100644
--- a/test/SILGen/inlineable_attribute.swift
+++ b/test/SILGen/inlineable_attribute.swift
@@ -74,3 +74,20 @@
@_inlineable public func talkAboutAHorse(h: Horse) {
_ = h.gallop
}
+
+@_versioned class Base {
+ @_versioned
+ @_inlineable
+ init(horse: Horse) {}
+}
+
+// CHECK-LABEL: sil [serialized] @_T020inlineable_attribute7DerivedCfd : $@convention(method) (@guaranteed Derived) -> @owned Builtin.NativeObject
+// CHECK-LABEL: sil [serialized] @_T020inlineable_attribute7DerivedCfD : $@convention(method) (@owned Derived) -> ()
+
+// Make sure the synthesized delegating initializer is inlineable also
+
+// CHECK-LABEL: sil [serialized] @_T020inlineable_attribute7DerivedCAcA5HorseC5horse_tcfc : $@convention(method) (@owned Horse, @owned Derived) -> @owned Derived
+@_versioned class Derived : Base {
+ // Allow @_inlineable deinits
+ @_inlineable deinit {}
+}
diff --git a/test/SILGen/versioned_attribute.swift b/test/SILGen/versioned_attribute.swift
new file mode 100644
index 0000000..5a01525
--- /dev/null
+++ b/test/SILGen/versioned_attribute.swift
@@ -0,0 +1,17 @@
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -emit-verbose-sil %s | %FileCheck %s
+
+@_versioned class Horse {
+ var mouth: AnyObject?
+}
+
+@_versioned class GiftHorse {
+ var mouth: AnyObject?
+
+ deinit {}
+}
+
+// CHECK-LABEL: sil @_T019versioned_attribute5HorseCfd : $@convention(method) (@guaranteed Horse) -> @owned Builtin.NativeObject
+// CHECK-LABEL: sil @_T019versioned_attribute5HorseCfD : $@convention(method) (@owned Horse) -> ()
+
+// CHEKC-LABEL: sil @_T019versioned_attribute9GiftHorseCfd : $@convention(method) (@guaranteed GiftHorse) -> @owned Builtin.NativeObject
+// CHECK-LABEL: sil @_T019versioned_attribute9GiftHorseCfD : $@convention(method) (@owned GiftHorse) -> ()
diff --git a/test/decl/protocol/recursive_requirement.swift b/test/decl/protocol/recursive_requirement.swift
index 30cd1a0..736d2af 100644
--- a/test/decl/protocol/recursive_requirement.swift
+++ b/test/decl/protocol/recursive_requirement.swift
@@ -76,14 +76,13 @@
associatedtype Delta: Alpha
}
-// FIXME: Redundancy diagnostics are an indication that we're getting
-// the minimization wrong. The errors prove it :D
+// FIXME: Redundancy diagnostics are odd here.
struct Epsilon<T: Alpha, // expected-note{{conformance constraint 'U': 'Gamma' implied here}}
// expected-warning@-1{{redundant conformance constraint 'T': 'Alpha'}}
U: Gamma> // expected-warning{{redundant conformance constraint 'U': 'Gamma'}}
// expected-note@-1{{conformance constraint 'T': 'Alpha' implied here}}
- where T.Beta == U, // expected-error{{'Beta' is not a member type of 'T'}}
- U.Delta == T {} // expected-error{{'Delta' is not a member type of 'U'}}
+ where T.Beta == U,
+ U.Delta == T {}
// -----
diff --git a/test/stdlib/Inputs/VariadicBool/module.map b/test/stdlib/Inputs/VariadicBool/module.map
new file mode 100644
index 0000000..fa0bef5
--- /dev/null
+++ b/test/stdlib/Inputs/VariadicBool/module.map
@@ -0,0 +1,3 @@
+module VariadicBool {
+ header "variadicBool.h"
+}
diff --git a/test/stdlib/Inputs/VariadicBool/variadicBool.c b/test/stdlib/Inputs/VariadicBool/variadicBool.c
new file mode 100644
index 0000000..95aa6b4
--- /dev/null
+++ b/test/stdlib/Inputs/VariadicBool/variadicBool.c
@@ -0,0 +1,16 @@
+#include "variadicBool.h"
+
+int numberOfTrues(int count, va_list arguments) {
+ int i, total;
+ total = 0;
+
+ for(i = 0; i < count; i++) {
+ //we're passing int here because passing bool is actually incorrect since
+ //bool is actually promoted to int in C
+ if(va_arg(arguments, int) == true) {
+ total += 1;
+ }
+ }
+
+ return total;
+}
\ No newline at end of file
diff --git a/test/stdlib/Inputs/VariadicBool/variadicBool.h b/test/stdlib/Inputs/VariadicBool/variadicBool.h
new file mode 100644
index 0000000..7980068
--- /dev/null
+++ b/test/stdlib/Inputs/VariadicBool/variadicBool.h
@@ -0,0 +1,5 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+extern int numberOfTrues(int count, va_list arguments);
\ No newline at end of file
diff --git a/test/stdlib/TypeName.swift b/test/stdlib/TypeName.swift
index dfb93e4..496bd71 100644
--- a/test/stdlib/TypeName.swift
+++ b/test/stdlib/TypeName.swift
@@ -185,4 +185,28 @@
_typeName(SomeOuterGenericClass<String>.SomeInnerGenericStruct<Int>.self));
}
+extension SomeOuterGenericClass {
+ struct OtherInnerStruct {}
+ struct OtherInnerGenericStruct<U> {}
+}
+
+TypeNameTests.test("NestedInExtension") {
+ expectEqual("main.SomeOuterGenericClass<Swift.Int>.OtherInnerStruct",
+ _typeName(SomeOuterGenericClass<Int>.OtherInnerStruct.self));
+ expectEqual("main.SomeOuterGenericClass<Swift.Int>.OtherInnerGenericStruct<Swift.String>",
+ _typeName(SomeOuterGenericClass<Int>.OtherInnerGenericStruct<String>.self));
+}
+
+extension SomeOuterGenericClass where T == Int {
+ struct AnotherInnerStruct {}
+ struct AnotherInnerGenericStruct<U> {}
+}
+
+TypeNameTests.test("NestedInConstrainedExtension") {
+ expectEqual("main.SomeOuterGenericClass.AnotherInnerStruct",
+ _typeName(SomeOuterGenericClass<Int>.AnotherInnerStruct.self));
+ expectEqual("main.SomeOuterGenericClass.AnotherInnerGenericStruct<Swift.String>",
+ _typeName(SomeOuterGenericClass<Int>.AnotherInnerGenericStruct<String>.self));
+}
+
runAllTests()
diff --git a/unittests/runtime/Metadata.cpp b/unittests/runtime/Metadata.cpp
index d53b6dc..97679b1 100644
--- a/unittests/runtime/Metadata.cpp
+++ b/unittests/runtime/Metadata.cpp
@@ -182,7 +182,7 @@
metadataWords[2] = argsWords[0];
return metadata;
},
- 3 * sizeof(void*), // metadata size
+ 2 * sizeof(void*), // metadata size
1, // num arguments
0, // address point
{} // private data
@@ -191,8 +191,7 @@
// Fields
{
MetadataKind::Struct,
- reinterpret_cast<const NominalTypeDescriptor*>(&Global1),
- nullptr
+ reinterpret_cast<const NominalTypeDescriptor*>(&Global1)
}
};
diff --git a/utils/build-script b/utils/build-script
index c377d7f..7313862 100755
--- a/utils/build-script
+++ b/utils/build-script
@@ -127,7 +127,11 @@
test = (
deployment_platform not in invocation.platforms_to_skip_test)
test_host_only = None
- build_benchmark = build and deployment_target.supports_benchmark
+ dt_supports_benchmark = deployment_target.supports_benchmark
+ build_benchmarks = build and dt_supports_benchmark
+ build_external_benchmarks = all([build, dt_supports_benchmark,
+ args.build_external_benchmarks])
+
# FIXME: Note, `build-script-impl` computed a property here
# w.r.t. testing, but it was actually unused.
@@ -161,13 +165,20 @@
else:
self.swift_stdlib_build_targets.append(
"swift-test-stdlib-" + name)
- if build_benchmark:
+ if build_benchmarks:
self.swift_benchmark_build_targets.append(
"swift-benchmark-" + name)
# FIXME: This probably should respect `args.benchmark`, but
# a typo in build-script-impl meant we always would do this.
self.swift_benchmark_run_targets.append(
"check-swift-benchmark-" + name)
+
+ if build_external_benchmarks:
+ # Add support for the external benchmarks.
+ self.swift_benchmark_build_targets.append(
+ "swift-benchmark-{}-external".format(name))
+ self.swift_benchmark_run_targets.append(
+ "check-swift-benchmark-{}-external".format(name))
if test:
if test_host_only:
suffix = "-non-executable"
@@ -506,6 +517,9 @@
"--skip-build-swift"]
if not args.build_benchmarks:
impl_args += ["--skip-build-benchmarks"]
+ # Currently we do not build external benchmarks by default.
+ if args.build_external_benchmarks:
+ impl_args += ["--skip-build-external-benchmarks=0"]
if not args.build_foundation:
impl_args += ["--skip-build-foundation"]
if not args.build_xctest:
diff --git a/utils/build-script-impl b/utils/build-script-impl
index 0de5738..5a65bba 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -126,6 +126,7 @@
skip-build-libdispatch "" "set to skip building libdispatch"
skip-build-libicu "" "set to skip building libicu"
skip-build-benchmarks "" "set to skip building Swift Benchmark Suite"
+ skip-build-external-benchmarks "1" "set to skip building the external Swift Benchmark Suite. (skipped by default)"
skip-build-playgroundlogger "" "set to skip building PlaygroundLogger"
skip-build-playgroundsupport "" "set to skip building PlaygroundSupport"
skip-test-cmark "" "set to skip testing CommonMark"
@@ -1324,6 +1325,7 @@
local test_this_target=1
local test_host_only=
local build_benchmark_this_target=
+ local build_external_benchmark_this_target=
local test_benchmark_this_target=
case ${stdlib_deployment_target} in
@@ -1352,6 +1354,7 @@
build_for_this_target=$(not ${SKIP_BUILD_OSX})
test_this_target=$(not ${SKIP_TEST_OSX})
build_benchmark_this_target=$(not ${SKIP_BUILD_OSX})
+ build_external_benchmark_this_target=$(not ${SKIP_BUILD_OSX})
test_benchmark_this_target=$(not ${SKIP_BUILD_OSX})
;;
iphoneos-*)
@@ -1363,10 +1366,12 @@
test_this_target=
fi
build_benchmark_this_target=$(not ${SKIP_BUILD_IOS_DEVICE})
+ build_external_benchmark_this_target=$(not ${SKIP_BUILD_IOS_DEVICE})
# Never build iOS armv7s benchmarks.
if [[ "${stdlib_deployment_target}" == "iphoneos-armv7s" ]]; then
build_benchmark_this_target=
+ build_external_benchmark_this_target=
fi
;;
iphonesimulator-x86_64)
@@ -1391,6 +1396,7 @@
test_this_target=
fi
build_benchmark_this_target=$(not ${SKIP_BUILD_TVOS_DEVICE})
+ build_external_benchmark_this_target=$(not ${SKIP_BUILD_TVOS_DEVICE})
;;
appletvsimulator-*)
swift_sdk="TVOS_SIMULATOR"
@@ -1406,6 +1412,7 @@
test_this_target=
fi
build_benchmark_this_target=$(not ${SKIP_BUILD_WATCHOS_DEVICE})
+ build_external_benchmark_this_target=$(not ${SKIP_BUILD_WATCHOS_DEVICE})
;;
watchsimulator-*)
swift_sdk="WATCHOS_SIMULATOR"
@@ -1443,6 +1450,16 @@
SWIFT_RUN_BENCHMARK_TARGETS+=("check-swift-benchmark-${stdlib_deployment_target}")
fi
fi
+
+ if [[ "$(true_false ${SKIP_BUILD_EXTERNAL_BENCHMARKS})" == "FALSE" ]] &&
+ [[ "${build_external_benchmark_this_target}" ]] &&
+ [[ "${is_in_build_list}" ]] ; then
+ SWIFT_BENCHMARK_TARGETS+=("swift-benchmark-${stdlib_deployment_target}-external")
+ if [[ $(not ${SKIP_TEST_BENCHMARK}) ]] ; then
+ SWIFT_RUN_BENCHMARK_TARGETS+=("check-swift-benchmark-${stdlib_deployment_target}-external")
+ fi
+ fi
+
if [[ "${test_this_target}" ]] && [[ "${is_in_build_list}" ]]; then
test_target_suffix=""
if [[ -n "${test_host_only}" ]] ; then
@@ -2098,13 +2115,16 @@
# Don't build benchmarks and tests when building cross compiler.
build_perf_testsuite_this_time=false
+ build_external_perf_testsuite_this_time=false
build_tests_this_time=false
native_llvm_tools_path="$(build_directory "${LOCAL_HOST}" llvm)/bin"
native_clang_tools_path="$(build_directory "${LOCAL_HOST}" llvm)/bin"
native_swift_tools_path="$(build_directory "${LOCAL_HOST}" swift)/bin"
else
+ # FIXME: Why is the next line not using false_true?
build_perf_testsuite_this_time=$(true_false "$(not ${SKIP_BUILD_BENCHMARKS})")
+ build_external_perf_testsuite_this_time=$(false_true "${SKIP_BUILD_EXTERNAL_BENCHMARKS}")
build_tests_this_time=${SWIFT_INCLUDE_TESTS}
fi
@@ -2162,6 +2182,7 @@
-DSWIFT_BUILD_DYNAMIC_SDK_OVERLAY:BOOL=$(true_false "${BUILD_SWIFT_DYNAMIC_SDK_OVERLAY}")
-DSWIFT_BUILD_STATIC_SDK_OVERLAY:BOOL=$(true_false "${BUILD_SWIFT_STATIC_SDK_OVERLAY}")
-DSWIFT_BUILD_PERF_TESTSUITE:BOOL=$(true_false "${build_perf_testsuite_this_time}")
+ -DSWIFT_BUILD_EXTERNAL_PERF_TESTSUITE:BOOL=$(true_false "${build_external_perf_testsuite_this_time}")
-DSWIFT_BUILD_EXAMPLES:BOOL=$(true_false "${BUILD_SWIFT_EXAMPLES}")
-DSWIFT_INCLUDE_TESTS:BOOL=$(true_false "${build_tests_this_time}")
-DSWIFT_INSTALL_COMPONENTS:STRING="${SWIFT_INSTALL_COMPONENTS}"
diff --git a/utils/build_swift/driver_arguments.py b/utils/build_swift/driver_arguments.py
index d7c43d5..7b6e8ef 100644
--- a/utils/build_swift/driver_arguments.py
+++ b/utils/build_swift/driver_arguments.py
@@ -153,6 +153,7 @@
args.build_watchos = False
args.build_android = False
args.build_benchmarks = False
+ args.build_external_benchmarks = False
args.build_lldb = False
args.build_llbuild = False
args.build_swiftpm = False
@@ -771,6 +772,12 @@
action=arguments.action.optional_false,
help="skip building Swift Benchmark Suite")
+ run_build_group.add_argument(
+ "--build-external-benchmarks",
+ dest='build_external_benchmarks',
+ action=arguments.action.optional_true,
+ help="skip building Swift Benchmark Suite")
+
skip_test_group = parser.add_argument_group(
title="Skip testing specified targets")
skip_test_group.add_argument(
diff --git a/validation-test/compiler_crashers_fixed/28816-unreachable-executed-at-swift-lib-sema-typecheckgeneric-cpp-214.swift b/validation-test/compiler_crashers/28816-unreachable-executed-at-swift-lib-sema-typecheckgeneric-cpp-214.swift
similarity index 88%
rename from validation-test/compiler_crashers_fixed/28816-unreachable-executed-at-swift-lib-sema-typecheckgeneric-cpp-214.swift
rename to validation-test/compiler_crashers/28816-unreachable-executed-at-swift-lib-sema-typecheckgeneric-cpp-214.swift
index 02b9326..1c78fe4 100644
--- a/validation-test/compiler_crashers_fixed/28816-unreachable-executed-at-swift-lib-sema-typecheckgeneric-cpp-214.swift
+++ b/validation-test/compiler_crashers/28816-unreachable-executed-at-swift-lib-sema-typecheckgeneric-cpp-214.swift
@@ -5,6 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// RUN: not %target-swift-frontend %s -emit-ir
+// RUN: not --crash %target-swift-frontend %s -emit-ir
protocol b{{}{}class a{{}class A}{}typealias a
init(t:Self.a.a.a
diff --git a/validation-test/compiler_crashers_2_fixed/0119-rdar33613329.swift b/validation-test/compiler_crashers_2_fixed/0119-rdar33613329.swift
new file mode 100644
index 0000000..1d251d6
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0119-rdar33613329.swift
@@ -0,0 +1,45 @@
+// RUN: %target-typecheck-verify-swift %s
+
+precedencegroup BindingPrecedence {
+ higherThan: DefaultPrecedence
+}
+
+infix operator ~>
+infix operator ≈> : BindingPrecedence
+
+struct M<L : P, R> {
+ let f: L
+ let b: (inout L.B) -> R
+
+ init(f: L, b: @escaping (inout L.B) -> R) {
+ self.f = f
+ self.b = b
+ }
+}
+
+protocol P {
+ associatedtype A
+ associatedtype B
+
+ func `in`<R>(_ a: inout A, apply body: (inout B) -> R) -> R
+
+ static func ~> (_: A, _: Self) -> B
+}
+
+extension P {
+ static func ≈> <R>(f: Self, b: @escaping (inout B) -> R) -> M<Self, R> {}
+}
+
+extension WritableKeyPath : P {
+ typealias A = Root
+ typealias B = Value
+
+ func `in`<R>(_ a: inout A, apply body: (inout B) -> R) -> R {}
+
+ static func ~> (a: A, path: WritableKeyPath) -> B {}
+}
+
+struct X { var y: Int = 0 }
+var x = X()
+x ~> \X.y ≈> { a in a += 1; return 3 }
+// expected-error@-1 {{cannot convert call result type 'M<WritableKeyPath<X, Int>, _>' to expected type 'WritableKeyPath<_, _>'}}
diff --git a/validation-test/execution/crashers/rdar18157434.swift b/validation-test/execution/crashers_fixed/rdar33767511.swift
similarity index 90%
rename from validation-test/execution/crashers/rdar18157434.swift
rename to validation-test/execution/crashers_fixed/rdar33767511.swift
index 5d0bfd8..825e4b1 100644
--- a/validation-test/execution/crashers/rdar18157434.swift
+++ b/validation-test/execution/crashers_fixed/rdar33767511.swift
@@ -1,7 +1,7 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: %target-build-swift %s -o %t/a.out
-// RUN: not --crash %target-run %t/a.out
+// RUN: %target-run %t/a.out
// REQUIRES: executable_test
// REQUIRES: OS=macosx
diff --git a/validation-test/stdlib/Bool.swift b/validation-test/stdlib/Bool.swift
new file mode 100644
index 0000000..758f155
--- /dev/null
+++ b/validation-test/stdlib/Bool.swift
@@ -0,0 +1,44 @@
+// RUN: mkdir -p %t
+// RUN: %target-clang -x c %S/Inputs/VariadicBool/variadicBool.c -c -o %t/variadicBool.o
+// RUN: %target-build-swift -I %S/Inputs/VariadicBool/ %t/variadicBool.o %s -o %t/a.out
+// RUN: %target-run %t/a.out
+// REQUIRES: executable_test
+
+
+import Swift
+import StdlibUnittest
+import StdlibCollectionUnittest
+import VariadicBool
+
+func countTrues(_ count: Int, _ bools: CVarArg...) -> Int {
+ return Int(withVaList(bools) { numberOfTrues(Int32(count), $0) })
+}
+
+var BoolTestSuite = TestSuite("Bool")
+
+BoolTestSuite.test("AllTrues") {
+ let result = countTrues(2, true, true)
+ expectEqual(2, result)
+}
+
+BoolTestSuite.test("HalfAndHalf") {
+ let result = countTrues(4, true, true, false, false)
+ expectEqual(2, result)
+}
+
+BoolTestSuite.test("AllFalse") {
+ let result = countTrues(2, false, false)
+ expectEqual(0, result)
+}
+
+BoolTestSuite.test("Interleaved") {
+ let result = countTrues(7, false, true, false, true, false, true, false)
+ expectEqual(3, result)
+}
+
+BoolTestSuite.test("FalsePositive") {
+ let result = countTrues(7, false, true, false, true, false, true, false)
+ expectNotEqual(30, result)
+}
+
+runAllTests()
\ No newline at end of file
diff --git a/validation-test/stdlib/BoolDiagnostics.swift b/validation-test/stdlib/BoolDiagnostics.swift
new file mode 100644
index 0000000..95eee5e
--- /dev/null
+++ b/validation-test/stdlib/BoolDiagnostics.swift
@@ -0,0 +1,7 @@
+// RUN: %target-swift-frontend -typecheck -verify %s
+
+func CVarArgs_withBool() {
+ func varArgFunc(_ x: Bool, _ args: CVarArg...) { }
+ let x = false
+ varArgFunc(x, x)
+}