Files
swift-mirror/stdlib/public/runtime/DynamicCast.cpp
tbkka c1fce93d0e SR-14635: Casts to NSCopying should not always succeed (#37683)
* SR-14635: Casts to NSCopying should not always succeed

The runtime dynamic casting logic explores a variety of strategies for
each cast request.  One of the last options is to wrap the source
in a `__SwiftValue` box so it can bridge to Obj-C.  The previous
code was overly aggressive about such boxing; it performed the boxing
for any source type and only checked to verify that the `__SwiftValue`
box itself was compatible with the destination.

Among other oddities, this results in the behavior discussed
in SR-14635, where any Swift or Obj-C type will always successfully cast
to NSCopying because `__SwiftValue` is compatible with NSCopying.

This is actually two subtly different issues:

* Class types should not be subject to `__SwiftValue` boxing at all.
  Casting class types to class existentials is already handled elsewhere,
  so this function should just reject any source with class type.

* Non-class types should be boxed only when being assigned to
  an AnyObject (an "unconstrained class existential").  If
  the class existential has constraints, it is by definition
  a class-constrained existential which should not receive
  any non-class object.

To solve these, this PR disables `__SwiftValue` boxing in two cases:
1. If the source is a class (reference) type.
2. If the destination has constraints

Resolves SR-14635
Resolves rdar://78224322

* Avoid boxing class metatypes on Darwin

But continue boxing
 * Non-class metatypes on all platforms
 * All metatypes on non-Darwin platforms

Obj-C interop requires that we do not box class metatypes;
those must be usable as simple pointers when passed to Obj-C.
But no other metatype is object-compatible, so we have to
continue boxing everything else.

* Split out ObjC-specific test cases
2021-06-01 11:27:57 -07:00

89 KiB