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

Disallow implicit existential opening when calling function with an opaque result type #59840

Open
karwa opened this issue Jul 1, 2022 · 3 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself type checker Area → compiler: Semantic analysis

Comments

@karwa
Copy link
Contributor

karwa commented Jul 1, 2022

Describe the bug

protocol P {
  associatedtype A
  func getA() -> A
}

struct S<T: P> {
    var s: T
}

func openSesame(_ p: some P) -> S<some P> {
    S(s: p)
}

func test(_ p: any P) {

  let x = openSesame(p)
//   print(x)

}
Unhandled coercion
UNREACHABLE executed at /home/build-user/swift/lib/Sema/CSApply.cpp:7219!
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the project and the crash backtrace.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/swift-nightly/usr/bin/swift-frontend -frontend -S -primary-file <source> -target x86_64-unknown-linux-gnu -disable-objc-interop -g -new-driver-path /opt/compiler-explorer/swift-nightly/usr/bin/swift-driver -empty-abi-descriptor -resource-dir /opt/compiler-explorer/swift-nightly/usr/lib/swift -enable-anonymous-context-mangled-names -Xllvm --x86-asm-syntax=intel -module-name output -o /app/output.s
1.	Swift version 5.8-dev (LLVM befe8168eb51210, Swift 0daa5584f4a2471)
2.	Compiling with the current language version
3.	While evaluating request TypeCheckSourceFileRequest(source_file "<source>")
4.	While evaluating request TypeCheckFunctionBodyRequest(output.(file).testOpenSimple(p:)@<source>:14:6)
5.	While type-checking statement at [<source>:14:31 - line:19:1] RangeText="{

  let x = openSesame(p)
//   print(x)

"
6.	While type-checking declaration 0xa816bf0 (at <source>:16:3)
7.	While evaluating request PatternBindingEntryRequest((unknown decl), 0, 0)
8.	While type-checking expression at [<source>:16:11 - line:16:23] RangeText="openSesame(p"
9.	While type-checking-target starting at <source>:16:11

To Reproduce

Godbolt

Environment (please complete the following information):

  • Swift version 5.8-dev (LLVM befe8168eb51210, Swift 0daa558)
  • OS: Linux
@karwa karwa added the bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. label Jul 1, 2022
@xedin xedin added the type checker Area → compiler: Semantic analysis label Jul 1, 2022
@slavapestov
Copy link
Contributor

This is a crash-on-invalid, we should reject the call to openSesame() for the same reason you can't call a protocol extension member that returns an opaque result type on an existential. CC @DougGregor

@slavapestov slavapestov changed the title Compiler crash: Unhandled coercion Disallow implicit existential opening when calling function with an opaque result type Jul 6, 2022
@karwa
Copy link
Contributor Author

karwa commented Jul 6, 2022

Right. If you change the return type to Any, it works:

func openSesame(_ p: some P) -> Any {
  S(s: p)
}

Also, if you change the return type to Optional<some P> (and just return the parameter unchanged), it works:

func openSesame(_ p: some P) -> Optional<some P> {
  p
}

But we don't support opaque types in generic parameters for types other than Optional, so S<some P> is invalid anyway (still shouldn't crash).

It may also be worth a diagnostic to let users know that this code can work (i.e. you can take a some P as we're doing here, and instantiate a value of generic type S<T> which uses it), but the value cannot be returned from the function in full fidelity -- it must be erased in some way.

@slavapestov
Copy link
Contributor

Also, if you change the return type to Optional (and just return the parameter unchanged), it works:

This works because we erase Optional<some P> to Optional<any P>. However we cannot do that for S<some P>, since S<any P> is invalid -- any P does not satisfy the requirements of S.

But we don't support opaque types in generic parameters for types other than Optional, so S is invalid anyway (still shouldn't crash).

We do support that actually (see https://github.com/apple/swift-evolution/blob/main/proposals/0328-structural-opaque-result-types.md). We just can't erase the return value when you call a function returning S<some P> on an opened existential.

@AnthonyLatsis AnthonyLatsis added the compiler The Swift compiler in itself label Dec 13, 2022
@slavapestov slavapestov self-assigned this Dec 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

5 participants