Swift 6 failing to implicitly open existentials?

Hi! I'm experimenting with Implicit Open Existentials in Swift 6 mode. I'm seeing a confusing error and I need the same workaround I used for 5.10. I'm not sure why I need this workaround. Should this work out-of-the-box in Swift 6 mode?

struct S { }

struct Box<T> {
  
}

func box<T>(_: T.Type) -> Box<T> {
  Box<T>()
}

func main() {
  func body<Value>(_: Value.Type) -> Value.Type { Value.self }
  
  let metatype: Any.Type = S.self
  
  let _ = body(metatype)
  
  let _ = box(_openExistential(metatype, do: body))
  
  let _ = box(metatype)
}

Here are the errors:

error: generic parameter 'T' could not be inferred
 5 | }
 6 | 
 7 | func box<T>(_: T.Type) -> Box<T> {
   |      `- note: in call to function 'box'
 8 |   Box<T>()
 9 | }
   :
18 |   let _ = box(_openExistential(metatype, do: body))
19 |   
20 |   let _ = box(metatype)
   |           `- error: generic parameter 'T' could not be inferred
21 | }
22 | 

error: cannot convert value of type 'any Any.Type' to expected argument type 'T.Type'
18 |   let _ = box(_openExistential(metatype, do: body))
19 |   
20 |   let _ = box(metatype)
   |               `- error: cannot convert value of type 'any Any.Type' to expected argument type 'T.Type'
21 | }
22 | 

Why would the call to my box function fail when passing an existential metatype? Would this not be enabled already in Swift 6? Why would I still need the _openExistential workaround from 5.10 to compile?

There are some examples in SE-0352 where we can't open an existential… but I'm not sure I understand how my example would translate to those (known) limitations. Any ideas?

This example minus the last statement (i.e., your workaround) doesn't compile (on godbolt.org) in 5.10 or in the nightly. The error in 5.10 is: "Found opened existential archetype Any outside enclosing OpenExistentialExpr"; and in the nightly: "Found local archetype outside its defining scope".

Isn't this what the proposal covers explicitly in the text quoted below?

When T or a T-rooted associated type appears in a non-covariant position in the result type, T cannot be bound to the underlying type of an existential value because there would be no way to represent the type-erased result. This is essentially the same property as descibed for the parameter types that prevents opening of existentials, as described above. For example:

func cannotOpen7<T: P>(_ value: T) -> X<T> { /*...*/ }
2 Likes

Hmm… I built from Xcode_16_beta_3 and did not see that. Weird!

Ahh… correct! I see it now. Thanks!