Track the key argument index separately from the generic parameter index when performing the invertible protocol checking in _checkGenericRequirements. This keeps the indexing correct when a non-key argument is followed by a key argument.
rdar://128774651
Emit metadata for runtime checks of conformances of associated types to
invertible protocols, e.g., `T.Assoc: Copyable`. This allows us to
correctly handle, e.g., dynamic casting involving conditional
conformances that have such constraints.
The model we use here is to emit an invertible-protocol constraint
that leaves only the specific bit clear in the invertible protocol
set.
Form a set of suppressed protocols for a function type based on
the extended flags (where future compilers can start recording
suppressible protocols) and the existing "noescape" bit. Compare
that against the "ignored" suppressible protocol requirements, as we
do for other types.
This involves a behavior change if any client has managed to evade the
static checking for noescape function types, but it's unlikely that
existing code has done so (and it was unsafe anyway).
Add more runtime support for checking suppressible protocol requirements:
* Parameter packs now check all of the arguments appropriately
* Most structural types now implement checking (these are hard to test).
Introduce metadata and runtime support for describing conformances to
"suppressible" protocols such as `Copyable`. The metadata changes occur
in several different places:
* Context descriptors gain a flag bit to indicate when the type itself has
suppressed one or more suppressible protocols (e.g., it is `~Copyable`).
When the bit is set, the context will have a trailing
`SuppressibleProtocolSet`, a 16-bit bitfield that records one bit for
each suppressed protocol. Types with no suppressed conformances will
leave the bit unset (so the metadata is unchanged), and older runtimes
don't look at the bit, so they will ignore the extra data.
* Generic context descriptors gain a flag bit to indicate when the type
has conditional conformances to suppressible protocols. When set,
there will be trailing metadata containing another
`SuppressibleProtocolSet` (a subset of the one in the main context
descriptor) indicating which suppressible protocols have conditional
conformances, followed by the actual lists of generic requirements
for each of the conditional conformances. Again, if there are no
conditional conformances to suppressible protocols, the bit won't be
set. Old runtimes ignore the bit and any trailing metadata.
* Generic requirements get a new "kind", which provides an ignored
protocol set (another `SuppressibleProtocolSet`) stating which
suppressible protocols should *not* be checked for the subject type
of the generic requirement. For example, this encodes a requirement
like `T: ~Copyable`. These generic requirements can occur anywhere
that there is a generic requirement list, e.g., conditional
conformances and extended existentials. Older runtimes handle unknown
generic requirement kinds by stating that the requirement isn't
satisfied.
Extend the runtime to perform checking of the suppressible
conformances on generic arguments as part of checking generic
requirements. This checking follows the defaults of the language, which
is that every generic argument must conform to each of the suppressible
protocols unless there is an explicit generic requirement that states
which suppressible protocols to ignore. Thus, a generic parameter list
`<T, Y where T: ~Escapable>` will check that `T` is `Copyable` but
not that it is `Escapable`, and check that `U` is both `Copyable` and
`Escapable`. To implement this, we collect the ignored protocol sets
from these suppressed requirements while processing the generic
requirements, then check all of the generic arguments against any
conformances not suppressed.
Answering the actual question "does `X` conform to `Copyable`?" (for
any suppressible protocol) looks at the context descriptor metadata to
answer the question, e.g.,
1. If there is no "suppressed protocol set", then the type conforms.
This covers types that haven't suppressed any conformances, including
all types that predate noncopyable generics.
2. If the suppressed protocol set doesn't contain `Copyable`, then the
type conforms.
3. If the type is generic and has a conditional conformance to
`Copyable`, evaluate the generic requirements for that conditional
conformance to answer whether it conforms.
The procedure above handles the bits of a `SuppressibleProtocolSet`
opaquely, with no mapping down to specific protocols. Therefore, the
same implementation will work even with future suppressible protocols,
including back deployment.
The end result of this is that we can dynamically evaluate conditional
conformances to protocols that depend on conformances to suppressible
protocols.
Implements rdar://123466649.
Ensure that context descriptor pointers are signed in the runtime by putting the ptrauth_struct attribute on the types.
We use the new __builtin_ptrauth_struct_key/disc to conditionally apply ptrauth_struct to TrailingObjects based on the signing of the base type, so that pointers to TrailingObjects get signed when used with a context descriptor pointer.
We add new runtime entrypoints that take signed pointers where appropriate, and have the compiler emit calls to the new entrypoints when targeting a sufficiently new OS.
rdar://111480914
Section scans (for metadata, protocols, etc.) can be costly. This change adds tracing calls to those scans so we can more easily see how much time is spent in these scans and where they're initiated.
This adds an os_signpost implementation controlled by SWIFT_STDLIB_TRACING, and a default empty implementation for when that's disabled.
rdar://110266743
Fix a potential false positive if we check a class for a protocol conformance and its superclasses aren't yet instantiated.
This was partially fixed before, but we were incorrectly saying that all superclasses had been instantiated if they had been instatiated by the LAST check in conformsToProtocol. That left us open for a possible false positive in an earlier check to go unnoticed.
This change fixes it by checking for uninstantiated superclasses after each iteration over superclasses, not just the last one.
This change also makes the concurrentTypeByName test much more robust. The original test caught this bug only rarely, but the new one catches it it reliably. We now look up 1000 types per test run. Testing locally, we typically hit the race after less than 100 types.
rdar://82364236
We were skipping shared cache queries if the ObjC metadata or descriptor were outside the shared cache, but we need to skip only if they're both outside the shared cache. We also need to check foreign types even if the descriptor is outside the shared cache.
rdar://93931813
The shared cache tables can only point to things within the shared cache, so if the protocol, ObjC class, or type descriptor are outside the shared cache, we know that the lookup will fail and we can skip it.
rdar://90427793
Apply a blanket pass of including `new` for the placement new allocation
and namespacing the call to the global placement new allocator. This
should repair the Android ARMv7 builds.
Leftover code was overwriting the result from the `on_disk` calls. Don't do that.
While we're in there, change the name of the `DYLD_CONFORMANCES_LOG` macro to `DYLD_CONFORMANCES_LOG` and fix up the wording to be more general.
rdar://89154273
Extend the support for precomputed protocol conformances in the shared cache. When available, we'll query dyld for conformances in optimized images loaded outside the shared cache. This is a relatively small addition; where we previously checked the shared cache, we now check both. The order is conditionalized on `scanSectionsBackwards` to preserve that behavior. We also rename some identifiers to fit this more expansive use of preoptimized conformances.
rdar://87425446
If we find multiple conformances for the same protocol, we generate a
warning. This works fine for Swift types, but for Objective-C types
it's possible that while generating the warning we might find that the
type description is NULL.
Fix by using swift_getTypeName().
rdar://86368350
In order to be able to debug, for example, a Linux process from a macOS host, we
need to be able to initialize a ReflectionContext without Objective-C
interoperability. This patch turns ObjCInterOp into another template trait, so
it's possible to instantiate a non-ObjC MetadataReader on a system built with
ObjC-interop (but not vice versa).
This patch changes the class hierarchy to
TargetMetadata<Runtime>
|
TargetHeapMetadata<Runtime>
|
TargetAnyClassMetadata<Runtime>
/ \
/ TargetAnyClassMetadataObjCInterop<Runtime>
/ \
TargetClassMetadata<Runtime, TargetAnyClassMetadata<Runtime>> \
\
TargetClassMetadata<Runtime, TargetAnyClassMetadataObjCInterop<Runtime>>
TargetAnyClassMetadataObjCInterop inherits from TargetAnyClassMetadata because
most of the implementation is the same. This choice makes TargetClassMetadata a
bit tricky. In this patch I went with templating the parent class.
rdar://87179578
* Refactor Bincompat
Organize everything around internal functions that test for
a particular OS version.
Correctly handle cases where we don't know the version of the app.
Make all bincompat functions consistently return `true` for the
legacy semantics, `false` for new semantics. Consistently name
them all to reflect this.
* Conditionalize the support for SR-14635
SR-14635 pointed out a hole in the updated dynamic casting logic
that allowed certain casts that should have been illegal.
In particular, when casting certain types to Obj-C protocols,
the Swift value gets boxed; we would permit the cast to succeed
whenever the resulting box satisfied the protocol. For example,
this allowed any Swift value to be cast to `NSCopying` regardless of
whether or not it implemented the required `copy(with:)` method.
This was fixed in #37683 to reject such casts but of course some folks were
depending on this behavior to pass Swift data into Obj-C functions.
(The properly supported approach for passing arbitrary Swift data into
Obj-C functions is to cast the Swift value to `AnyObject`.)
This change makes that new behavior conditional. For now,
the legacy semantics are enabled on Apple platforms and the
new semantics are in use everywhere else. This will allow
us to gradually enable enforcement of the new behavior over
time.
* Just skip this test on Apple platforms, since it is inconsistently implemented there (and is therefore not really testable)
Conformance checks now walk the superclass chain in two stages: stage 1 only walks superclasses that have already been instantiated. When there's a negative result and there's an uninstantiated superclass, then stage 2 will walk the uninstantiated superclasses.
The infinite recursion would occur in this scenario:
class Super<T: P> {}
class Sub: Super<Sub>, P {}
Instantiating the metadata for Super requires looking up the conformance for Sub: P. Conformance checking for Sub would instantiate the metadata for Super to check for a Super: P conformance.
The compiler does not allow the conformance to come from a superclass in this situation. This does not compile:
class Super<T: P>: P {}
class Sub: Super<Sub> {}
Therefore it's not necessary to look at Super when finding the conformance for Sub: P in this particular case. The trick is knowing when to skip Super.
We do need to instantiate Super in the general case, otherwise we can get false negatives. This was addressed in a80fe8536b, which walks the full superclass chain during conformance checks, even if the superclass has not yet been instantiated. Unfortunately, that causes this infinite recursion.
This fix modifies that fix to make superclass instantiation conditional. The result is the ability to choose between the old algorithm (which skipped uninstantiated superclasses, albeit somewhat by accident) and the new one. A small wrapper then runs the check with the old algorithm, and then only if the old algorithm fails and there is an uninstantiated superclass, it runs with the new one.
Uninstantiated superclasses are uncommon and transient (you only run into this while metadata is in the process of being constructed) so 99.9999% of the time we'll just run the first stage and be done, and performance should remain the same as before.
rdar://80532245
The getSuperclassForMaybeIncompleteMetadata function assumes Swift metadata, and can malfunction strangely when given a pure ObjC class. This is rare, as we usually get the Swift wrapper metadata instead, but possible when using calls like objc_copyClassList.
Fix this by checking for isTypeMetadata before doing anything that assumes Swift-metadata-ness.
rdar://80336030
tryGetCompleteMetadataNonblocking crashes on artificial subclasses due to the NULL type descriptor. Explicitly check for artificial subclasses in getSuperclassForMaybeIncompleteMetadata and immediately return their Superclass field. Artificial subclasses are always fully initialized so we don't need to do anything special for them.
rdar://72583931
When we rely on a protocol conformance, and the type in question has multiple
conformances to that protocol in its inheritance chain, emit a runtime warning.
It's quite tricky to cause this problem - you need a type in one dylib that is
extended to conform to a protocol in another dylib, subclassed in another module
and then some subclass has protocol conformance added as well. If they're in
the same module, the compiler will give an error and prevent the problem
completely.
rdar://73364629