mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
SILGen: Emit default arguments as "delayed arguments".
This causes default arguments to get emitted after formal evaluation of `self`, allowing protocol methods to access the opened `Self` type of an existential receiver. Fixes rdar://problem/39524104
This commit is contained in:
File diff suppressed because it is too large
Load Diff
39
test/SILGen/protocol-extension-default-arg-existential.swift
Normal file
39
test/SILGen/protocol-extension-default-arg-existential.swift
Normal file
@@ -0,0 +1,39 @@
|
||||
// RUN: %target-swift-frontend -emit-sil -verify %s
|
||||
|
||||
//
|
||||
// Make sure neither rdar://problem/37031037 (default arguments on protocol extension methods
|
||||
// depend on Self and normally get evaluated before an existential self value
|
||||
// gets opened) nor rdar://problem/39524104 (if you open the existential self
|
||||
// earlier in an attempt to fix this, then you get undesirable exclusivity
|
||||
// conflicts on constructs like `existential.x = existential.y`) regress.
|
||||
//
|
||||
|
||||
protocol MethodWithDefaultArgGenerator {
|
||||
var a: Int { get set }
|
||||
var b: Int { get nonmutating set }
|
||||
|
||||
mutating func mutate(_ x: inout Int)
|
||||
}
|
||||
|
||||
protocol P { static var value: Self { get } }
|
||||
extension Int: P { static var value: Int { return 0 } }
|
||||
|
||||
extension MethodWithDefaultArgGenerator {
|
||||
mutating func foo(_ x: Int = 0) {}
|
||||
|
||||
mutating func reabstracted<T>(_ x: T.Type = T.self) -> T { fatalError() }
|
||||
mutating func indirected<T: P>(_ x: T = T.value) -> T { fatalError() }
|
||||
|
||||
mutating func exploded(x y: (Int, String) = (0, "foo")) {}
|
||||
}
|
||||
func invokeMethodsWithDefaultArgs(x: inout MethodWithDefaultArgGenerator) {
|
||||
x.foo()
|
||||
_ = x.reabstracted() as Int
|
||||
_ = x.indirected() as Int
|
||||
x.exploded()
|
||||
}
|
||||
func checkAgainstExclusivityViolations(x: inout MethodWithDefaultArgGenerator) {
|
||||
x.a = x.a
|
||||
x.mutate(&x.b)
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ func variadicSecond(_ x: Int, _ y: Int...) {}
|
||||
|
||||
var x = 0
|
||||
// CHECK: [[X_ADDR:%.*]] = global_addr @$S20scalar_to_tuple_args1xSivp : $*Int
|
||||
// CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[X_ADDR]] : $*Int
|
||||
// CHECK: [[DEFAULT_Y:%.*]] = apply {{.*}} : $@convention(thin) () -> Int
|
||||
// CHECK: [[DEFAULT_Z:%.*]] = apply {{.*}} : $@convention(thin) () -> Int
|
||||
// CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[X_ADDR]] : $*Int
|
||||
// CHECK: [[INOUT_WITH_DEFAULTS:%.*]] = function_ref @$S20scalar_to_tuple_args17inoutWithDefaults_1y1zySiz_S2itF
|
||||
// CHECK: apply [[INOUT_WITH_DEFAULTS]]([[WRITE]], [[DEFAULT_Y]], [[DEFAULT_Z]])
|
||||
inoutWithDefaults(&x)
|
||||
|
||||
@@ -970,12 +970,12 @@ struct StructWithLayout {
|
||||
// CHECK: [[PROJ:%.*]] = project_box %{{.*}} : ${ var StructWithLayout }, 0
|
||||
// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] %{{.*}}([[PROJ]]) : $@convention(thin) (@inout_aliasable StructWithLayout) -> Bool
|
||||
// CHECK: [[CLOSURE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PA]] : $@callee_guaranteed () -> Bool to $@noescape @callee_guaranteed () -> Bool
|
||||
// call default argument
|
||||
// CHECK: apply %{{.*}}() : $@convention(thin) () -> StaticString
|
||||
// call StaticString.init
|
||||
// CHECK: apply
|
||||
// call UInt.init(_builtinIntegerLiteral:)
|
||||
// CHECK: apply
|
||||
// call default argument
|
||||
// CHECK: apply %{{.*}}() : $@convention(thin) () -> StaticString
|
||||
// call _sanityCheck(_:_:file:line:)
|
||||
// CHECK: apply %{{.*}}([[CLOSURE]], {{.*}})
|
||||
// CHECK: load [trivial] [[PROJ]] : $*StructWithLayout
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
// RUN: %target-swift-frontend -enforce-exclusivity=none -emit-sil -Onone %s -o %t/Onone.sil
|
||||
// RUN: %target-sil-opt %t/Onone.sil -inline -assume-parsing-unqualified-ownership-sil -o %t/inlined.sil
|
||||
// RUN: %FileCheck %s --check-prefix=INLINE < %t/inlined.sil
|
||||
// RUN: not %target-sil-opt -enable-sil-verify-all %t/inlined.sil -enforce-exclusivity=unchecked -diagnose-static-exclusivity -assume-parsing-unqualified-ownership-sil -o /dev/null 2> %t/err.txt
|
||||
// RUN: %FileCheck %s --check-prefix=DIAGNOSE < %t/err.txt
|
||||
// RUN: %target-sil-opt -enable-sil-verify-all %t/inlined.sil -enforce-exclusivity=unchecked -diagnose-static-exclusivity -assume-parsing-unqualified-ownership-sil -o /dev/null
|
||||
|
||||
public protocol SomeP {
|
||||
var someV: Int { get set }
|
||||
@@ -23,15 +22,10 @@ struct Some : SomeP {
|
||||
//
|
||||
// INLINE-LABEL: $S5Onone16testNestedAccessyyF
|
||||
// INLINE: [[OUTER:%.*]] = begin_access [modify] [static] %0 : $*SomeP
|
||||
// INLINE: [[INNERREAD:%.*]] = begin_access [read] [static] [[OUTER]] : $*SomeP
|
||||
// INLINE: [[INNERMOD:%.*]] = begin_access [modify] [static] [[OUTER]] : $*SomeP
|
||||
// INLINE: %{{.*}} = open_existential_addr mutable_access [[INNERMOD]] : $*SomeP to $*@opened("{{.*}}") SomeP
|
||||
// INLINE: [[INNERREAD:%.*]] = begin_access [read] [static] [[OUTER]] : $*SomeP
|
||||
//
|
||||
// DIAGNOSE: error: overlapping accesses, but modification requires exclusive access; consider copying to a local variable
|
||||
// DIAGNOSE: %{{.*}} = begin_access [modify] [static] %0 : $*SomeP
|
||||
// DIAGNOSE: %{{.*}} = begin_access [read] [static] %0 : $*SomeP
|
||||
// DIAGNOSE: %{{.*}} = begin_access [modify] [static] %{{.*}} : $*SomeP
|
||||
// DIAGNOSE: %{{.*}} = begin_access [read] [static] %{{.*}} : $*SomeP
|
||||
public func testNestedAccess() {
|
||||
var s: SomeP = Some()
|
||||
assignNonConflict(&s)
|
||||
|
||||
Reference in New Issue
Block a user