-
Notifications
You must be signed in to change notification settings - Fork 10.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generic subscript materializeForSet emission #7752
Generic subscript materializeForSet emission #7752
Conversation
@swift-ci Please smoke test |
7dd0bab
to
0a3de7c
Compare
@swift-ci Please smoke test |
cef235c
to
9955871
Compare
@swift-ci Please smoke test |
1 similar comment
@swift-ci Please smoke test |
Eventually I'd like SubstitutionLists to be opaque, and not ArrayRefs.
First, use the correct generic environment to compute the substituted storage type. Substitutions derived from 'self' are not enough, because we also want the archetypes of the generic subscript's innermost generic parameters. Also, use the method and witness_method calling conventions for the materializeForSet callback, depending on if we have a protocol witness or concrete implementation. Since the materializeForSet callback is called with a more abstract type at the call site than the actual function type of the callback, we used to rely on these two SIL types being ABI compatible: @convention(thin) <Self : P, T, U) (..., Self.Type) -> () @convention(thin) <T, U> (..., Foo<T, U>.Type) -> () The IRGen lowering is roughly the following -- the call site passes two unused parameters, but that's fine: (..., Self.Type*, Self.Type*, Self.P*) (..., Foo<T, U>.Type*) However if the callback has its own generic parameters because the subscript is generic, we might have SIL types like so, @convention(thin) <Self : P, T, U, V) (..., Self.Type) -> () @convention(thin) <T, U, V> (..., Foo<T, U>.Type) -> () And the IRGen lowering is the following: (..., Self.Type*, Self.Type*, Self.P*, V.Type*) (..., Foo<T, U>.Type*, V.Type*) The parameters no longer line up, because the caller still passes the two discarded arguments, and type metadata for V cannot be derived from the Self metadata so must be passed separately. The witness_method calling convention is designed to solve this problem; it puts the Self metadata and protocol conformance last, so if you have these SIL types: @convention(witness_method) <Self : P, T, U, V) (..., swiftself Self.Type) -> () @convention(witness_method) <T, U, V> (..., swiftself Foo<T, U>.Type) -> () The IRGen lowering is the following: (..., Self.Type*, V.Type*, Self.Type*, Self.P*) (..., Foo<T, U>.Type*, V.Type*, Self.Type*, unused i8*) However, the problem is now that witness_method and thin functions are not ABI compatible, because thin functions don't have a distinguished 'self', which is passed differently in LLVM's swiftcc calling convention: @convention(witness_method) <Self : P, T, U, V) (..., Self.Type) -> () @convention(thin) <T, U, V> (..., Foo<T, U>.Type) -> () So instead of using 'thin' representation for the concrete callback case, use 'method', which is essentially the same as 'thin' except if the last parameter is pointer-size, it is passed as the 'self' value. This makes everything work out.
9955871
to
fa8f2ce
Compare
@swift-ci Please smoke test |
1 similar comment
@swift-ci Please smoke test |
@jckarter I think I finally got this one sorted, and I wrote some comments to explain what (I think) is going on. Mind looking over this to make sure it makes sense? |
cc @rjmccall. This will probably work for now, but we'll need to revisit it if we move to the coroutine model for formal accesses. It seems like we could use a variation of box types that use a fixed-sized buffer to capture the generic environment as part of the context (but that would require completing the implementation work for non-single-element boxes, and adding support for different box representations). |
Follow-up to #7697 that adds materializeForSet emission for generic subscripts. This is required for inout access of polymorphic subscripts defined in classes or protocols.
rdar://problem/21461357