Files
swift-mirror/test/IRGen/dependent_reabstraction.swift
Slava Pestov 60f437abe1 IRGen: Change witness_method calling convention to take a witness table
This is another incremental step toward protocol resilience.

To support resiliently adding requirements with default implementations,
we need to emit the witness thunk for each default requirement once,
and share it between conformances.

However, the body of the witness thunk can call witness methods from
the conformance of <Self : P>. Formerly, witness thunks were only emitted
with a concrete Self type, so any calls were resolved statically.

Now that Self can be abstract in a witness thunk signature, we have to
pass in the witness table and do the necessary gymnastics on both sides
of the call.

At the call site, the witness table is either abstract, concrete, or
undefined, as follows:

- If the unsubstituted Self type is concrete in the witness method
  signature, no witness table is necessary; this is the case of a
  concrete (non-default) witness thunk.

- If the unsubstituted Self type is abstract and the substituted Self
  type is concrete, the witness table is accessed via direct reference.

- If the unsubstituted Self type is abstract and the substituted Self
  type is also abstract, the witness table comes from type metadata
  that was passed in to the function where the call is taking place.

Inside the body of the witness method thunk, we only bind the witness
table if Self is an abstract type; this rules out the first case above,
where the witness table is not needed and cannot be provided by the
caller.

The result of a SIL witness_method instruction now lowers as an
explosion containing two values, the function pointer itself and
the witness table.

Similarly, partial application thunks now grab the witness table and
package it up in the context.

Special care is taken to support function_ref + apply and
function_ref + partial_apply of @convention(witness_method) callees;
here, we can hit the case where we don't know the original conformance
because the callee is concrete, in which case we just pass in a null
pointer as the witness table.

Witness thunks with an abstract Self currently only work for protocols
without any associated type requirements; to support those, we need
to be able to fulfill associated type metadata from the witness
table for the <Self : P> conformance. This will be addressed as part
of @rjmccall's calling convention work.

Also I didn't make any attempt to support this for @objc protocols that
do not have a witness table. In this case, the extra parameter is not
necessary since we can perform dynamic dispatch on the 'self' value to
call requirements; however, @objc protocols will not support default
implementations, at least not in the near-term.
2016-02-16 01:46:18 -08:00

27 lines
595 B
Swift

// RUN: %target-swift-frontend -emit-ir %s | FileCheck %s
func markUsed<T>(t: T) {}
protocol A {
typealias B
func b(_: B)
}
struct X<Y> : A {
// CHECK-LABEL: define hidden void @_TTWurGV23dependent_reabstraction1Xx_S_1AS_FS1_1bfwx1BT_(%swift.type** noalias nocapture dereferenceable({{.*}}), %V23dependent_reabstraction1X* noalias nocapture, %swift.type* %Self, i8** %SelfWitnessTable)
func b(b: X.Type) {
let x: Any = b
markUsed(b as X.Type)
}
}
func foo<T: A>(x: T, _ y: T.B) {
x.b(y)
}
let a = X<Int>()
let b = X<String>()
foo(a, X<Int>.self)
foo(b, X<String>.self)