-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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
[metadata prespecialization] Check conformances. #32482
[metadata prespecialization] Check conformances. #32482
Conversation
@swift-ci please test |
Build failed |
@swift-ci please clean test os x platform |
05bc1be
to
0ae794b
Compare
@swift-ci please test |
Build failed |
Build failed |
@swift-ci please clean test macos platform |
0ae794b
to
8ab8a5a
Compare
@swift-ci please test and merge |
1 similar comment
@swift-ci please test and merge |
Previously, the metadata accessor for a generic type for which some metadata prespecialization was done only tested that the type metadata arguments were equal to those of the prespecialization. If the generic type had an argument which was constrained to conform to a protocol, the particular conformance to that protocol was determined at compile time, but the conformance was ignored in the metadata accessor. As a result it was possible--in certain multi-module cases--for the metadata accessor to incorrectly return a prespecialized metadata record whose type arguments matched the type arguments passed to the accessor but whose conformance arguments did not. For example, given the following, Base: struct K {} protocol P {} Conformance1: import Base struct G<T : P> {} extension K : P {} // first conformance prespecialize( G<K>.self ) Conformance2: import Base extension K : P {} // second conformance the metadata accessor for G defined in Conformance1 would behave like MetadataResponse `metadata accessor for G`( MetadataRequest request, const Metadata *M, const WitnessTable *WT) { if (M == `type metadata for K`) { return `canonical prespecialized type metadata for G<K>` } return swift_getGenericMetadata(request, {M, WT}); } Here, the WitnessTable argument is the witness table describing a conformance of the type whose metadata is provided to the protocol P. The incorrect behavior occurs when calling the metadata accessor with these arguments: `some request` `type metadata for K` `protocol witness table for Base.K : Base.P in Conformance2` The accessor would return the `canonical prespecialized type metadata for G<K>`. The problem is that the prespecialized metadata contains the following generic arguments: `type metadata for K` `protocol witness table for Base.K : Base.P in Conformance1` Specificallly, the witness table is for the conformance from Conformance1, not the conformance from Conformance2. Here, the problem is addressed by testing that the witness tables passed into the accessor are for the same conformance as the witness table referred to by the prespecialized record. Now, the metadata accessor for G will behave like MetadataResponse `metadata accessor for G`( MetadataRequest request, const Metadata *M, const WitnessTable *WT) { if (M == `type metadata for K` swift_compareProtocolConformanceDescriptors( WT->getDescription(), `protocol conformance descriptor for Base.K : Base.P in Conformance1`) ) { return `canonical prespecialized type metadata for G<K>` } return swift_getGenericMetadata(request, {M, WT}); } Consequently, when the accessor is called with the same arguments as before, the call to swift_compareProtocolConformanceDescriptors will return false and the non-matching prespecialized metadata will not be returned.
8ab8a5a
to
a5f0069
Compare
@swift-ci please test |
Build failed |
Build failed |
@swift-ci please test macos platform |
1 similar comment
@swift-ci please test macos platform |
Build failed |
@swift-ci please clean test macos platform |
Previously, the metadata accessor for a generic type for which some metadata prespecialization was done only tested that the type metadata arguments were equal to those of the prespecialization. If the generic type had an argument which was constrained to conform to a protocol, the particular conformance to that protocol was determined at compile time, but the conformance was ignored in the metadata accessor. As a result it was possible--in certain multi-module cases--for the metadata accessor to incorrectly return a prespecialized metadata record whose type arguments matched the type arguments passed to the accessor but whose conformance arguments did not.
For example, given the following,
the metadata accessor for
G
defined inConformance1
would behave likeHere, the WitnessTable argument is the witness table describing a conformance of the type whose metadata is provided to the protocol
P
.The incorrect behavior occurs when calling the metadata accessor with these arguments:
The accessor would return the
canonical prespecialized type metadata for G<K>
. The problem is that the prespecialized metadata contains the following generic arguments:Specificallly, the witness table is for the conformance from
Conformance1
, not the conformance fromConformance2
.Here, the problem is addressed by testing that the witness tables passed into the accessor are for the same conformance as the witness table referred to by the prespecialized record. Now, the metadata accessor for
G
will behave likeConsequently, when the accessor is called with the same arguments as before, the call to
swift_compareProtocolConformanceDescriptors
will return false and the non-matching prespecialized metadata will not be returned.Dependent on #32471 .