Proposal: Initialization should not be required in precondition(false) case


(Amir Michail) #1

For example:

let x:Int
if … { x = 1 }
else if … { x = 2 }
else { precondition(false) } // no initialization needed

Similarly,

let x:Int
switch ... {
case …: x = 1
case …: x = 2
default: precondition(false) // no initialization needed
}


(David Turnbull) #2

Use preconditionFailure() instead of precondition(false).

-david

···

On Fri, Feb 12, 2016 at 7:59 AM, Amir Michail via swift-evolution < swift-evolution@swift.org> wrote:

For example:

let x:Int
if … { x = 1 }
else if … { x = 2 }
else { precondition(false) } // no initialization needed

Similarly,

let x:Int
switch ... {
case …: x = 1
case …: x = 2
default: precondition(false) // no initialization needed
}
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Amir Michail) #3

Use preconditionFailure() instead of precondition(false).

That works! But I think precondition(false) should also work.

···

On Feb 12, 2016, at 11:29 AM, David Turnbull <dturnbull@gmail.com> wrote:

-david

On Fri, Feb 12, 2016 at 7:59 AM, Amir Michail via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
For example:

let x:Int
if … { x = 1 }
else if … { x = 2 }
else { precondition(false) } // no initialization needed

Similarly,

let x:Int
switch ... {
case …: x = 1
case …: x = 2
default: precondition(false) // no initialization needed
}
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Ross O'Brien) #4

It would be really helpful if you could describe the problem you're
experiencing so I don't have to guess what it is from your example code.

Am I guessing right if I say that you want a change to Swift such that a
switch initialisation can be 'force-unwrapped', such that if none of the
cases apply, the app crashes, in a more explicit fashion?

I've written code like this, but I've tended towards 'default:
fatalError()', which wouldn't be covered by your suggestion. 'precondition'
isn't at fault here.

Just as a digression, I've just learned that 'precondition(false)' doesn't
cause any immediately following code to receive the compiler warning 'will
never be executed' that code in a 'if false { ... }' does. So that would be
nice.

···

On Fri, Feb 12, 2016 at 3:59 PM, Amir Michail via swift-evolution < swift-evolution@swift.org> wrote:

For example:

let x:Int
if … { x = 1 }
else if … { x = 2 }
else { precondition(false) } // no initialization needed

Similarly,

let x:Int
switch ... {
case …: x = 1
case …: x = 2
default: precondition(false) // no initialization needed
}
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Radek Pietruszewski) #5

I think what you mean is `fatalError()`.

You can’t do what you suggest, because you can’t prove that the expression passed to precondition will evaluate to false. (You theoretically could if the compiler checked for you passing `false`, but that makes no sense. Just go with `fatalError` or `preconditionFailure`.)

— Radek

···

On 12 Feb 2016, at 16:59, Amir Michail via swift-evolution <swift-evolution@swift.org> wrote:

For example:

let x:Int
if … { x = 1 }
else if … { x = 2 }
else { precondition(false) } // no initialization needed

Similarly,

let x:Int
switch ... {
case …: x = 1
case …: x = 2
default: precondition(false) // no initialization needed
}
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Chris Lattner) #6

Weird special cases make the compiler less predictable.

-Chris

···

On Feb 12, 2016, at 9:15 AM, Amir Michail via swift-evolution <swift-evolution@swift.org> wrote:

On Feb 12, 2016, at 12:09 PM, Radosław Pietruszewski <radexpl@gmail.com> wrote:

I think what you mean is `fatalError()`.

You can’t do what you suggest, because you can’t prove that the expression passed to precondition will evaluate to false. (You theoretically could if the compiler checked for you passing `false`, but that makes no sense. Just go with `fatalError` or `preconditionFailure`.)

What’s wrong with having the compiler explicitly check for “false”?


(Dmitri Gribenko) #7

How far would you require the compiler to go? precondition(2 < 1)?
precondition(someFunctionThatAlwaysReturnsFalse())?
precondition(isFermatsLastTheoremTrue())?

This is important to define precisely since the answer to this
question changes the set of the programs that the compiler accepts.

Dmitri

···

On Fri, Feb 12, 2016 at 9:15 AM, Amir Michail via swift-evolution <swift-evolution@swift.org> wrote:

On Feb 12, 2016, at 12:09 PM, Radosław Pietruszewski <radexpl@gmail.com> wrote:

I think what you mean is `fatalError()`.

You can’t do what you suggest, because you can’t prove that the expression passed to precondition will evaluate to false. (You theoretically could if the compiler checked for you passing `false`, but that makes no sense. Just go with `fatalError` or `preconditionFailure`.)

What’s wrong with having the compiler explicitly check for “false”?

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Chris Lattner) #8

That is not what you’re actually proposing. You are proposing that the compiler encode special knowledge of the precondition *library function* into the compiler, and teach it about a single special case. We don’t like the compiler to have special cases like this for a large number of reasons, in particular, if we did this, someone would file a bug asking for *their* equivalent reimplementation of precondition to have the same magic blessed behavior.

This is a slippery slope that leads to a lot of complexity downstream, it is better to keep the compiler simple and predictable. Also, as other people have pointed out, this has already been solved for you: just use preconditionFailure.

-Chris

···

On Feb 12, 2016, at 9:27 AM, Amir Michail <a.michail@me.com> wrote:

What’s wrong with having the compiler explicitly check for “false”?

Weird special cases make the compiler less predictable.

True, but not having them requires deeper knowledge of the standard libraries.

In practice, just checking for “false” would solve this problem.


(Jordan Rose) #9

This is a good observation. I think it deserves its own design and its own thread, though.

Jordan

···

On Feb 12, 2016, at 9:45 , Amir Michail via swift-evolution <swift-evolution@swift.org> wrote:

On Feb 12, 2016, at 12:41 PM, Ross O'Brien <narrativium+swift@gmail.com <mailto:narrativium+swift@gmail.com>> wrote:

I have a suggestion.
Suppose we think of 'switch' as being like a non-optional type. The compiler does its thing and tries to ensure that the switched expression will match something, and enforces a default if it cannot verify a matching state.
Could we force the switch? i.e. suffix the 'switch' keyword with an exclamation mark, to say: the programmer insists that one of these cases will match; there's no need for a default case, but if nothing matches then crash.

This doesn’t solve the more general problem — namely, that of required deep knowledge of the standard libraries.

A more general solution would be to provide a way for API writers to issue (heuristic) warnings for suboptimal usage of their APIs.


(Amir Michail) #10

It would be really helpful if you could describe the problem you're experiencing so I don't have to guess what it is from your example code.

I want to ensure that one of the cases applies. Otherwise, there is a bug in my code. That’s why I have the precondition(false).

However, writing code like this is annoying:

let x:Int
if … { x = 1 }
else if … { x = 2 }
else { x = dummyValue; precondition(false) }

···

On Feb 12, 2016, at 11:27 AM, Ross O'Brien <narrativium+swift@gmail.com> wrote:

Am I guessing right if I say that you want a change to Swift such that a switch initialisation can be 'force-unwrapped', such that if none of the cases apply, the app crashes, in a more explicit fashion?

I've written code like this, but I've tended towards 'default: fatalError()', which wouldn't be covered by your suggestion. 'precondition' isn't at fault here.

Just as a digression, I've just learned that 'precondition(false)' doesn't cause any immediately following code to receive the compiler warning 'will never be executed' that code in a 'if false { ... }' does. So that would be nice.

On Fri, Feb 12, 2016 at 3:59 PM, Amir Michail via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
For example:

let x:Int
if … { x = 1 }
else if … { x = 2 }
else { precondition(false) } // no initialization needed

Similarly,

let x:Int
switch ... {
case …: x = 1
case …: x = 2
default: precondition(false) // no initialization needed
}
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Amir Michail) #11

I think what you mean is `fatalError()`.

You can’t do what you suggest, because you can’t prove that the expression passed to precondition will evaluate to false. (You theoretically could if the compiler checked for you passing `false`, but that makes no sense. Just go with `fatalError` or `preconditionFailure`.)

What’s wrong with having the compiler explicitly check for “false”?

···

On Feb 12, 2016, at 12:09 PM, Radosław Pietruszewski <radexpl@gmail.com> wrote:

— Radek

On 12 Feb 2016, at 16:59, Amir Michail via swift-evolution <swift-evolution@swift.org> wrote:

For example:

let x:Int
if … { x = 1 }
else if … { x = 2 }
else { precondition(false) } // no initialization needed

Similarly,

let x:Int
switch ... {
case …: x = 1
case …: x = 2
default: precondition(false) // no initialization needed
}
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Amir Michail) #12

I think what you mean is `fatalError()`.

You can’t do what you suggest, because you can’t prove that the expression passed to precondition will evaluate to false. (You theoretically could if the compiler checked for you passing `false`, but that makes no sense. Just go with `fatalError` or `preconditionFailure`.)

What’s wrong with having the compiler explicitly check for “false”?

How far would you require the compiler to go? precondition(2 < 1)?
precondition(someFunctionThatAlwaysReturnsFalse())?
precondition(isFermatsLastTheoremTrue())?

Just “false”. Why would you write anything else?

···

On Feb 12, 2016, at 12:24 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:
On Fri, Feb 12, 2016 at 9:15 AM, Amir Michail via swift-evolution > <swift-evolution@swift.org> wrote:

On Feb 12, 2016, at 12:09 PM, Radosław Pietruszewski <radexpl@gmail.com> wrote:

This is important to define precisely since the answer to this
question changes the set of the programs that the compiler accepts.

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Amir Michail) #13

I think what you mean is `fatalError()`.

You can’t do what you suggest, because you can’t prove that the expression passed to precondition will evaluate to false. (You theoretically could if the compiler checked for you passing `false`, but that makes no sense. Just go with `fatalError` or `preconditionFailure`.)

What’s wrong with having the compiler explicitly check for “false”?

Weird special cases make the compiler less predictable.

True, but not having them requires deeper knowledge of the standard libraries.

In practice, just checking for “false” would solve this problem.

···

On Feb 12, 2016, at 12:23 PM, Chris Lattner <clattner@apple.com> wrote:

On Feb 12, 2016, at 9:15 AM, Amir Michail via swift-evolution <swift-evolution@swift.org> wrote:

On Feb 12, 2016, at 12:09 PM, Radosław Pietruszewski <radexpl@gmail.com> wrote:

-Chris


(Amir Michail) #14

What’s wrong with having the compiler explicitly check for “false”?

Weird special cases make the compiler less predictable.

True, but not having them requires deeper knowledge of the standard libraries.

In practice, just checking for “false” would solve this problem.

That is not what you’re actually proposing. You are proposing that the compiler encode special knowledge of the precondition *library function* into the compiler, and teach it about a single special case. We don’t like the compiler to have special cases like this for a large number of reasons, in particular, if we did this, someone would file a bug asking for *their* equivalent reimplementation of precondition to have the same magic blessed behavior.

What about having the compiler issue a warning pointing you to preconditionFailure whenever it sees precondition(false)?

···

On Feb 12, 2016, at 12:32 PM, Chris Lattner <clattner@apple.com> wrote:
On Feb 12, 2016, at 9:27 AM, Amir Michail <a.michail@me.com> wrote:

This is a slippery slope that leads to a lot of complexity downstream, it is better to keep the compiler simple and predictable. Also, as other people have pointed out, this has already been solved for you: just use preconditionFailure.

-Chris


(Amir Michail) #15

I have a suggestion.
Suppose we think of 'switch' as being like a non-optional type. The compiler does its thing and tries to ensure that the switched expression will match something, and enforces a default if it cannot verify a matching state.
Could we force the switch? i.e. suffix the 'switch' keyword with an exclamation mark, to say: the programmer insists that one of these cases will match; there's no need for a default case, but if nothing matches then crash.

This doesn’t solve the more general problem — namely, that of required deep knowledge of the standard libraries.

A more general solution would be to provide a way for API writers to issue (heuristic) warnings for suboptimal usage of their APIs.

···

On Feb 12, 2016, at 12:41 PM, Ross O'Brien <narrativium+swift@gmail.com> wrote:

For example:
let x:Int
switch! expression
{
    case ... { x = 1 }
    case ... { x = 2 }
    // no default. the ! signifies that the app should crash if none of these cases matches the expression
}

On Fri, Feb 12, 2016 at 5:32 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
On Feb 12, 2016, at 9:27 AM, Amir Michail <a.michail@me.com <mailto:a.michail@me.com>> wrote:
>>>
>>> What’s wrong with having the compiler explicitly check for “false”?
>>
>> Weird special cases make the compiler less predictable.
>
> True, but not having them requires deeper knowledge of the standard libraries.
>
> In practice, just checking for “false” would solve this problem.

That is not what you’re actually proposing. You are proposing that the compiler encode special knowledge of the precondition *library function* into the compiler, and teach it about a single special case. We don’t like the compiler to have special cases like this for a large number of reasons, in particular, if we did this, someone would file a bug asking for *their* equivalent reimplementation of precondition to have the same magic blessed behavior.

This is a slippery slope that leads to a lot of complexity downstream, it is better to keep the compiler simple and predictable. Also, as other people have pointed out, this has already been solved for you: just use preconditionFailure.

-Chris
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Amir Michail) #16

Okay, but the original general problem was that you wanted to ensure that one of the cases applied, and my suggestion addressed that problem.

Since then it's become whether or not the developer has knowledge of fatalError(), preconditionFailure(), and then the more general 'precondition'. It seems to me that the compiler clearly does have some boolean evaluation routine in place, or 'if false { ... }' wouldn't generate the 'this will never be executed' warning I mentioned earlier, and perhaps this routine could be applied to precondition calls as well.

Providing a way for me to issue warnings for suboptimal use of APIs I write is a third thing entirely.

It would also provide a solution to this problem in particular.

···

On Feb 12, 2016, at 12:56 PM, Ross O'Brien <narrativium+swift@gmail.com> wrote:

On Fri, Feb 12, 2016 at 5:45 PM, Amir Michail <a.michail@me.com <mailto:a.michail@me.com>> wrote:

On Feb 12, 2016, at 12:41 PM, Ross O'Brien <narrativium+swift@gmail.com <mailto:narrativium+swift@gmail.com>> wrote:

I have a suggestion.
Suppose we think of 'switch' as being like a non-optional type. The compiler does its thing and tries to ensure that the switched expression will match something, and enforces a default if it cannot verify a matching state.
Could we force the switch? i.e. suffix the 'switch' keyword with an exclamation mark, to say: the programmer insists that one of these cases will match; there's no need for a default case, but if nothing matches then crash.

This doesn’t solve the more general problem — namely, that of required deep knowledge of the standard libraries.

A more general solution would be to provide a way for API writers to issue (heuristic) warnings for suboptimal usage of their APIs.

For example:
let x:Int
switch! expression
{
    case ... { x = 1 }
    case ... { x = 2 }
    // no default. the ! signifies that the app should crash if none of these cases matches the expression
}

On Fri, Feb 12, 2016 at 5:32 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
On Feb 12, 2016, at 9:27 AM, Amir Michail <a.michail@me.com <mailto:a.michail@me.com>> wrote:
>>>
>>> What’s wrong with having the compiler explicitly check for “false”?
>>
>> Weird special cases make the compiler less predictable.
>
> True, but not having them requires deeper knowledge of the standard libraries.
>
> In practice, just checking for “false” would solve this problem.

That is not what you’re actually proposing. You are proposing that the compiler encode special knowledge of the precondition *library function* into the compiler, and teach it about a single special case. We don’t like the compiler to have special cases like this for a large number of reasons, in particular, if we did this, someone would file a bug asking for *their* equivalent reimplementation of precondition to have the same magic blessed behavior.

This is a slippery slope that leads to a lot of complexity downstream, it is better to keep the compiler simple and predictable. Also, as other people have pointed out, this has already been solved for you: just use preconditionFailure.

-Chris
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Ross O'Brien) #17

I have a suggestion.
Suppose we think of 'switch' as being like a non-optional type. The
compiler does its thing and tries to ensure that the switched expression
will match something, and enforces a default if it cannot verify a matching
state.
Could we force the switch? i.e. suffix the 'switch' keyword with an
exclamation mark, to say: the programmer insists that one of these cases
will match; there's no need for a default case, but if nothing matches then
crash.

For example:
let x:Int
switch! expression
{
    case ... { x = 1 }
    case ... { x = 2 }
    // no default. the ! signifies that the app should crash if none of
these cases matches the expression
}

···

On Fri, Feb 12, 2016 at 5:32 PM, Chris Lattner via swift-evolution < swift-evolution@swift.org> wrote:

On Feb 12, 2016, at 9:27 AM, Amir Michail <a.michail@me.com> wrote:
>>>
>>> What’s wrong with having the compiler explicitly check for “false”?
>>
>> Weird special cases make the compiler less predictable.
>
> True, but not having them requires deeper knowledge of the standard
libraries.
>
> In practice, just checking for “false” would solve this problem.

That is not what you’re actually proposing. You are proposing that the
compiler encode special knowledge of the precondition *library function*
into the compiler, and teach it about a single special case. We don’t like
the compiler to have special cases like this for a large number of reasons,
in particular, if we did this, someone would file a bug asking for *their*
equivalent reimplementation of precondition to have the same magic blessed
behavior.

This is a slippery slope that leads to a lot of complexity downstream, it
is better to keep the compiler simple and predictable. Also, as other
people have pointed out, this has already been solved for you: just use
preconditionFailure.

-Chris
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Ross O'Brien) #18

Okay, but the original general problem was that you wanted to ensure that
one of the cases applied, and my suggestion addressed that problem.

Since then it's become whether or not the developer has knowledge of
fatalError(), preconditionFailure(), and then the more general
'precondition'. It seems to me that the compiler clearly does have some
boolean evaluation routine in place, or 'if false { ... }' wouldn't
generate the 'this will never be executed' warning I mentioned earlier, and
perhaps this routine could be applied to precondition calls as well.

Providing a way for me to issue warnings for suboptimal use of APIs I write
is a third thing entirely.

···

On Fri, Feb 12, 2016 at 5:45 PM, Amir Michail <a.michail@me.com> wrote:

On Feb 12, 2016, at 12:41 PM, Ross O'Brien <narrativium+swift@gmail.com> > wrote:

I have a suggestion.
Suppose we think of 'switch' as being like a non-optional type. The
compiler does its thing and tries to ensure that the switched expression
will match something, and enforces a default if it cannot verify a matching
state.
Could we force the switch? i.e. suffix the 'switch' keyword with an
exclamation mark, to say: the programmer insists that one of these cases
will match; there's no need for a default case, but if nothing matches then
crash.

This doesn’t solve the more general problem — namely, that of required
deep knowledge of the standard libraries.

A more general solution would be to provide a way for API writers to issue
(heuristic) warnings for suboptimal usage of their APIs.

For example:
let x:Int
switch! expression
{
    case ... { x = 1 }
    case ... { x = 2 }
    // no default. the ! signifies that the app should crash if none of
these cases matches the expression
}

On Fri, Feb 12, 2016 at 5:32 PM, Chris Lattner via swift-evolution < > swift-evolution@swift.org> wrote:

On Feb 12, 2016, at 9:27 AM, Amir Michail <a.michail@me.com> wrote:
>>>
>>> What’s wrong with having the compiler explicitly check for “false”?
>>
>> Weird special cases make the compiler less predictable.
>
> True, but not having them requires deeper knowledge of the standard
libraries.
>
> In practice, just checking for “false” would solve this problem.

That is not what you’re actually proposing. You are proposing that the
compiler encode special knowledge of the precondition *library function*
into the compiler, and teach it about a single special case. We don’t like
the compiler to have special cases like this for a large number of reasons,
in particular, if we did this, someone would file a bug asking for *their*
equivalent reimplementation of precondition to have the same magic blessed
behavior.

This is a slippery slope that leads to a lot of complexity downstream, it
is better to keep the compiler simple and predictable. Also, as other
people have pointed out, this has already been solved for you: just use
preconditionFailure.

-Chris
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Thorsten Seitz) #19

Why would you write anything else than preconditionFailure()??

-Thorsten

···

Am 12.02.2016 um 18:26 schrieb Amir Michail via swift-evolution <swift-evolution@swift.org>:

How far would you require the compiler to go? precondition(2 < 1)?
precondition(someFunctionThatAlwaysReturnsFalse())?
precondition(isFermatsLastTheoremTrue())?

Just “false”. Why would you write anything else?


(Alexey Demedetskiy) #20

+1 for this switch behavior. Can we also treat switch? as one with did not require default checking?

···

I have a suggestion.
Suppose we think of 'switch' as being like a non-optional type. The compiler does its thing and tries to ensure that the switched expression will match something, and enforces a default if it cannot verify a matching state.
Could we force the switch? i.e. suffix the 'switch' keyword with an exclamation mark, to say: the programmer insists that one of these cases will match; there's no need for a default case, but if nothing matches then crash.

For example:
let x:Int
switch! expression
{
case ... { x = 1 }
case ... { x = 2 }
// no default. the ! signifies that the app should crash if none of these cases matches the expression
}

On Fri, Feb 12, 2016 at 5:32 PM, Chris Lattner via swift-evolution<swift-evolution@swift.org(mailto:swift-evolution@swift.org)>wrote:
> On Feb 12, 2016, at 9:27 AM, Amir Michail<a.michail@me.com(mailto:a.michail@me.com)>wrote:
> >>>
> >>>What’s wrong with having the compiler explicitly check for “false”?
> >>
> >>Weird special cases make the compiler less predictable.
> >
> >True, but not having them requires deeper knowledge of the standard libraries.
> >
> >In practice, just checking for “false” would solve this problem.
>
> That is not what you’re actually proposing.You are proposing that the compiler encode special knowledge of the precondition *library function* into the compiler, and teach it about a single special case.We don’t like the compiler to have special cases like this for a large number of reasons, in particular, if we did this, someone would file a bug asking for *their* equivalent reimplementation of precondition to have the same magic blessed behavior.
>
> This is a slippery slope that leads to a lot of complexity downstream, it is better to keep the compiler simple and predictable.Also, as other people have pointed out, this has already been solved for you: just use preconditionFailure.
>
> -Chris
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org(mailto:swift-evolution@swift.org)
> https://lists.swift.org/mailman/listinfo/swift-evolution