Files
swift-mirror/test/SILGen/dependent_member_lowering.swift
Slava Pestov 6a83e7303e SILGen: Protocol witness thunks don't need public linkage
We used to give witness thunks public linkage if the
conforming type and the protocol are public.

This is completely unnecessary. If the conformance is
fragile, the thunk should be [shared] [serialized],
allowing the thunk to be serialized into callers after
devirtualization.

Otherwise for private protocols or resilient modules,
witness thunks can just always be private.

This should reduce the size of compiled binaries.

There are two other mildly interesting consequences:

1) In the bridged cast tests, we now inline the witness
   thunks from the bridgeable conformances, which removes
   one level of indirection.

2) This uncovered a flaw in our accessibility checking
   model. Usually, we reject a witness that is less
   visible than the protocol; however, we fail to
   reject it in the case that it comes from an
   extension.

   This is because members of an extension can be
   declared 'public' even if the extended type is not
   public, and it appears that in this case the 'public'
   keyword has no effect.

   I would prefer it if a) 'public' generated a warning
   here, and b) the conformance also generated a warning.

   In Swift 4 mode, we could then make this kind of
   sillyness into an error. But for now, live with the
   broken behavior, and add a test to exercise it to ensure
   we don't crash.

   There are other places where this "allow public but
   ignore it, kinda, except respect it in some places"
   behavior causes problems. I don't know if it was intentional
   or just emergent behavior from general messiness in Sema.

3) In the TBD code, there is one less 'failure' because now
   that witness thunks are no longer public, TBDGen does not
   need to reason about them (except for the case #2 above,
   which will probably require a similar workaround in TBDGen
   as what I put into SILGen).
2017-03-30 03:52:57 -07:00

22 lines
878 B
Swift

// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
protocol P {
associatedtype A
func f(_ x: A)
}
struct Foo<T>: P {
typealias A = T.Type
func f(_ t: T.Type) {}
// CHECK-LABEL: sil private [transparent] [thunk] @_T025dependent_member_lowering3FooVyxGAA1PAAlAaEP1fy1AQzFTW : $@convention(witness_method) <τ_0_0> (@in @thick τ_0_0.Type, @in_guaranteed Foo<τ_0_0>) -> ()
// CHECK: bb0(%0 : $*@thick τ_0_0.Type, %1 : $*Foo<τ_0_0>):
}
struct Bar<T>: P {
typealias A = (Int) -> T
func f(_ t: @escaping (Int) -> T) {}
// CHECK-LABEL: sil private [transparent] [thunk] @_T025dependent_member_lowering3BarVyxGAA1PAAlAaEP1fy1AQzFTW : $@convention(witness_method) <τ_0_0> (@in @callee_owned (@in Int) -> @out τ_0_0, @in_guaranteed Bar<τ_0_0>) -> ()
// CHECK: bb0(%0 : $*@callee_owned (@in Int) -> @out τ_0_0, %1 : $*Bar<τ_0_0>):
}