# Understanding the "cast from 'any P' to unrelated type 'S' always fails" warning

**URL:** <https://forums.swift.org/t/understanding-the-cast-from-any-p-to-unrelated-type-s-always-fails-warning/71327>\
**Category:** Using Swift\
**Tags:** existential\
**Created:** [April 17, 2024, 10:03pm UTC](https://forums.swift.org/t/understanding-the-cast-from-any-p-to-unrelated-type-s-always-fails-warning/71327 "2024-04-17T22:03:51Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [April 17, 2024, 10:03pm UTC](https://forums.swift.org/t/understanding-the-cast-from-any-p-to-unrelated-type-s-always-fails-warning/71327/1 "2024-04-17T22:03:51Z")

</div>

i wrote some code like the following:

```swift
public
struct S
{
}

public
func f(values:[any Identifiable<Int>])
{
    for case let value as S in values
    {
    }
}

```

my intention was to **retroactively** conform `S` to `Identifiable<Int>` in a downstream module. the goal was to have `f` be able to discover an instance of `S` only if the app includes a conformance of `S` to `Identifiable<Int>`.

but instead, i get this warning:

```swift
warning: cast from 'any Identifiable<Int>' to unrelated type 'S' always fails
    for case let value as S in values

```

is this something that is supported by the type system?

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [April 18, 2024, 12:34am UTC](https://forums.swift.org/t/understanding-the-cast-from-any-p-to-unrelated-type-s-always-fails-warning/71327/2 "2024-04-18T00:34:21Z")

</div>

I believe the warning is a bit of lie—if you _do_ provide that retroactive conformance then the cast will, in fact, succeed. Perhaps we ought to allow silencing this warning somehow when that's the author's intention, maybe by module-qualifying the types involved, as one can do to silence the retroactive conformance warning?

---

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [April 18, 2024, 3:36am UTC](https://forums.swift.org/t/understanding-the-cast-from-any-p-to-unrelated-type-s-always-fails-warning/71327/3 "2024-04-18T03:36:48Z")

</div>

Having some explicit indicator that you really mean to do this would also be a good way to prevent the optimiser from eliminating the actual runtime check. Otherwise, I wouldn't trust future compiler versions to not optimise this out, irrespective of what the current version happens to do.

---

<div class="post-metadata">

**Author:** ![aetherealtech](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/aetherealtech/32/36879_2.png) [@aetherealtech](https://forums.swift.org/u/aetherealtech)\
**Post date:** [August 13, 2024, 11:29am UTC](https://forums.swift.org/t/understanding-the-cast-from-any-p-to-unrelated-type-s-always-fails-warning/71327/4 "2024-08-13T11:29:01Z")

</div>

This is an interesting problem. What should happen if that function gets called when no one supplied the conformance? Right now it would silently "fail" (skip over the `S`s). Should it instead terminate the program?

I suppose the API of the module would ideally _require_ someone to provide a conformance of `S` to `Identifiable`, but there's no way to do that in Swift. The closest we can get is adding a global hook that starts off failing at runtime (as in `fatalError`) with an instruction to replace it.

Since `Identifiable` has an associated type, and this hook implies the implementation (including the type of the ID that gets returned) is now set at runtime, you lose type safety and just fall back to type erased IDs (luckily the specially treated `AnyHashable` eraser makes this easier).

```swift
public var getSID: (_ s: S) -> any Hashable = {
  fatalError("You must supply a definition for the ID of an `S`")
}

public struct S: Identifiable {
  var id: AnyHashable { getSID(self) }

  ...
}

```

I have wanted the ability to leave unimplemented hooks like this that some other module must define many times. This is possible in C/C++ by supplying a header declaration for a function in a library (so the library implementation can include and call it) but not a definition. If the library is statically linked, the library compiles fine but once you include the library in an executable (either a program or a dylib), if you don't define the function you are hit with an undefined symbol error at link time. This is perfect, as long as you understand the error. It catches the mistake of not defining the function at build time.

If the library is dynamically linked, you need to turn on the compiler option to allow undefined symbols, and the error of not defining the function gets pushed to runtime as soon as the library gets loaded. This is less ideal, but if you _truly_ need dynamic linkage (you usually don't, it's needed for e.g. a plugin system) this is the only way that makes sense. At least the error occurs as soon as the library is loaded and not whenever the function is first called.

Allowing Swift to do something like this would require this ability to wire up calls at link time, which enables link time polymorphism. I pitched what I believe is a more "Swifty" (instead of C-like) way to accomplish this a while ago [here](https://forums.swift.org/t/module-polymorphism/66034).

Another approach is to do this with generics. You can maintain strongly typed IDs that way:

```swift
protocol SIDProvider<ID> {
  associated type ID: Hashable

  static func id(for s: S<Self>) -> ID
}

struct S<IDProvider: SIDProvider>: Identifiable {
  var id: IDProvider.ID { IDProvider.id(for: self) }

  ...
}

public
func f<IDProvider: SIDProvider>(values:[any Identifiable<IDProvider.ID>])
{
    for case let value as S<IDProvider> in values
    {
    }
}

```

Now all the code up until the module that defines the ID needs to become generic, and by propagating the same type parameter this expresses that all the code works with a single ID Provider. Once the module defining the ID is present, you just assign that type parameter to the `SIDProvider` implementation defined in that module and everything above it is no longer generic. This expresses that this is where the ID definition gets locked down.

This is how I would solve this problem. It's more "invasive", lots of stuff (everything between where `S` enters the picture and the module defining the ID comes in) has to be modified but it's strongly typed and fully compile time enforced.

Another example where generics proliferate, which I found scary at first but eventually got used to it and now favor it and exercise them frequently and pervasively.

---

<div class="post-metadata">

**Author:** ![vns](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/vns/32/37396_2.png) [@vns](https://forums.swift.org/u/vns)\
**Post date:** [August 13, 2024, 11:50am UTC](https://forums.swift.org/t/understanding-the-cast-from-any-p-to-unrelated-type-s-always-fails-warning/71327/5 "2024-08-13T11:50:22Z")

</div>

With the help of additional protocol there can be a compiler guarantee:

```swift
// module A
struct MyType: MyTypeProto {
}

protocol MyTypeProto {
}

func f<T>(
    values: [some Identifiable<Int>],
    _ t: T.Type = T.self
) where T: MyTypeProto & Identifiable {
    for case let value as T in values {
    }
}

// module B
import A

extension MyType: @retroactive Identifiable {
    public var id: Int { 1 }
}

f(values: [MyType()], MyType.self) // a bit ugly on a call site, as type cannot be inferred otherwise

```

---

<div class="post-metadata">

**Author:** ![aetherealtech](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/aetherealtech/32/36879_2.png) [@aetherealtech](https://forums.swift.org/u/aetherealtech)\
**Post date:** [August 13, 2024, 12:16pm UTC](https://forums.swift.org/t/understanding-the-cast-from-any-p-to-unrelated-type-s-always-fails-warning/71327/6 "2024-08-13T12:16:28Z")

</div>

This approach made me think, "could we put `f` in a constrained extension?", like this:

```swift
extension S where Self: Identifiable<Int> {
  static func f(values: [some Identifiable<Int>]) {
    for case let value as Self in values {
    }
  }
}

```

But this doesn't work, you get "`where` clause on non-generic declaration" error (same if you move the constraint to the function).

However, that seems like it would be a reasonable way to express in Swift what is desired here. Retroactive conformances are what would make these kind of "non-generic constraints" meaningful.

Along those lines I think in your approach you can eliminate the surrogate type parameter by moving `f` into an extension on the protocol:

```swift
extension MyTypeProto where Self: Identifiable<Int> {
  static func f<T>(
    values: [some Identifiable<Int>]
  ) {
    for case let value as Self in values {
    }
  }
}

```

You still have to spell out `MyType` to call it, but maybe it's a little nicer as `MyType.f(values: ...)` instead of as a function parameter.

I think a problem with this approach might be that you can't actually call `f` until you're in code where the ID definition is visible. Before that, `MyType` doesn't satisfy the constraint. And if you only need to call `f` after the retroactive conformance is introduced you could just move `f` itself up to that level.

You'd probably have to make code that calls `f` before the ID is defined generic w.r.t. `MyTypeProto`, i.e:

```swift
func somethingThatCallsF<T: MyTypeProto & Identifiable>() {
  ...

  f(values: ..., T.self)

  ...
}

```

So on this level, between `MyType` getting defined and the conformance getting defined, things will either need to become generic or lose type safety either way.
