Implicit force unwrap in the same scope

So one thing that I run into a lot with swift is something like the following code

let value = SomeNonOptionalValue()
self.optionalValue = value
doSomethingWithNonOptionalValue(value)

I basically just want to set a value to an optional property and also use it in a non-optional way immediately. My team actually blocks most(all) uses of force unwrap for pretty good reason. This is a case where force unwrapping can work but I wonder if it would be better if the compiler just took care of this.

Ideally the code would then look like

self.optionalValue = SomeNonOptionalValue()
doSomethingWithNonOptionalValue(self.optionalValue)

I realize this is one line of code saving but I feel in the first case you have issues tracking that first variable. You don't know who is using it at first glance and this just seems like a quality of life fix.

self.value.map { doSomethingWithNonOptionalValue($0) }

Or

self.value.map(doSomethingWithNonOptionalValue)

Why would you block usage of IUO? It’s perfect for scenarios like this.

We don't block IUO we block force unwrapping. That is a bit different than the case I have here.

var value: String!

is not the same as

doSomethingWithNonOptionalValue(self.value!)

You may want to set this property to nil in the future. My issue is more or less a QOL change to get the compiler to force unwrap self.value if it was set to a non-optional value in the same scope. I know (and I think the compiler should as well) that self.value in the example i posted is non-optional If I force unwrap it myself it's kinda dangerous as I can't guarantee someone in the future wont remove the line that sets it in the first place and cause a crash.

I may not be explaining it that well though. I know there is errors in my example since I wrote this on my phone so I fixed those.

Right, sorry, I meant force unwrapping. Which you already answered, though I don't entirely agree.

1 Like

The only way the compiler would know that it is safe to do this is if you assert that it's safe...by using the operator !. If you forbid telling the compiler that it's safe to do this, then no, the compiler can't just take care of it. Consider:

struct SomeNonOptionalValue { }
func doSomethingWithNonOptionalValue(_: SomeNonOptionalValue) { }

struct S {
    var optionalValue: SomeNonOptionalValue? {
        get { nil }
        set { }
    }
}

extension S {
    mutating func f() {
        self.optionalValue = SomeNonOptionalValue()
        doSomethingWithNonOptionalValue(self.optionalValue!)
        // oops
    }
}
6 Likes

Right. It's theoretically possible to prove things like this, but it would make type-checking a completely intractable problem. The local variable straightforwardly solves the problem, is clearer for readers, and may generate more efficient code.

3 Likes

Ah this is a great example. Thanks!

Yea I can see how this isn't as trivial as I was initially thinking.

It would be interesting if it could be limited to properties without explicit getters and setters maybe.

That said I opened this as a discussion because it was something I run into a lot and it always feels redundant to create the local variable just to pass it into a new property/function as non-optional.

Hopefully I didn't create this is post in the wrong location. I appreciate all the comments here though!

Imagine such implementation:

var optionalValue: Int? {
   didSet {
    if newValue < 2 {
     optionalValue = nil
   }
  }
}

Then force unwrapping will cause an error.

Why do you need to pass self.optionalValue instead of value? Maybe some other examples will make more sense.