Commit Graph

47 Commits

Author SHA1 Message Date
Doug Gregor
43df05a89c [SE-0470] Prohibit isolated conformances in dynamic casts marked as such
Certain dynamic casts cannot work safely with isolated conformances,
regardless of what executor the code runs on. For such cases, reject
all attempts to conform to the type.
2025-03-26 22:31:52 -07:00
Doug Gregor
296e14662a Rework runtime entrypoints for isolated conformance checking
Replace the pair of global actor type/conformance we are passing around with
a general "conformance execution context" that could grow new functionality
over time. Add three external symbols to the runtime:

* swift_conformsToProtocolWithExecutionContext: a conforms-to-protocol check
  that also captures the execution context that should be checked before
  using the conformance for anything. The only execution context right now
  is for an isolated conformance.
* swift_isInConformanceExecutionContext: checks whether the function is
  being executed in the given execution context, i.e., running on the
  executor for the given global actor.
* swift_ConformanceExecutionContextSize: the size of the conformance
  execution context. Client code outside of the Swift runtime can allocate
  a pointer-aligned region of memory of this size to use with the runtime
  functions above.
2025-03-07 23:52:20 -08:00
Doug Gregor
48aa75d86f [Isolated conformances] Cache resolved global actor for conformances
In the prior implementation of runtime resolution of isolated conformances,
the runtime had to look in both the protocol conformance descriptor and
in all conditional conformance requirements (recursively) to find any
isolated conformances. If it found one, it had to demangle the global
actor type to metadata. Since swift_conformsToProtocol is a hot path through
the runtime, we can't afford this non-constant-time work in the common
case.

Instead, cache the resolved global actor and witness table as part of the
conformance cache, so that we have access to this information every time
we look up a witness table for a conformance. Propagate this up through
various callers (e.g., generic requirement checking) to the point where
we either stash it in the cache or check it at runtime. This gets us down
to a very quick check (basically, NULL-or-not) for nonisolated conformances,
and just one check for isolated conformances.
2025-03-07 23:51:46 -08:00
Egor Zhdan
84ae5fbe8c [cxx-interop] Fix runtime crash when casting from an existential to a foreign reference type
When a C++ foreign reference type is conformed to a Swift protocol via a Swift extension, trying to cast `any MyProtocol` to the foreign reference type crashes the runtime.

This was because `selectCasterForDest` wasn't handling C++ foreign reference types, and we were hitting `swift_unreachable`.

This change makes sure the runtime doesn't crash for such casts.

Notably, Swift doesn't have enough metadata to determine if the conditional cast actually succeeded. This is also a problem for CF types. Casting CF types in a similar fashion triggers a typechecker diagnostic. That diagnostic will be amended in a follow-up patch to also trigger for foreign reference types.

rdar://141227849
2024-12-16 20:23:17 +00:00
Michael Gottesman
cb8e8b505a Fix syntax highlighting by changing how we include COMPATIBILITY_OVERRIDE_INCLUDE_PATH.
The way that we include COMPATIBILITY_OVERRIDE_INCLUDE_PATH freaks out the
syntax highlighting of editors like emacs. It causes the whole file to be
highlighted like it is part of the include string.

To work around this, this patch creates a separate file called
CompatibilityOverrideIncludePath.h that just includes
COMPATIBILITY_OVERRIDE_INCLUDE_PATH. So its syntax highlighting is borked, but
at least in the actual files that contain real code, the syntax highlighting is
restored.
2024-10-01 16:17:16 -07:00
Mike Ash
b86fe88c43 [Runtime] Fix key argument indexing when checking invertible protocols.
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
2024-06-11 12:39:23 -04:00
Doug Gregor
b167eece42 Metadata and runtime support for suppressible protocol requirements
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.
2024-03-21 14:57:47 -07:00
Rick van Voorden
f8ae46b3f3 [inclusive-language] changed sanity to soundness 2024-01-25 18:18:02 -08:00
Mike Ash
3716df4ca5 [Runtime] Fix findBridgeWitness when building for the shared cache.
The static bridgeableProtocol inherits the ptrauth_struct attribute which uses the B key, and that's not allowed on global data in the shared cache. Pass the value directly as a parameter instead.
2023-12-01 09:40:25 -05:00
Tim Kientzle
079c83ba9e Reword message a bit more based on review feedback 2023-11-08 11:04:43 -08:00
Tim Kientzle
d16e493856 Clarify the error we emit when we see an unexpected null pointer 2023-11-06 16:39:14 -08:00
Mike Ash
fe7e13bba5 [Runtime][IRGen] Sign type context descriptor pointers.
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
2023-07-07 18:10:35 -04:00
Slava Pestov
d776f71b4f Runtime: Teach checkGenericRequirements() to check same-shape and conformance pack requirements 2023-03-09 09:42:00 -05:00
Tim Kientzle
00f49a98d0 Provide a Bincompat override for the newly tightened casting semantics 2023-02-02 08:45:50 -08:00
Tim Kientzle
1846545da1 Use SwiftValue unpacking API correctly 2023-02-02 08:45:50 -08:00
Tim Kientzle
6127cc286c Fix calling convention for unboxFromSwiftValueWithType 2023-02-02 08:45:50 -08:00
Tim Kientzle
b91f29dfcb SR-14635: __SwiftValue should be transparent to casting
This PR changes the casting machinery to avoid casting `__SwiftValue` boxes
directly.  This forces the caster to instead unwrap `__SwiftValue` boxes and
retry with the inner content.  This results in boxed values being cast like the
inner content.

This fixes the behavior in situations like the following:
```
   let t = ...
   let s = t as Any as! AnyObject
   // `s` is now a `__SwiftValue` box
   // Next line should be true iff t conforms to NSCopying
   // Prior to this change, it always succeeds
   s is NSCopying
```

After this change, the above cast succeeds only if `t` actually
conforms to `NSCopying`.

This is a follow-on to PR#37683.
Related to: SR-14635
2023-02-02 08:45:50 -08:00
Anthony Latsis
c731089068 Gardening: Migrate stdlib sources to GH issues 2022-09-26 06:30:49 +03:00
Robert Widmann
541aa8dc7a Merge pull request #59507 from CodaFi/metastability 2022-06-16 20:37:13 -06:00
Robert Widmann
16c3323b4c Switch From Bitwise to Logical And
This seems to have been a thinko that got copied-and-pasted around this file.
2022-06-16 18:07:59 -06:00
Robert Widmann
824fa48f34 Check The Last Node After Unwrapping Metatypes
Ensure the last node after all of the destructuring really
is a dependent generic param type. If it isn't, something has
gone horribly wrong.
2022-06-16 17:13:43 -06:00
Robert Widmann
c06e811b09 Fixup Extended Existential Metatype Casts
The fix here is two-fold:

1) Teach SILGen that it cannot use the scalar casting paths for extended existentials
2) Teach the runtime casting entrypoint to unwrap as much metatype structure as possible
   before arriving at a 'Self' type bound for the requirement checking paths.

The code here mirrors the destructuring check we're doing in remote mirrors.

rdar://95166916
2022-06-16 14:35:20 -06:00
Robert Widmann
9e4670a605 Implement Casting For Extended Existentials
Implement casting to and from extended existentials. This is done by slightly generalizing the conditional conformances checking infrastructure.

Unfortunately, casts for reference types and metatypes are unsound because IRGen is peepholing all non-opaque existential conversions with a helper. I’ll disable that in a follow-up.

rdar://92197049
2022-06-15 21:35:15 -06:00
Alejandro Alonso
77c3d1a47f Break after tuples aren't equal (#58764) 2022-05-09 14:11:27 -07:00
Josh Soref
5fab3d1f58 Spelling stdlib/public/runtime (#42439)
* spelling: access

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: bridgeable

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: canonical

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: clazz

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: compatibility

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: language

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: necessary

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: platform

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: recursive

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: related

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: repeated

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: satisfy

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: that

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: the

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

* spelling: verification

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>

Co-authored-by: Josh Soref <jsoref@users.noreply.github.com>
2022-04-19 14:03:03 -07:00
tbkka
184488d3f2 Conditionalize the fix for SR-14635 (#40822)
* 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)
2022-01-14 11:56:25 -08:00
David Smith
12166a9c2d Optimize NSString->AnyHashable and String->AnyHashable 2022-01-08 02:33:51 -08:00
Mike Ash
89d93a000d [Runtime] Replace std::max_align_t with MaximumAlignment from MetadataValues.h.
On Windows, std::max_align_t is only 8-byte aligned, but Swift assumes 16-byte alignment. MaximumAlignment is our notion of the maximum alignment of a type, so use that instead.
2021-11-18 13:56:05 -05:00
Alastair Houghton
e339feb2da [Runtime] Add format string attributes.
Added some attributes to mark functions as taking format strings.

rdar://84571859
2021-10-25 13:46:05 +01:00
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
Mishal Shah
3116eed2e4 Update the branch to build with Xcode 12.5 (#37046) 2021-04-23 16:24:11 -07:00
Mike Ash
6aab257c33 [Concurrency] Add compatibility overrides to Concurrency library.
Take the existing CompatibilityOverride mechanism and generalize it so it can be used in both the runtime and Concurrency libraries. The mechanism is preprocessor-heavy, so this requires some tricks. Use the SWIFT_TARGET_LIBRARY_NAME define to distinguish the libraries, and use a different .def file and mach-o section name accordingly.

We want the global/main executor functions to be a little more flexible. Instead of using the override mechanism, we expose function pointers that can be set by the compatibility library, or by any other code that wants to use a custom implementation.

rdar://73726764
2021-03-22 11:09:06 -04:00
tbkka
f29d049d09 In backwards compatibility mode, be more permissive of Obj-C null references (#35825)
The new cast logic checks and aborts if a non-nullable pointer has a null value
at runtime.  However, because this was tolerated by the old casting logic, some
apps inadvertently rely on being able to cast such null references.

This change adds specific checks for null pointers in compatibility mode and
handles them similarly to the previous casting logic:
 * Casting to Obj-C or CF type: casting a null pointer succeeds
 * Casting to class-constrained existential: casting a null pointer succeeds
 * Casting to a Swift class type: cast fails without crashing
 * Bridging from Obj-C class to Swift struct type: cast fails without crashing
This also adds a guard to avoid trying to lookup the dynamic type of a null
class reference.

In non-compatibility mode, all of the above cause an immediate runtime crash.
The changes here are only intended to support existing binaries running against
new Swift runtimes.

Resolves rdar://72323929
2021-02-09 07:31:22 -08:00
Tim Kientzle
086dc14008 Don't link-check the Optional/AnyHashable workaround
This restores the earlier behavior of Optionals cast to
AnyHashable, so that [String?:Any] dictionaries cast
to [AnyHashable:Any] can be indexed by plain String
keys.

This is a little problematic because it's not consistent with the
compiler-optimized casts.

But the ability to index such dictionaries by plain String
keys seems important to preserve.  SR-9047 will expand
Optional/AnyHashable interoperability so that such
indexing works without this special case.

An earlier proposal would link-check this, changing the behavior
depending on the caller.  But it's not really workable to
change the behavior seen by intermediate frameworks depending
on the app they're being called by.
2021-02-01 09:54:03 -08:00
Tim Kientzle
5aaabfd5a2 Fix spelling of DynamicCastResult 2021-01-29 09:00:45 -08:00
Tim Kientzle
14df4d1310 Compatibility for Optional -> AnyHashable casts
As part of making casting more consistent, the behavior of Optional -> AnyHashable casts
was changed in some cases.  This PR provides a hook for re-enabling the old behavior
in certain contexts.

Background: Most of the time, casts from String? to AnyHashable get optimized
to just injects the String? into the AnyHashable, so the following
has long been true and remains true in Swift 5.4:
```
let s = "abc"
let o: String? = s

// Next test is true because s is promoted to Optional<String>
print(s == o)

// Next test is false: Optional<String> and String are different types
print(s as AnyHashable == o as AnyHashable)
```

But when casts ended up going through the runtime, Swift 5.3 behaved
differently, as you could see by casting a dictionary with `String?` keys (in
the generic array code, key and value casts always use the runtime logic).  In
the following code, both print statements behave differently in Swift 5.4 than
before:
```
let a: [String?:String] = ["Foo":"Bar"]
let b = a as [AnyHashable:Any]
print(b["Foo"] == "Bar")  // Works before Swift 5.4
print(b["Foo" as String?] == "Bar") // Works in Swift 5.4 and later
```

Old behavior: The `String?` keys would get unwrapped to `String` before being injected into AnyHashable.  This allows the first to work but strangely breaks the second.

New behavior: The `String?` keys do not get unwrapped.  This breaks the first but makes the second work.

TODO: The long-term goal, of course, is for `AnyHashable("Foo" as String?)` to
test equal to `AnyHashable("Foo")` (and hash the same, of course).  In that
case, all of the tests above will succeed.

Resolves rdar://73301155
2021-01-29 08:24:56 -08:00
Tim Kientzle
7d686cde77 Remove no-longer-needed external declaration of swift_dynamicCast_OLD 2021-01-05 18:02:09 -08:00
Tim Kientzle
e5c4e2d9f9 Add a hook for a future cast optimization
NSString->AnyHashable casts are remarkably common.  We
should make them faster someday.
2020-12-17 15:18:08 -08:00
Tim Kientzle
4d78405bc0 Conditionalize null ptr check when casting
Background: We've noticed a lot of problems from Obj-C APIs that returned null
even though they were declared to never do so.  These mismatches subvert Swift's
type system and can lead to hard-to-diagnose crashes much later in the program.
This fatal error was introduced into the primary casting function to help catch
such problems closer to the point where they occur so developers could more
easily identify and fix them.

However, there's been some concern about what this means for old binaries, so
we're considering a check here that would allow the old behavior in certain
cases yet to be determined.  This PR adds the framework for such a check.

Resolves rdar://72323929
2020-12-15 12:28:42 -08:00
tbkka
ef05015951 Remove old swift_dynamicCast implementation (#34789)
The new implementation has been the default for a while now and
seems to be stable and relatively bug-free.
2020-11-18 10:16:56 -08:00
tbkka
d92f1d58f8 Dynamic Casting: Properly unwrap existential metatype sources (#34469)
* Dynamic Casting: Properly unwrap existential metatype sources

Existential metatypes are really just existentials that hold metatypes.  As
such, they should be handled in the general casting logic in much the same way
as regular existentials: They should generally be ignored by most casting logic,
and unwrapped as necessary at the top level.

In particular, the previous code would fail to correctly handle the following
cast from an existential metatype (`AnyObject.Type`) to an existential
(`AnyObject`):
```
  class C {}
  let a = C.self as AnyObject.Type
  let b = a as! AnyObject
```
With the old code, `b` above would hold a reference to a `__SwiftValue` box
containing the type reference.  The correct result would simply store the type
reference directly in `b`.  These two are only really distinguishable in that
the correct form permits `a === b` to return `true`.

Fixes rdar://70582753

Note: This is not yet fully supported on Linux.  Basically, metatypes on Linux are not currently
fully compatible with reference-counted class pointers, which prevents us from
fully supporting metatype operations on Linux that we support on macOS.
2020-10-29 14:46:10 -07:00
John McCall
0fb407943f [NFC] Rename swift_runtime_unreachable to swift_unreachable and make it use LLVM's support when available. 2020-10-03 02:54:56 -04:00
Xiaodi Wu
45299909bc [runtime] Silence unreachable code warning (#33912) 2020-09-21 07:30:43 -04:00
tbkka
a61e7044c4 Witness tables have special ptrauth requirements (#33876) 2020-09-10 08:24:20 -07:00
Denys Shabalin
78c957f485 Move fallthrough one line up 2020-09-09 17:14:16 +02:00
Denys Shabalin
87906df2fe Add missing SWIFT_FALLTHROUGH to the tryCastToString 2020-09-07 16:09:38 +02:00
tbkka
524cfae1b2 [Dynamic Casting] Overhauled Runtime (#33561)
* Dynamic Cast Rework: Runtime

This is a completely refactored version of the core swift_dynamicCast
runtime method.

This fixes a number of bugs, especially in the handling of multiply-wrapped
types such as Optional within Any.  The result should be much closer to the
behavior specified by `docs/DynamicCasting.md`.

Most of the type-specific logic is simply copied over from the
earlier implementation, but the overall structure has been changed
to be uniformly recursive.  In particular, this provides uniform
handling of Optional, existentials, Any and other common "box"
types along all paths.  The consistent structure should also be
easier to update in the future with new general types.

Benchmarking does not show any noticable performance implications.

**Temporarily**, the old implementation is still available.  Setting the
environment variable `SWIFT_OLD_DYNAMIC_CAST_RUNTIME` before launching a program
will use the old runtime implementation.  This is only to facilitate testing;
once the new implementation is stable, I expect to completely remove the old
implementation.
2020-08-27 11:06:40 -07:00