Unexpected error with integer generic parameters

While playing with integer generic parameters in form of implementing a compile time optional type:

struct Optional<let isNil: Int, Wrapped> {
  private let wrapped: Wrapped!

  init(wrapped: Wrapped) where isNil == 1 {
    self.wrapped = wrapped
  }

  init() where isNil == 0 {
    self.wrapped = nil
  }

  func wrappedValue() -> Wrapped where isNil == 1 {
    return wrapped
  }
}

func nilCheck<let isNil: Int, T>(_ value: Optional<isNil, T>) {
  if isNil == 1 {
    print(value.wrappedValue()) // - error: instance method 'wrappedValue()' requires the types 'isNil' and '1' be equivalent
  } else {
    print("nil")
  }
}

nilCheck(Optional<0, Int>())
nilCheck(Optional(wrapped: 1))

I am getting error:

:21:17: error: instance method 'wrappedValue()' requires the types 'isNil' and '1' be equivalent
12 | }
13 |
14 | func wrappedValue() -> Wrapped where isNil == 1 {
| - note: where 'isNil' = 'isNil' 15 | return wrapped 16 | } : 19 | func nilCheck<let isNil: Int, T>(_ value: Optional<isNil, T>) { 20 | if isNil == 1 { 21 | print(value.wrappedValue()) | - error: instance method 'wrappedValue()' requires the types 'isNil' and '1' be equivalent
22 | } else {
23 | print("nil")

But shouldn’t this kind of usage work since the wrappedValue method is only accessed in the context isNil is 1?

No. An if statement doesn’t add any static information, without binding.

What you have is the same kind of thing as this, with Swift.Optional:

if value != nil {

This is the kind of binding you need:

if case let value as Optional<1, T> = value {

@Danny shouldn’t compiler be able to infer I am in a context where the isNil is 1 is already satisfied. I see other languages are able to do that. Is this a limitation on Swift compiler?

Is there somewhere else in Swift that you think you’ve seen anything like this?

Constraints and overloads are how Swift deals with this.

func nilCheck(_ value: Optional<1, some Any>) {
  print(value.wrappedValue())
}

func nilCheck(_: Optional<0, some Any>) {
  print("nil")
}
1 Like