Skip to content
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

Opaque types as inferred associated types violate type safety #73245

Open
JadenGeller opened this issue Apr 25, 2024 · 2 comments
Open

Opaque types as inferred associated types violate type safety #73245

JadenGeller opened this issue Apr 25, 2024 · 2 comments
Labels
accepts invalid Bug: Accepts invalid bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself opaque result types Feature → types → opaque types: opaque result types opaque types Feature → types: opaque types swift 6.0 type checker Area → compiler: Semantic analysis

Comments

@JadenGeller
Copy link
Contributor

JadenGeller commented Apr 25, 2024

Description / Reproduction

The following ought to generate a type-error where whoops is declared, but instead it complies and violates type safety, interpreting memory as incorrect type.

protocol ExampleProtocol {}
extension Int: ExampleProtocol {}
extension String: ExampleProtocol {}

struct ExampleFactory {
    func makeExample() -> some ExampleProtocol { 0 }
}

protocol MakeExampleProtocol {
    associatedtype Example
    func makeExample() -> Example
}
extension ExampleFactory: MakeExampleProtocol {}

let whoops: ExampleFactory.Example = "hi"
print(whoops) // -> 26984

In the example above, the String "hi" was reinterpreted as an Int since ExampleFactor.Example is Int.

If we were to unsafeBitCast a String to Int, it would trap since the sizes don't match. Instead, we can run the following:

print(unsafeBitCast("hi", to: (Int, Int).self)) // (26984, -2161727821137838080)

As you can see, the first component matches the value of whoops, confirming that Swift in the first example silently reinterpreted whoops's initializing value as a conflicting type.

Expected behavior

Cannot convert value of type 'String' to specified type 'some ExampleProtocol' (result of 'ExampleFactory.makeExample()')

Environment

swift-driver version: 1.87.3 Apple Swift version 5.9.2 (swiftlang-5.9.2.2.56 clang-1500.1.0.2.5)
Target: arm64-apple-macosx14.0

Additional information

No response

@JadenGeller JadenGeller added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels labels Apr 25, 2024
@JadenGeller JadenGeller changed the title Opaque types as inferred associated types violate memory safety Opaque types as inferred associated types violate type safety Apr 25, 2024
@JadenGeller
Copy link
Contributor Author

JadenGeller commented Apr 27, 2024

I updated the expected behavior from

Cannot convert value of type 'String' to specified type 'Int'

to

Cannot convert value of type 'String' to specified type 'some ExampleProtocol' (result of 'ExampleFactory.makeExample()')

since I don't think type inference should act as a side-channel to determine the concrete instance of an opaque type.

@AnthonyLatsis AnthonyLatsis added compiler The Swift compiler in itself type checker Area → compiler: Semantic analysis conformances Feature → protocol: protocol conformances opaque types Feature → types: opaque types typealias Feature → type declarations: `typealias` declarations opaque result types Feature → types → opaque types: opaque result types swift 6.0 accepts invalid Bug: Accepts invalid protocol Feature → type declarations: Protocol declarations and removed triage needed This issue needs more specific labels typealias Feature → type declarations: `typealias` declarations conformances Feature → protocol: protocol conformances protocol Feature → type declarations: Protocol declarations labels Apr 28, 2024
@AnthonyLatsis
Copy link
Collaborator

A simpler example:

// test.swift

func f() -> some Sequence { "" }
typealias A = @_opaqueReturnTypeOf("$s4test1fQryF", 0) __

let a: A = "" // OK

let b: A.Element = "" // Crash
let c: A
c = "" // error: cannot assign value of type 'String' to type 'A' (aka 'some Sequence') [cannot_convert_assign]

I suspect we are wrongly assuming somewhere that an explicit type annotation necessarily implies the opaque types it represents are declared on the variable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepts invalid Bug: Accepts invalid bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself opaque result types Feature → types → opaque types: opaque result types opaque types Feature → types: opaque types swift 6.0 type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

2 participants