Skip to content
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

Merged

Conversation

slavapestov
Copy link
Contributor

@slavapestov slavapestov commented Feb 24, 2017

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

@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov slavapestov force-pushed the generic-subscript-materialize-for-set branch from 7dd0bab to 0a3de7c Compare February 25, 2017 06:42
@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov slavapestov force-pushed the generic-subscript-materialize-for-set branch 3 times, most recently from cef235c to 9955871 Compare February 26, 2017 09:48
@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

1 similar comment
@slavapestov
Copy link
Contributor Author

@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.
@slavapestov slavapestov force-pushed the generic-subscript-materialize-for-set branch from 9955871 to fa8f2ce Compare February 27, 2017 05:27
@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

1 similar comment
@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov
Copy link
Contributor Author

@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?

@slavapestov slavapestov merged commit 0059016 into swiftlang:master Feb 27, 2017
@jckarter
Copy link
Contributor

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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants