[Draft] Change @noreturn to unconstructible return type

>
>>
>>> I disagree. We are discussing how to annotate a function in some way so that the compiler knows that the code following it will never be executed *and* so a human who reads the declaration knows that it does not return. “Never" is a poor choice for that. Never what? Never return? Never use this function? Never say never again?
>>
>> "Never return". That's why it's in the return type slot, right after the `->`. If you read it out loud, you'll read "returns Never", which is exactly correct.
>>
>> NoReturn, on the other hand, does *not* read well in that slot: "returns NoReturn". Huh? I mean, I suppose you won't misunderstand it, but it makes no sense whatsoever *as a type name*.
>
> But it’s *not* a type. You’ll never have an instance of it.

That's the dictionary definition of a bottom type, though: a type which has no values.

Since it’s not a type name, it doesn’t make sense that it needs to look like one. What it is doing is telling you something about the behavior of the function itself, not its return value. Its return value, if there were one, is irrelevant, since the function, by its very nature, will never even get to the point where it would return it.

And that's the dictionary definition of a function where the return type is bottom. This isn't something being made up just for Swift...

What’s the dictionary definition of a do loop? Or a for loop? Or try/catch?

Swift doesn’t do things the same as other languages in lots of places. I don’t see why it has to be different here. @noreturn is a clearer description of what this construct does.

Hi,

I know of no other language that has a named bottom type that can syntactically compete with non-bottom-types. Swift would be the first (I think). The definition of bottom types hasn't been made up for Swift, right. "bottom type" is to "type" as is "javascript" to "java". Almost every language has a bottom type, including Swift 1. That doesn't mean that we should give it a name.

-Michael

···

Am 07.06.2016 um 22:36 schrieb Charles Srstka via swift-evolution <swift-evolution@swift.org>:

On Jun 7, 2016, at 3:12 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
On Tue, Jun 7, 2016 at 2:49 PM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:
> Am 07.06.2016 um 19:45 schrieb Charles Srstka via swift-evolution <swift-evolution@swift.org>:
>> On Jun 7, 2016, at 11:47 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

Charles

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

I disagree about the theoretical soundness here. It is implementable and doesn't introduce ambiguities, that's all IMHO.

-Michael

···

Am 07.06.2016 um 22:56 schrieb Xiaodi Wu via swift-evolution <swift-evolution@swift.org>:

My response was simply to say that Never or NoReturn would in fact be a type, which is a good justification for looking like one. This behavior would be learnable and is theoretically sound, not an ad hoc idea being made up on the spot. No doubt, @noreturn is clearer today, but how much of that is because it's what we already know? And FWIW, "returns never" is hard to misinterpret, no?

The problem is, types flow through the type system. Use a NoReturn method with optional chaining, now you have an Optional<NoReturn>. flatMap over that Optional<NoReturn>, now you have a parameter of type NoReturn. What's a *parameter* of type NoReturn? You'd want it to be, say, a different bottom type named NoPass, but you can't—the type came from a NoReturn, and it's stuck being a NoReturn.

This is a method that *does not return*. The compiler should error if you try to use the “result” of a no return function. In fact, it should error if there is any more code after the method that can’t be reached by a path that avoids the call.

Like the path introduced by optional chaining, which I *specifically* mentioned in the paragraph you quoted so scathingly.

Let me write out an example explicitly so you can see what I mean. Suppose you have this protocol:

  protocol Runnable {
    associatedtype Result
    func run() -> Result
    static func isSuccessful(_ result: Result) -> Bool
  }

And you implement this generic function to use it:

  func runAndCheck<R: Runnable>(_ runner: R?) -> Bool {
    return runner?.run().flatMap(R.isSuccessful) ?? true
  }

With intermediate variables and explicit type annotations, that's:

  func runAndCheck<R: Runnable>(_ runner: R?) -> Bool {
    let optionalResult: R.Result? = runner?.run()
    let optionalSuccess: Bool? = processedResult.flatMap(R.isSuccessful)
    let success: Bool = optionalSuccess ?? true
    return success
  }

Now, suppose `R` is a `RunLoop` type with a `run()` method that never returns. (`NSRunLoop` is similar to this type, although its `run()` actually can return; you just can't really count on it ever doing so.) Then you have this:

  class RunLoop: Runnable {
    …
    associatedtype Result = Never
    
    func run() -> Never {
      …
    }
    
    class func isSuccessful(_ result: Never) -> Bool {
      // Uncallable due to Never parameter
    }
  }

And `runAndCheck(_:)` specializes to:

  func runAndCheck(_ runner: RunLoop?) -> Bool {
    let optionalResult: Never? = runner?.run()
    let optionalSuccess: Bool? = processedResult.flatMap(RunLoop.isSuccessful)
    let success: Bool = optionalSuccess ?? true
    return success
  }

So, as you can see, this code *does* have a path beyond the non-returning call: the path where `runner` is `nil`.

This code benefits in several ways from using a bottom type to express `run()`'s non-returning nature:

1. The protocol now correctly expresses the fact that, if `run()` can never return, then `isSuccessful(_:)` can never be called. With a `@noreturn` attribute, `run()` would have to have some kind of fake return type (probably `Void`), and `isSuccessful` would be callable with a `Void`.

2. Because the compiler can prove that `isSuccessful(_:)` can never be called, there's no need to provide any implementation for it. The compiler can prove that any implementation you might provide is dead code, because it could only be reached after code that would have to instantiate a `Never`. With a `@noreturn` attribute, `Result` would be some fake type like `Void`, and the compiler could not prove that `isSuccessful(_:)` is unreachable.

3. Since `optionalResult` is of type `Never?`, the compiler can prove that it cannot ever be `.some`. To construct a `.some`, you would need to instantiate a `Never`, which is impossible. With a `@noreturn`-type solution, `optionalResult` would be of (say) type `Void?`, and the fact that `.some` was impossible would be lost to us.

This means that:

1. If the compiler inlines `Optional<Never>.flatMap`, it can eliminate the `.some` case (since it can never match), then eliminate the `switch` statement entirely, turning the method into simply `return .none`.

  func runAndCheck(_ runner: RunLoop?) -> Bool {
    let optionalResult: Never? = runner?.run()
    let optionalSuccess: Bool? = .none
    let success: Bool = optionalSuccess ?? true
    return success
  }

2. The compiler can then notice that `optionalSuccess` is always `.none`, so `success` is always `true`.

  func runAndCheck(_ runner: RunLoop?) -> Bool {
    let optionalResult: Never? = runner?.run()
    let success: Bool = true
    return success
  }

3. The compiler can then notice that `optionalResult` is never actually used, and eliminate that value.

  func runAndCheck(_ runner: RunLoop?) -> Bool {
    _ = runner?.run()
    let success: Bool = true
    return success
  }

Could the compiler have done this without using `Never`? Maybe; the information is still there if you look (at least if it knows `run()` is @noreturn). But it's less straightforward to make it flow through the entire function like this. If we use a bottom type to represent the fact that a function cannot return, then the type system naturally carries this information to all the places where it's needed.

···

--
Brent Royal-Gordon
Architechies

A return type makes a lot of sense linguistically but does not cover all practical cases because you might not be the one deciding what the function's signature is. For example, you might implement a protocol method that is non-optional, but you never expect to be called. The only way to indicate that to the compiler is with an attribute.

If Swift permits return type covariance—that is, for an override or implementation to tighten the return type—then this will happen naturally: Never is a subtype of all types, so you can validly change any return type to Never and meet the supertype's requirements.

Good point!

I believe Swift supports return type covariance for overridden methods, but not for protocol requirements. This is, in my opinion, an incorrect behavior which should be changed.

+1

-Thorsten

···

Am 08.06.2016 um 01:36 schrieb Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org>:

--
Brent Royal-Gordon
Architechies

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

+1 for keeping it as it is for the same arguments and many other arguments already details previously, like telling the function can return something that does not exists is not the same that telling it does not return or the fact that you can’t expect to code it purely in the standard library using type if you want to be able to warn on unreachable code let the compiler optimize based on the fact the function never returns (and does not return never).

···

Le 8 juin 2016 à 02:21, Jordan Rose via swift-evolution <swift-evolution@swift.org> a écrit :

On Jun 7, 2016, at 12:49, Michael Peternell via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Am 07.06.2016 um 19:45 schrieb Charles Srstka via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

On Jun 7, 2016, at 11:47 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I disagree. We are discussing how to annotate a function in some way so that the compiler knows that the code following it will never be executed *and* so a human who reads the declaration knows that it does not return. “Never" is a poor choice for that. Never what? Never return? Never use this function? Never say never again?

"Never return". That's why it's in the return type slot, right after the `->`. If you read it out loud, you'll read "returns Never", which is exactly correct.

NoReturn, on the other hand, does *not* read well in that slot: "returns NoReturn". Huh? I mean, I suppose you won't misunderstand it, but it makes no sense whatsoever *as a type name*.

But it’s *not* a type. You’ll never have an instance of it. Since it’s not a type name, it doesn’t make sense that it needs to look like one. What it is doing is telling you something about the behavior of the function itself, not its return value. Its return value, if there were one, is irrelevant, since the function, by its very nature, will never even get to the point where it would return it. Either it’s going to kill the app via a fatalError or something, or we have something like dispatch_main() which will keep executing until the program stops, and one way or another, it won’t return.

For that reason, frankly, I don’t understand why we want to change this from being an attribute, which seems to me the more natural and logical choice to describe this behavior. If we *do* have to change it, though, NoReturn conveys the most clearly to the reader what it does.

+1 for @noreturn
We don't have to change it.
We have to keep it.

I strongly agree. Just because it can be modelled as a type doesn’t mean it’s the best way to represent the concept. It feels like uniformity for uniformity’s sake.

func fatalError() -> Never

@noreturn func fatalError()

The first one probably isn't too hard to explain to a learner. The second one probably doesn’t need an explanation.

Scala has `Nothing`.

···

On Tue, Jun 7, 2016 at 3:57 PM, <michael.peternell@gmx.at> wrote:

> Am 07.06.2016 um 22:36 schrieb Charles Srstka via swift-evolution < > swift-evolution@swift.org>:
>
>> On Jun 7, 2016, at 3:12 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
>>
>> On Tue, Jun 7, 2016 at 2:49 PM, Michael Peternell via swift-evolution < > swift-evolution@swift.org> wrote:
>>
>> > Am 07.06.2016 um 19:45 schrieb Charles Srstka via swift-evolution < > swift-evolution@swift.org>:
>> >
>> >> On Jun 7, 2016, at 11:47 AM, Brent Royal-Gordon via swift-evolution < > swift-evolution@swift.org> wrote:
>> >>
>> >>> I disagree. We are discussing how to annotate a function in some
way so that the compiler knows that the code following it will never be
executed *and* so a human who reads the declaration knows that it does not
return. “Never" is a poor choice for that. Never what? Never return? Never
use this function? Never say never again?
>> >>
>> >> "Never return". That's why it's in the return type slot, right after
the `->`. If you read it out loud, you'll read "returns Never", which is
exactly correct.
>> >>
>> >> NoReturn, on the other hand, does *not* read well in that slot:
"returns NoReturn". Huh? I mean, I suppose you won't misunderstand it, but
it makes no sense whatsoever *as a type name*.
>> >
>> > But it’s *not* a type. You’ll never have an instance of it.
>>
>> That's the dictionary definition of a bottom type, though: a type which
has no values.
>>
>> Since it’s not a type name, it doesn’t make sense that it needs to look
like one. What it is doing is telling you something about the behavior of
the function itself, not its return value. Its return value, if there were
one, is irrelevant, since the function, by its very nature, will never even
get to the point where it would return it.
>>
>> And that's the dictionary definition of a function where the return
type is bottom. This isn't something being made up just for Swift...
>
> What’s the dictionary definition of a do loop? Or a for loop? Or
try/catch?
>
> Swift doesn’t do things the same as other languages in lots of places. I
don’t see why it has to be different here. @noreturn is a clearer
description of what this construct does.

Hi,

I know of no other language that has a named bottom type that can
syntactically compete with non-bottom-types. Swift would be the first (I
think). The definition of bottom types hasn't been made up for Swift,
right. "bottom type" is to "type" as is "javascript" to "java". Almost
every language has a bottom type, including Swift 1. That doesn't mean that
we should give it a name.

I disagree. We are discussing how to annotate a function in some way so that the compiler knows that the code following it will never be executed *and* so a human who reads the declaration knows that it does not return. “Never" is a poor choice for that. Never what? Never return? Never use this function? Never say never again?

"Never return". That's why it's in the return type slot, right after the `->`. If you read it out loud, you'll read "returns Never", which is exactly correct.

NoReturn, on the other hand, does *not* read well in that slot: "returns NoReturn". Huh? I mean, I suppose you won't misunderstand it, but it makes no sense whatsoever *as a type name*.

But it’s *not* a type. You’ll never have an instance of it. Since it’s not a type name, it doesn’t make sense that it needs to look like one. What it is doing is telling you something about the behavior of the function itself, not its return value. Its return value, if there were one, is irrelevant, since the function, by its very nature, will never even get to the point where it would return it. Either it’s going to kill the app via a fatalError or something, or we have something like dispatch_main() which will keep executing until the program stops, and one way or another, it won’t return.

For that reason, frankly, I don’t understand why we want to change this from being an attribute, which seems to me the more natural and logical choice to describe this behavior. If we *do* have to change it, though, NoReturn conveys the most clearly to the reader what it does.

+1 for @noreturn
We don't have to change it.
We have to keep it.

this is so unfortunate… IMHO the proposal is the right move because it goes into the direction of unifying things in the language. the problem is that it is difficult to see it without looking at the language as a whole. then we realize that this can be connected to the change of dynamicType to a function or to the fact that .Type and .Self might also warrant a revisiting.

from a practical point of view, a @noreturn function is just so much different than any other function. this shouldn't be "unified". we can discuss if bottom types and normal types can be unified from a theoretical/academical point of view. but in the real world, a @noreturn function does not return at all, whereas most other function does return execution to its caller. To honor this view, a function that returns `Void` is meant to return, it just doesn't return any particular value. But `Void` should be the type with no values, not the type with exactly one value, so a function that returns `Void` shouldn't be able to return, because there can be no `Void` value. `Void` is an unconstructable type, and yet it is different from `@noreturn`. That would be a unification ;) . The whole concept of return-values is so much different in imperative programming than it is in Haskell and with "denotational semantics". Therefore we have 1) functions that return a value, e.g. `Int`, 2) functions that return no value (`Void`), and 3) functions that doesn't return at all (`@noreturn`) => I would like to keep it that way.

···

Am 07.06.2016 um 22:14 schrieb L Mihalkovic via swift-evolution <swift-evolution@swift.org>:

On Jun 7, 2016, at 9:49 PM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

Am 07.06.2016 um 19:45 schrieb Charles Srstka via swift-evolution <swift-evolution@swift.org>:

On Jun 7, 2016, at 11:47 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

I do hope the core team does pull ranks and goes with it. Frankly I have no stake in the name, and I would even argue that there might be a possible case for doing something even more un-explainable than this change:

1) create a protocol SwiftBottomType { } [ the core team might defend the idea that it should really be BuiltinBottomType, which I have no issues with ]

2) then create a enum NoReturn: SwiftBottomType {}

When looking at this question and a couple of other related ones, a pattern should form, and the rational become self evident.

-Michael

Charles

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

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

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

Ok, one last thing, then I go to sleep for today...

Basic Definition of a "Type":
I learned in university that a type is a "set of values".
When a function has a return type of R, it means that it does return a value of type R.

On the other hand, a @noreturn function doesn't return any value, so it doesn't really have a return type. The whole concept of a "bottom type" was made to create a model where every function can be specified as having a return type. This isn't really a useful concept outside of the Haskell language [1].

I like the "Basic Definition of a Type": while it does not generalize to non-returning functions, it includes all functions in the mathematical sense; it includes all functions that are meant to return a value. It includes all functions that terminate and that neither crash nor throw. This "basic definition" is the reason why we have functions at all. We don't have functions in order to build an academic model where we can study denotational semantics [2] in, and that is super-consistent. We have them to calculate things. And we don't calculate values of type `NoReturn` or `Nothing`.

If I haven't convinced you yet => we'll meet again when casting votes for the proposal (if it will ever go into formal review)

-Michael

[1] Yes, someone will find another language where it is useful too, but anyhow, it's not useful for Swift, Java, Obj-C or C++.
[2] Haskell/Denotational semantics - Wikibooks, open books for an open world

On the other hand...

The first is rather clever and beautiful looking...making it somewhat Swifty.

“Clever” is not necessarily good. “Clever” implies cleverness is needed to understand it.

“Beautiful” is a subjective concept. Personally, I think a computer language construct is beautiful if it conveys the intent with complete clarity. By my criteria the @noreturn attribute is beautiful and the -> Never return type is ugly (or at least less beautiful).

“Swifty” is a nebulous concept that nobody has defined and thus means different things to different people. It seems to me that “it’s not Swifty” is used mostly to try to shut down debate when reasoned arguments are thin on the ground.

I never cared for annotations:

That’s a subjective opinion.

- they make it look noisy

How so?

- they seem like a "hack" rather than a true part of the standard library

Annotations aren’t part of the standard library are they? I thought they were part of the language.

Also technically,

@noreturn func fatalError()

can be modeled as (I think?):
@noreturn func fatalError() -> Void

which doesn't make much sense.

In what way does it not make sense? Theoretically there’s no problem with specifying a return type for a noreturn function.

Also, could this fix this issue:
"That said, you can’t override a function or method that is marked with the noreturnattribute with a function or method that is not. Similar rules apply when you implement a protocol method in a conforming type."

Overriding a method without this as an attribute could allow this. I'm not sure if this is something people would need though or if it even makes sense.

It doesn’t make sense. If you have a protocol or a base class with an @noreturn method, and you could override it with a method that does return, then code using the protocol or base class that assumes that the method does not return as the API contract says will be surprised when, after dispatching the call, it returns.

···

On 8 Jun 2016, at 03:10, Brandon Knope via swift-evolution <swift-evolution@swift.org> wrote:

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

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

I strongly disagree. Type systems are not some esoteric academic thing only working for Haskell or functional languages. Just have a look at the type systems of other languages like Ceylon, Rust or TypeScript.

I hope that Swift will someday have variance annotations for generic parameters and associated types so that we may express sound subtyping rules between generic types. A real bottom type will fit in there just nicely.

+1 for a real bottom type
+1 for calling it Never

-Thorsten

···

Am 07.06.2016 um 22:43 schrieb Michael Peternell via swift-evolution <swift-evolution@swift.org>:

Am 07.06.2016 um 22:14 schrieb L Mihalkovic via swift-evolution <swift-evolution@swift.org>:

On Jun 7, 2016, at 9:49 PM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

Am 07.06.2016 um 19:45 schrieb Charles Srstka via swift-evolution <swift-evolution@swift.org>:

On Jun 7, 2016, at 11:47 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

I disagree. We are discussing how to annotate a function in some way so that the compiler knows that the code following it will never be executed *and* so a human who reads the declaration knows that it does not return. “Never" is a poor choice for that. Never what? Never return? Never use this function? Never say never again?

"Never return". That's why it's in the return type slot, right after the `->`. If you read it out loud, you'll read "returns Never", which is exactly correct.

NoReturn, on the other hand, does *not* read well in that slot: "returns NoReturn". Huh? I mean, I suppose you won't misunderstand it, but it makes no sense whatsoever *as a type name*.

But it’s *not* a type. You’ll never have an instance of it. Since it’s not a type name, it doesn’t make sense that it needs to look like one. What it is doing is telling you something about the behavior of the function itself, not its return value. Its return value, if there were one, is irrelevant, since the function, by its very nature, will never even get to the point where it would return it. Either it’s going to kill the app via a fatalError or something, or we have something like dispatch_main() which will keep executing until the program stops, and one way or another, it won’t return.

For that reason, frankly, I don’t understand why we want to change this from being an attribute, which seems to me the more natural and logical choice to describe this behavior. If we *do* have to change it, though, NoReturn conveys the most clearly to the reader what it does.

+1 for @noreturn
We don't have to change it.
We have to keep it.

this is so unfortunate… IMHO the proposal is the right move because it goes into the direction of unifying things in the language. the problem is that it is difficult to see it without looking at the language as a whole. then we realize that this can be connected to the change of dynamicType to a function or to the fact that .Type and .Self might also warrant a revisiting.

from a practical point of view, a @noreturn function is just so much different than any other function. this shouldn't be "unified". we can discuss if bottom types and normal types can be unified from a theoretical/academical point of view. but in the real world, a @noreturn function does not return at all, whereas most other function does return execution to its caller. To honor this view, a function that returns `Void` is meant to return, it just doesn't return any particular value. But `Void` should be the type with no values, not the type with exactly one value, so a function that returns `Void` shouldn't be able to return, because there can be no `Void` value. `Void` is an unconstructable type, and yet it is different from `@noreturn`. That would be a unification ;) . The whole concept of return-values is so much different in imperative programming than it is in Haskell and with "denotational semantics". Therefore we have 1) functions that return a value, e.g. `Int`, 2) functions that return no value (`Void`), and 3) functions that doesn't return at all (`@noreturn`) => I would like to keep it that way.

I do hope the core team does pull ranks and goes with it. Frankly I have no stake in the name, and I would even argue that there might be a possible case for doing something even more un-explainable than this change:

1) create a protocol SwiftBottomType { } [ the core team might defend the idea that it should really be BuiltinBottomType, which I have no issues with ]

2) then create a enum NoReturn: SwiftBottomType {}

When looking at this question and a couple of other related ones, a pattern should form, and the rational become self evident.

-Michael

Charles

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

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

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

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

Ok, one last thing, then I go to sleep for today...

Basic Definition of a "Type":
I learned in university that a type is a "set of values".

Yep. And because sets can be empty there is a type with an empty set, the bottom type.

When a function has a return type of R, it means that it does return a value of type R.

From this follows naturally that a function with return type Never cannot return, because there is no such value in Never's empty set.

On the other hand, a @noreturn function doesn't return any value, so it doesn't really have a return type. The whole concept of a "bottom type" was made to create a model where every function can be specified as having a return type. This isn't really a useful concept outside of the Haskell language [1].

Actually Haskell does not have an explicit bottom type (which is not needed because there is no subtyping in Haskell) but other languages have like Scala and Ceylon. And Ceylon does very elegant things with its bottom type in conjunction with union types, e.g. discerning in the type system between Iterables statically known to be empty or non-empty. And Ceylon certainly is not an academic language as they have always strived (quite successful IMO) to be a language with easily understandable concepts. For example, they did introduce union and intersection types not for their theoretical power but to make all types representable as normal types of the language, even such types that have been inferred by the type system when dealing with generics, so that error messages from the compiler would be easily understandable. Only later they discovered how useful type unions and intersections are and how natural many things can be solved with them.

I like the "Basic Definition of a Type": while it does not generalize to non-returning functions,

But it does if you include the empty set.

-Thorsten

···

Am 07.06.2016 um 23:32 schrieb Michael Peternell via swift-evolution <swift-evolution@swift.org>:

it includes all functions in the mathematical sense; it includes all functions that are meant to return a value. It includes all functions that terminate and that neither crash nor throw. This "basic definition" is the reason why we have functions at all. We don't have functions in order to build an academic model where we can study denotational semantics [2] in, and that is super-consistent. We have them to calculate things. And we don't calculate values of type `NoReturn` or `Nothing`.

If I haven't convinced you yet => we'll meet again when casting votes for the proposal (if it will ever go into formal review)

-Michael

[1] Yes, someone will find another language where it is useful too, but anyhow, it's not useful for Swift, Java, Obj-C or C++.
[2] Haskell/Denotational semantics - Wikibooks, open books for an open world

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

On the other hand...

The first is rather clever and beautiful looking...making it somewhat Swifty.

“Clever” is not necessarily good. “Clever” implies cleverness is needed to understand it.

I knew I would regret using this word. I can do this too: "clever" is not necessarily bad either. (The very definition says "quick to understand, learn...". Seems pretty apt here)

“Beautiful” is a subjective concept. Personally, I think a computer language construct is beautiful if it conveys the intent with complete clarity. By my criteria the @noreturn attribute is beautiful and the -> Never return type is ugly (or at least less beautiful).

Of course it is subjective. Almost every reply in swift evolution is rooted in personal opinion.

“Swifty” is a nebulous concept that nobody has defined and thus means different things to different people. It seems to me that “it’s not Swifty” is used mostly to try to shut down debate when reasoned arguments are thin on the ground.

I guess we need to tell this to Chris...who uses it quite often. "Swifty" IS a thing. It's just not 100% defined and constantly changing.

I never cared for annotations:

That’s a subjective opinion.

Of course...but isn't this where I share...my opinion?

- they make it look noisy

How so?

@noreturn func test() -> Void
func test() -> Never

Objectively...it is less noisy by using less characters :P.

Also, the function information seems somewhat lost with the heavy @ annotation (my opinion!). My eyes are immediately drawn to the annotation when looking at this signature. Is this good or bad? It's all subjective, but to me it makes this version noisier.

- they seem like a "hack" rather than a true part of the standard library

Annotations aren’t part of the standard library are they? I thought they were part of the language.

That was kind of my point. Doesn't swift try to define almost everything in the standard library? It would be more Swifty!

Also technically,

@noreturn func fatalError()

can be modeled as (I think?):
@noreturn func fatalError() -> Void

which doesn't make much sense.

In what way does it not make sense? Theoretically there’s no problem with specifying a return type for a noreturn function.

It's redundant. And why would a noreturn function have a return type? Maybe I'm missing a use case

Also, could this fix this issue:
"That said, you can’t override a function or method that is marked with the noreturnattribute with a function or method that is not. Similar rules apply when you implement a protocol method in a conforming type."

Overriding a method without this as an attribute could allow this. I'm not sure if this is something people would need though or if it even makes sense.

It doesn’t make sense. If you have a protocol or a base class with an @noreturn method, and you could override it with a method that does return, then code using the protocol or base class that assumes that the method does not return as the API contract says will be surprised when, after dispatching the call, it returns.

This one was a stretch on my part, but I need to think a little more on this.

Brandon

···

Sent from my iPad

On Jun 8, 2016, at 5:59 AM, Jeremy Pereira <jeremy.j.pereira@googlemail.com> wrote:

On 8 Jun 2016, at 03:10, Brandon Knope via swift-evolution <swift-evolution@swift.org> wrote:

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

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

I strongly disagree. Type systems are not some esoteric academic thing only working for Haskell or functional languages. Just have a look at the type systems of other languages like Ceylon, Rust or TypeScript.

I hope that Swift will someday have variance annotations for generic parameters and associated types so that we may express sound subtyping rules between generic types. A real bottom type will fit in there just nicely.

+1 for a real bottom type
+1 for calling it Never

+1 on all accounts (it is not the first time I find myself in agreement with many of the choices you support, and more interestingly, with the rational you use to support them: usually a mix between references to other examples and pragmatism).

here is another twist on Never… see further down...

-Thorsten

I disagree. We are discussing how to annotate a function in some way so that the compiler knows that the code following it will never be executed *and* so a human who reads the declaration knows that it does not return. “Never" is a poor choice for that. Never what? Never return? Never use this function? Never say never again?

"Never return". That's why it's in the return type slot, right after the `->`. If you read it out loud, you'll read "returns Never", which is exactly correct.

NoReturn, on the other hand, does *not* read well in that slot: "returns NoReturn". Huh? I mean, I suppose you won't misunderstand it, but it makes no sense whatsoever *as a type name*.

But it’s *not* a type. You’ll never have an instance of it. Since it’s not a type name, it doesn’t make sense that it needs to look like one. What it is doing is telling you something about the behavior of the function itself, not its return value. Its return value, if there were one, is irrelevant, since the function, by its very nature, will never even get to the point where it would return it. Either it’s going to kill the app via a fatalError or something, or we have something like dispatch_main() which will keep executing until the program stops, and one way or another, it won’t return.

For that reason, frankly, I don’t understand why we want to change this from being an attribute, which seems to me the more natural and logical choice to describe this behavior. If we *do* have to change it, though, NoReturn conveys the most clearly to the reader what it does.

+1 for @noreturn
We don't have to change it.
We have to keep it.

this is so unfortunate… IMHO the proposal is the right move because it goes into the direction of unifying things in the language. the problem is that it is difficult to see it without looking at the language as a whole. then we realize that this can be connected to the change of dynamicType to a function or to the fact that .Type and .Self might also warrant a revisiting.

from a practical point of view, a @noreturn function is just so much different than any other function. this shouldn't be "unified". we can discuss if bottom types and normal types can be unified from a theoretical/academical point of view. but in the real world, a @noreturn function does not return at all, whereas most other function does return execution to its caller. To honor this view, a function that returns `Void` is meant to return, it just doesn't return any particular value. But `Void` should be the type with no values, not the type with exactly one value, so a function that returns `Void` shouldn't be able to return, because there can be no `Void` value. `Void` is an unconstructable type, and yet it is different from `@noreturn`. That would be a unification ;) . The whole concept of return-values is so much different in imperative programming than it is in Haskell and with "denotational semantics". Therefore we have 1) functions that return a value, e.g. `Int`, 2) functions that return no value (`Void`), and 3) functions that doesn't return at all (`@noreturn`) => I would like to keep it that way.

Consider for a moment that the bottom type is a technical aspect of the runtime., the thing that the compiler needs so avoid some internal magic while steering towards expressing more things that can be expressed with protocols, using protocols. So that would give the compiler what it needs to have more internal symmetry. But then nothing says that our needs are the same as the compiler’s, particularly when it comes to expressivity. So that leaves us with the possibility of having a bottom type, and having something based on it that can present a more user friendly interface. And while we are at it, nothing says that the user facing side has to be universal, fitting all possible use cases. So then that opens up the possibility of

1) have a bottom type
2) have use site derived notions (the ones we users will learn) that are internally linkable to 1), but outside of what we care about

which bring us back to something like the following scenario:

1) create a protocol SwiftBottomType { } [ the core team might defend the idea that it should really be BuiltinBottomType, but the argument also goes that BuiltinXxxxLiteral can be converted to SwiftXxxxLiteral ]. This is something only the compiler cares about, but a building block for what we need. it would be simple to enforce in the compiler that SwiftXXXXX protocols cannot be the target of any user defined conformances if need be.
In fact, these SwiftXxxxxx protocols could be considered so critical for the existence of the language/compiler (i.e. ‘below' the stdlib) that might might not even be represented in the sodlib, but directly manufactured into the TEXT.__swift3_builtin (don’t quote me on this one versus the meaning of the __swift2_proto??? can't recall its name at the moment) section of the libswiftRuntime.a (runtime lib already deals with all the metadata loading, low level existential, and internal reflection)

then :
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinBooleanLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinExtendedGraphemeClusterLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinFloatLiteralConvertible)
...

can become (or stay as it is but, the point is that they are unified, and have become a pattern for future extensibility)

BUILTIN_CORE_PROTOCOL_(SwiftBooleanLiteralConvertible) // btw, they can all retain the BuiltinXxxxxxxx pattern
BUILTIN_CORE_PROTOCOL_(SwiftExtendedGraphemeClusterLiteralConvertible)
BUILTIN_CORE_PROTOCOL_(SwiftFloatLiteralConvertible)
BUILTIN_CORE_PROTOCOL_(SwiftBottomType) // one of the the new guys

2) then create a enum NoReturn: SwiftBottomType {} that we learn about (and name it Never, or …. to match the returning situation. And as time goes, there may be other synonymous that will be built with the best possible user facing name for these circumstances.

When looking at this question and a couple of other related ones, a pattern should form, whose rational is self evident (I am listing a couple others in a separate doc just because IMHO it is a somewhat elegant binding for the low level)

···

On Jun 8, 2016, at 6:57 AM, Thorsten Seitz <tseitz42@icloud.com> wrote:

Am 07.06.2016 um 22:43 schrieb Michael Peternell via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

Am 07.06.2016 um 22:14 schrieb L Mihalkovic via swift-evolution <swift-evolution@swift.org>:

On Jun 7, 2016, at 9:49 PM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

Am 07.06.2016 um 19:45 schrieb Charles Srstka via swift-evolution <swift-evolution@swift.org>:

On Jun 7, 2016, at 11:47 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

I strongly disagree. Type systems are not some esoteric academic thing only working for Haskell or functional languages. Just have a look at the type systems of other languages like Ceylon, Rust or TypeScript.

I hope that Swift will someday have variance annotations for generic parameters and associated types so that we may express sound subtyping rules between generic types. A real bottom type will fit in there just nicely.

+1 for a real bottom type
+1 for calling it Never

+1 on all accounts (it is not the first time I find myself in agreement with many of the choices you support, and more interestingly, with the rational you use to support them: usually a mix between references to other examples and pragmatism).

here is another twist on Never… see further down...

-Thorsten

I disagree. We are discussing how to annotate a function in some way so that the compiler knows that the code following it will never be executed *and* so a human who reads the declaration knows that it does not return. “Never" is a poor choice for that. Never what? Never return? Never use this function? Never say never again?

"Never return". That's why it's in the return type slot, right after the `->`. If you read it out loud, you'll read "returns Never", which is exactly correct.

NoReturn, on the other hand, does *not* read well in that slot: "returns NoReturn". Huh? I mean, I suppose you won't misunderstand it, but it makes no sense whatsoever *as a type name*.

But it’s *not* a type. You’ll never have an instance of it. Since it’s not a type name, it doesn’t make sense that it needs to look like one. What it is doing is telling you something about the behavior of the function itself, not its return value. Its return value, if there were one, is irrelevant, since the function, by its very nature, will never even get to the point where it would return it. Either it’s going to kill the app via a fatalError or something, or we have something like dispatch_main() which will keep executing until the program stops, and one way or another, it won’t return.

For that reason, frankly, I don’t understand why we want to change this from being an attribute, which seems to me the more natural and logical choice to describe this behavior. If we *do* have to change it, though, NoReturn conveys the most clearly to the reader what it does.

+1 for @noreturn
We don't have to change it.
We have to keep it.

this is so unfortunate… IMHO the proposal is the right move because it goes into the direction of unifying things in the language. the problem is that it is difficult to see it without looking at the language as a whole. then we realize that this can be connected to the change of dynamicType to a function or to the fact that .Type and .Self might also warrant a revisiting.

from a practical point of view, a @noreturn function is just so much different than any other function. this shouldn't be "unified". we can discuss if bottom types and normal types can be unified from a theoretical/academical point of view. but in the real world, a @noreturn function does not return at all, whereas most other function does return execution to its caller. To honor this view, a function that returns `Void` is meant to return, it just doesn't return any particular value. But `Void` should be the type with no values, not the type with exactly one value, so a function that returns `Void` shouldn't be able to return, because there can be no `Void` value. `Void` is an unconstructable type, and yet it is different from `@noreturn`. That would be a unification ;) . The whole concept of return-values is so much different in imperative programming than it is in Haskell and with "denotational semantics". Therefore we have 1) functions that return a value, e.g. `Int`, 2) functions that return no value (`Void`), and 3) functions that doesn't return at all (`@noreturn`) => I would like to keep it that way.

Consider for a moment that the bottom type is a technical aspect of the runtime., the thing that the compiler needs so avoid some internal magic while steering towards expressing more things that can be expressed with protocols, using protocols. So that would give the compiler what it needs to have more internal symmetry. But then nothing says that our needs are the same as the compiler’s, particularly when it comes to expressivity. So that leaves us with the possibility of having a bottom type, and having something based on it that can present a more user friendly interface. And while we are at it, nothing says that the user facing side has to be universal, fitting all possible use cases. So then that opens up the possibility of

1) have a bottom type
2) have use site derived notions (the ones we users will learn) that are internally linkable to 1), but outside of what we care about

which bring us back to something like the following scenario:

1) create a protocol SwiftBottomType { } [ the core team might defend the idea that it should really be BuiltinBottomType, but the argument also goes that BuiltinXxxxLiteral can be converted to SwiftXxxxLiteral ]. This is something only the compiler cares about, but a building block for what we need. it would be simple to enforce in the compiler that SwiftXXXXX protocols cannot be the target of any user defined conformances if need be.
In fact, these SwiftXxxxxx protocols could be considered so critical for the existence of the language/compiler (i.e. ‘below' the stdlib) that might might not even be represented in the sodlib, but directly manufactured into the TEXT.__swift3_builtin (don’t quote me on this one versus the meaning of the __swift2_proto??? can't recall its name at the moment) section of the libswiftRuntime.a (runtime lib already deals with all the metadata loading, low level existential, and internal reflection)

then :
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinBooleanLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinExtendedGraphemeClusterLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinFloatLiteralConvertible)
...

can become (or stay as it is but, the point is that they are unified, and have become a pattern for future extensibility)

BUILTIN_CORE_PROTOCOL_(SwiftBooleanLiteralConvertible) // btw, they can all retain the BuiltinXxxxxxxx pattern
BUILTIN_CORE_PROTOCOL_(SwiftExtendedGraphemeClusterLiteralConvertible)
BUILTIN_CORE_PROTOCOL_(SwiftFloatLiteralConvertible)
BUILTIN_CORE_PROTOCOL_(SwiftBottomType) // one of the the new guys

2) then create a enum NoReturn: SwiftBottomType {} that we learn about (and name it Never, or …. to match the returning situation. And as time goes, there may be other synonymous that will be built with the best possible user facing name for these circumstances.

When looking at this question and a couple of other related ones, a pattern should form, whose rational is self evident (I am listing a couple others in a separate doc just because IMHO it is a somewhat elegant binding for the low level)

···

On Jun 8, 2016, at 6:57 AM, Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:

Am 07.06.2016 um 22:43 schrieb Michael Peternell via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

Am 07.06.2016 um 22:14 schrieb L Mihalkovic via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

On Jun 7, 2016, at 9:49 PM, Michael Peternell via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Am 07.06.2016 um 19:45 schrieb Charles Srstka via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

On Jun 7, 2016, at 11:47 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

btw, I know that BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_ have to be treated differently, but I think it is still possible to use the pattern they form to express other critically essential language notions via Protocols as opposed to contextual keywords (eg .Type .Self ) or some other types of secret hand-shakes.

For example at the moment they all are statically declared in the compiler, which also means that adding a new one requires recompiling the compiler, or that users cannot follow in the footsteps with their own literal convertibles (ours have to remain on the other side of a possible very smart thing the compiler would learn to do in the future). Which means that nothing says the following cannot be done

Replace :

BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinBooleanLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinExtendedGraphemeClusterLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinFloatLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinIntegerLiteralConvertible)
...

with

BUILTIN_CORE_PROTOCOL_(SwiftLiteralConvertible) // a single core protocol to flag for the compiler the entire literal convertible pattern
BUILTIN_CORE_PROTOCOL_(SwiftBottomType) // one of the the new core guys

BUILTIN_SPECIALISED_PROTOCOL_(BuiltinBooleanLiteralConvertible, SwiftLiteralConvertible)
BUILTIN_SPECIALISED_PROTOCOL_(BuiltinExtendedGraphemeClusterLiteralConvertible, SwiftLiteralConvertible)

and then maybe the second type can be opened to us too… or these secondary definitions get out of the c++ code and back into the sodlib .swift code, which means that we can pattern some MyOwnSmartLiteralConvertibleThatISwearWillBehaveLikeYours after this model and have it equally discoverable as the lib's

reading your code is a very humbling experience.. I just think some additional symmetries might simplify things further.

···

On Jun 8, 2016, at 7:49 AM, L Mihalkovic <laurent.mihalkovic@gmail.com> wrote:

On Jun 8, 2016, at 6:57 AM, Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:

I strongly disagree. Type systems are not some esoteric academic thing only working for Haskell or functional languages. Just have a look at the type systems of other languages like Ceylon, Rust or TypeScript.

I hope that Swift will someday have variance annotations for generic parameters and associated types so that we may express sound subtyping rules between generic types. A real bottom type will fit in there just nicely.

+1 for a real bottom type
+1 for calling it Never

+1 on all accounts (it is not the first time I find myself in agreement with many of the choices you support, and more interestingly, with the rational you use to support them: usually a mix between references to other examples and pragmatism).

here is another twist on Never… see further down...

-Thorsten

Am 07.06.2016 um 22:43 schrieb Michael Peternell via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

Am 07.06.2016 um 22:14 schrieb L Mihalkovic via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

On Jun 7, 2016, at 9:49 PM, Michael Peternell via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Am 07.06.2016 um 19:45 schrieb Charles Srstka via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

On Jun 7, 2016, at 11:47 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I disagree. We are discussing how to annotate a function in some way so that the compiler knows that the code following it will never be executed *and* so a human who reads the declaration knows that it does not return. “Never" is a poor choice for that. Never what? Never return? Never use this function? Never say never again?

"Never return". That's why it's in the return type slot, right after the `->`. If you read it out loud, you'll read "returns Never", which is exactly correct.

NoReturn, on the other hand, does *not* read well in that slot: "returns NoReturn". Huh? I mean, I suppose you won't misunderstand it, but it makes no sense whatsoever *as a type name*.

But it’s *not* a type. You’ll never have an instance of it. Since it’s not a type name, it doesn’t make sense that it needs to look like one. What it is doing is telling you something about the behavior of the function itself, not its return value. Its return value, if there were one, is irrelevant, since the function, by its very nature, will never even get to the point where it would return it. Either it’s going to kill the app via a fatalError or something, or we have something like dispatch_main() which will keep executing until the program stops, and one way or another, it won’t return.

For that reason, frankly, I don’t understand why we want to change this from being an attribute, which seems to me the more natural and logical choice to describe this behavior. If we *do* have to change it, though, NoReturn conveys the most clearly to the reader what it does.

+1 for @noreturn
We don't have to change it.
We have to keep it.

this is so unfortunate… IMHO the proposal is the right move because it goes into the direction of unifying things in the language. the problem is that it is difficult to see it without looking at the language as a whole. then we realize that this can be connected to the change of dynamicType to a function or to the fact that .Type and .Self might also warrant a revisiting.

from a practical point of view, a @noreturn function is just so much different than any other function. this shouldn't be "unified". we can discuss if bottom types and normal types can be unified from a theoretical/academical point of view. but in the real world, a @noreturn function does not return at all, whereas most other function does return execution to its caller. To honor this view, a function that returns `Void` is meant to return, it just doesn't return any particular value. But `Void` should be the type with no values, not the type with exactly one value, so a function that returns `Void` shouldn't be able to return, because there can be no `Void` value. `Void` is an unconstructable type, and yet it is different from `@noreturn`. That would be a unification ;) . The whole concept of return-values is so much different in imperative programming than it is in Haskell and with "denotational semantics". Therefore we have 1) functions that return a value, e.g. `Int`, 2) functions that return no value (`Void`), and 3) functions that doesn't return at all (`@noreturn`) => I would like to keep it that way.

Consider for a moment that the bottom type is a technical aspect of the runtime., the thing that the compiler needs so avoid some internal magic while steering towards expressing more things that can be expressed with protocols, using protocols. So that would give the compiler what it needs to have more internal symmetry. But then nothing says that our needs are the same as the compiler’s, particularly when it comes to expressivity. So that leaves us with the possibility of having a bottom type, and having something based on it that can present a more user friendly interface. And while we are at it, nothing says that the user facing side has to be universal, fitting all possible use cases. So then that opens up the possibility of

1) have a bottom type
2) have use site derived notions (the ones we users will learn) that are internally linkable to 1), but outside of what we care about

which bring us back to something like the following scenario:

1) create a protocol SwiftBottomType { } [ the core team might defend the idea that it should really be BuiltinBottomType, but the argument also goes that BuiltinXxxxLiteral can be converted to SwiftXxxxLiteral ]. This is something only the compiler cares about, but a building block for what we need. it would be simple to enforce in the compiler that SwiftXXXXX protocols cannot be the target of any user defined conformances if need be.
In fact, these SwiftXxxxxx protocols could be considered so critical for the existence of the language/compiler (i.e. ‘below' the stdlib) that might might not even be represented in the sodlib, but directly manufactured into the TEXT.__swift3_builtin (don’t quote me on this one versus the meaning of the __swift2_proto??? can't recall its name at the moment) section of the libswiftRuntime.a (runtime lib already deals with all the metadata loading, low level existential, and internal reflection)

then :
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinBooleanLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinExtendedGraphemeClusterLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinFloatLiteralConvertible)
...

can become (or stay as it is but, the point is that they are unified, and have become a pattern for future extensibility)

BUILTIN_CORE_PROTOCOL_(SwiftBooleanLiteralConvertible) // btw, they can all retain the BuiltinXxxxxxxx pattern
BUILTIN_CORE_PROTOCOL_(SwiftExtendedGraphemeClusterLiteralConvertible)
BUILTIN_CORE_PROTOCOL_(SwiftFloatLiteralConvertible)
BUILTIN_CORE_PROTOCOL_(SwiftBottomType) // one of the the new guys

2) then create a enum NoReturn: SwiftBottomType {} that we learn about (and name it Never, or …. to match the returning situation. And as time goes, there may be other synonymous that will be built with the best possible user facing name for these circumstances.

When looking at this question and a couple of other related ones, a pattern should form, whose rational is self evident (I am listing a couple others in a separate doc just because IMHO it is a somewhat elegant binding for the low level)

+1 for the bottom type

···

On 08 Jun 2016, at 07:45, L Mihalkovic via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 8, 2016, at 6:57 AM, Thorsten Seitz <tseitz42@icloud.com> wrote:

I strongly disagree. Type systems are not some esoteric academic thing only working for Haskell or functional languages. Just have a look at the type systems of other languages like Ceylon, Rust or TypeScript.

I hope that Swift will someday have variance annotations for generic parameters and associated types so that we may express sound subtyping rules between generic types. A real bottom type will fit in there just nicely.

+1 for a real bottom type
+1 for calling it Never

+1 on all accounts (it is not the first time I find myself in agreement with many of the choices you support, and more interestingly, with the rational you use to support them: usually a mix between references to other examples and pragmatism).

here is another twist on Never… see further down...

-Thorsten

Am 07.06.2016 um 22:43 schrieb Michael Peternell via swift-evolution <swift-evolution@swift.org>:

Am 07.06.2016 um 22:14 schrieb L Mihalkovic via swift-evolution <swift-evolution@swift.org>:

On Jun 7, 2016, at 9:49 PM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

Am 07.06.2016 um 19:45 schrieb Charles Srstka via swift-evolution <swift-evolution@swift.org>:

On Jun 7, 2016, at 11:47 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

I disagree. We are discussing how to annotate a function in some way so that the compiler knows that the code following it will never be executed *and* so a human who reads the declaration knows that it does not return. “Never" is a poor choice for that. Never what? Never return? Never use this function? Never say never again?

"Never return". That's why it's in the return type slot, right after the `->`. If you read it out loud, you'll read "returns Never", which is exactly correct.

NoReturn, on the other hand, does *not* read well in that slot: "returns NoReturn". Huh? I mean, I suppose you won't misunderstand it, but it makes no sense whatsoever *as a type name*.

But it’s *not* a type. You’ll never have an instance of it. Since it’s not a type name, it doesn’t make sense that it needs to look like one. What it is doing is telling you something about the behavior of the function itself, not its return value. Its return value, if there were one, is irrelevant, since the function, by its very nature, will never even get to the point where it would return it. Either it’s going to kill the app via a fatalError or something, or we have something like dispatch_main() which will keep executing until the program stops, and one way or another, it won’t return.

For that reason, frankly, I don’t understand why we want to change this from being an attribute, which seems to me the more natural and logical choice to describe this behavior. If we *do* have to change it, though, NoReturn conveys the most clearly to the reader what it does.

+1 for @noreturn
We don't have to change it.
We have to keep it.

this is so unfortunate… IMHO the proposal is the right move because it goes into the direction of unifying things in the language. the problem is that it is difficult to see it without looking at the language as a whole. then we realize that this can be connected to the change of dynamicType to a function or to the fact that .Type and .Self might also warrant a revisiting.

from a practical point of view, a @noreturn function is just so much different than any other function. this shouldn't be "unified". we can discuss if bottom types and normal types can be unified from a theoretical/academical point of view. but in the real world, a @noreturn function does not return at all, whereas most other function does return execution to its caller. To honor this view, a function that returns `Void` is meant to return, it just doesn't return any particular value. But `Void` should be the type with no values, not the type with exactly one value, so a function that returns `Void` shouldn't be able to return, because there can be no `Void` value. `Void` is an unconstructable type, and yet it is different from `@noreturn`. That would be a unification ;) . The whole concept of return-values is so much different in imperative programming than it is in Haskell and with "denotational semantics". Therefore we have 1) functions that return a value, e.g. `Int`, 2) functions that return no value (`Void`), and 3) functions that doesn't return at all (`@noreturn`) => I would like to keep it that way.

Consider for a moment that the bottom type is a technical aspect of the runtime., the thing that the compiler needs so avoid some internal magic while steering towards expressing more things that can be expressed with protocols, using protocols. So that would give the compiler what it needs to have more internal symmetry. But then nothing says that our needs are the same as the compiler’s, particularly when it comes to expressivity. So that leaves us with the possibility of having a bottom type, and having something based on it that can present a more user friendly interface. And while we are at it, nothing says that the user facing side has to be universal, fitting all possible use cases. So then that opens up the possibility of

1) have a bottom type
2) have use site derived notions (the ones we users will learn) that are internally linkable to 1), but outside of what we care about

which bring us back to something like the following scenario:

1) create a protocol SwiftBottomType { } [ the core team might defend the idea that it should really be BuiltinBottomType, but the argument also goes that BuiltinXxxxLiteral can be converted to SwiftXxxxLiteral ]. This is something only the compiler cares about, but a building block for what we need. it would be simple to enforce in the compiler that SwiftXXXXX protocols cannot be the target of any user defined conformances if need be.
In fact, these SwiftXxxxxx protocols could be considered so critical for the existence of the language/compiler (i.e. ‘below' the stdlib) that might might not even be represented in the sodlib, but directly manufactured into the TEXT.__swift3_builtin (don’t quote me on this one versus the meaning of the __swift2_proto??? can't recall its name at the moment) section of the libswiftRuntime.a (runtime lib already deals with all the metadata loading, low level existential, and internal reflection)

then :
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinBooleanLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinExtendedGraphemeClusterLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinFloatLiteralConvertible)
...

can become (or stay as it is but, the point is that they are unified, and have become a pattern for future extensibility)

BUILTIN_CORE_PROTOCOL_(SwiftBooleanLiteralConvertible) // btw, they can all retain the BuiltinXxxxxxxx pattern
BUILTIN_CORE_PROTOCOL_(SwiftExtendedGraphemeClusterLiteralConvertible)
BUILTIN_CORE_PROTOCOL_(SwiftFloatLiteralConvertible)
BUILTIN_CORE_PROTOCOL_(SwiftBottomType) // one of the the new guys

2) then create a enum NoReturn: SwiftBottomType {} that we learn about (and name it Never, or …. to match the returning situation. And as time goes, there may be other synonymous that will be built with the best possible user facing name for these circumstances.

When looking at this question and a couple of other related ones, a pattern should form, whose rational is self evident (I am listing a couple others in a separate doc just because IMHO it is a somewhat elegant binding for the low level)

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

I realize that this message might have more relevance in this list. Let me know if that is not the case.

···

Begin forwarded message:

From: L Mihalkovic <laurent.mihalkovic@gmail.com>
Date: June 8, 2016 at 7:49:22 AM GMT+2
To: Thorsten Seitz <tseitz42@icloud.com>
Cc: Michael Peternell <michael.peternell@gmx.at>, swift-evolution <swift-evolution@swift.org>, Dave Abrahams <dabrahams@apple.com>, Douglas Gregor <dgregor@apple.com>, Joe Groff <jgroff@apple.com>
Subject: Re: [swift-evolution] [Draft] Change @noreturn to unconstructible return type

On Jun 8, 2016, at 6:57 AM, Thorsten Seitz <tseitz42@icloud.com> wrote:

I strongly disagree. Type systems are not some esoteric academic thing only working for Haskell or functional languages. Just have a look at the type systems of other languages like Ceylon, Rust or TypeScript.

I hope that Swift will someday have variance annotations for generic parameters and associated types so that we may express sound subtyping rules between generic types. A real bottom type will fit in there just nicely.

+1 for a real bottom type
+1 for calling it Never

+1 on all accounts (it is not the first time I find myself in agreement with many of the choices you support, and more interestingly, with the rational you use to support them: usually a mix between references to other examples and pragmatism).

here is another twist on Never… see further down...

-Thorsten

Am 07.06.2016 um 22:43 schrieb Michael Peternell via swift-evolution <swift-evolution@swift.org>:

Am 07.06.2016 um 22:14 schrieb L Mihalkovic via swift-evolution <swift-evolution@swift.org>:

On Jun 7, 2016, at 9:49 PM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

Am 07.06.2016 um 19:45 schrieb Charles Srstka via swift-evolution <swift-evolution@swift.org>:

On Jun 7, 2016, at 11:47 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

I disagree. We are discussing how to annotate a function in some way so that the compiler knows that the code following it will never be executed *and* so a human who reads the declaration knows that it does not return. “Never" is a poor choice for that. Never what? Never return? Never use this function? Never say never again?

"Never return". That's why it's in the return type slot, right after the `->`. If you read it out loud, you'll read "returns Never", which is exactly correct.

NoReturn, on the other hand, does *not* read well in that slot: "returns NoReturn". Huh? I mean, I suppose you won't misunderstand it, but it makes no sense whatsoever *as a type name*.

But it’s *not* a type. You’ll never have an instance of it. Since it’s not a type name, it doesn’t make sense that it needs to look like one. What it is doing is telling you something about the behavior of the function itself, not its return value. Its return value, if there were one, is irrelevant, since the function, by its very nature, will never even get to the point where it would return it. Either it’s going to kill the app via a fatalError or something, or we have something like dispatch_main() which will keep executing until the program stops, and one way or another, it won’t return.

For that reason, frankly, I don’t understand why we want to change this from being an attribute, which seems to me the more natural and logical choice to describe this behavior. If we *do* have to change it, though, NoReturn conveys the most clearly to the reader what it does.

+1 for @noreturn
We don't have to change it.
We have to keep it.

this is so unfortunate… IMHO the proposal is the right move because it goes into the direction of unifying things in the language. the problem is that it is difficult to see it without looking at the language as a whole. then we realize that this can be connected to the change of dynamicType to a function or to the fact that .Type and .Self might also warrant a revisiting.

from a practical point of view, a @noreturn function is just so much different than any other function. this shouldn't be "unified". we can discuss if bottom types and normal types can be unified from a theoretical/academical point of view. but in the real world, a @noreturn function does not return at all, whereas most other function does return execution to its caller. To honor this view, a function that returns `Void` is meant to return, it just doesn't return any particular value. But `Void` should be the type with no values, not the type with exactly one value, so a function that returns `Void` shouldn't be able to return, because there can be no `Void` value. `Void` is an unconstructable type, and yet it is different from `@noreturn`. That would be a unification ;) . The whole concept of return-values is so much different in imperative programming than it is in Haskell and with "denotational semantics". Therefore we have 1) functions that return a value, e.g. `Int`, 2) functions that return no value (`Void`), and 3) functions that doesn't return at all (`@noreturn`) => I would like to keep it that way.

Consider for a moment that the bottom type is a technical aspect of the runtime., the thing that the compiler needs so avoid some internal magic while steering towards expressing more things that can be expressed with protocols, using protocols. So that would give the compiler what it needs to have more internal symmetry. But then nothing says that our needs are the same as the compiler’s, particularly when it comes to expressivity. So that leaves us with the possibility of having a bottom type, and having something based on it that can present a more user friendly interface. And while we are at it, nothing says that the user facing side has to be universal, fitting all possible use cases. So then that opens up the possibility of

1) have a bottom type
2) have use site derived notions (the ones we users will learn) that are internally linkable to 1), but outside of what we care about

which bring us back to something like the following scenario:

1) create a protocol SwiftBottomType { } [ the core team might defend the idea that it should really be BuiltinBottomType, but the argument also goes that BuiltinXxxxLiteral can be converted to SwiftXxxxLiteral ]. This is something only the compiler cares about, but a building block for what we need. it would be simple to enforce in the compiler that SwiftXXXXX protocols cannot be the target of any user defined conformances if need be.
In fact, these SwiftXxxxxx protocols could be considered so critical for the existence of the language/compiler (i.e. ‘below' the stdlib) that might might not even be represented in the sodlib, but directly manufactured into the TEXT.__swift3_builtin (don’t quote me on this one versus the meaning of the __swift2_proto??? can't recall its name at the moment) section of the libswiftRuntime.a (runtime lib already deals with all the metadata loading, low level existential, and internal reflection)

then :
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinBooleanLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinExtendedGraphemeClusterLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinFloatLiteralConvertible)
...

can become (or stay as it is but, the point is that they are unified, and have become a pattern for future extensibility)

BUILTIN_CORE_PROTOCOL_(SwiftBooleanLiteralConvertible) // btw, they can all retain the BuiltinXxxxxxxx pattern
BUILTIN_CORE_PROTOCOL_(SwiftExtendedGraphemeClusterLiteralConvertible)
BUILTIN_CORE_PROTOCOL_(SwiftFloatLiteralConvertible)
BUILTIN_CORE_PROTOCOL_(SwiftBottomType) // one of the the new guys

2) then create a enum NoReturn: SwiftBottomType {} that we learn about (and name it Never, or …. to match the returning situation. And as time goes, there may be other synonymous that will be built with the best possible user facing name for these circumstances.

When looking at this question and a couple of other related ones, a pattern should form, whose rational is self evident (I am listing a couple others in a separate doc just because IMHO it is a somewhat elegant binding for the low level)

More thoughts on protocols used more systematically to replace compiler magic.

···

Begin forwarded message:

From: L Mihalkovic <laurent.mihalkovic@gmail.com>
Date: June 8, 2016 at 8:07:02 AM GMT+2
To: Thorsten Seitz <tseitz42@icloud.com>
Cc: Michael Peternell <michael.peternell@gmx.at>, swift-evolution <swift-evolution@swift.org>, Dave Abrahams <dabrahams@apple.com>, Douglas Gregor <dgregor@apple.com>, Joe Groff <jgroff@apple.com>, Chris Lattner <clattner@apple.com>
Subject: Re: [swift-evolution] [Draft] Change @noreturn to unconstructible return type

On Jun 8, 2016, at 7:49 AM, L Mihalkovic <laurent.mihalkovic@gmail.com> wrote:

On Jun 8, 2016, at 6:57 AM, Thorsten Seitz <tseitz42@icloud.com> wrote:

I strongly disagree. Type systems are not some esoteric academic thing only working for Haskell or functional languages. Just have a look at the type systems of other languages like Ceylon, Rust or TypeScript.

I hope that Swift will someday have variance annotations for generic parameters and associated types so that we may express sound subtyping rules between generic types. A real bottom type will fit in there just nicely.

+1 for a real bottom type
+1 for calling it Never

+1 on all accounts (it is not the first time I find myself in agreement with many of the choices you support, and more interestingly, with the rational you use to support them: usually a mix between references to other examples and pragmatism).

here is another twist on Never… see further down...

-Thorsten

Am 07.06.2016 um 22:43 schrieb Michael Peternell via swift-evolution <swift-evolution@swift.org>:

Am 07.06.2016 um 22:14 schrieb L Mihalkovic via swift-evolution <swift-evolution@swift.org>:

On Jun 7, 2016, at 9:49 PM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

Am 07.06.2016 um 19:45 schrieb Charles Srstka via swift-evolution <swift-evolution@swift.org>:

On Jun 7, 2016, at 11:47 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

I disagree. We are discussing how to annotate a function in some way so that the compiler knows that the code following it will never be executed *and* so a human who reads the declaration knows that it does not return. “Never" is a poor choice for that. Never what? Never return? Never use this function? Never say never again?

"Never return". That's why it's in the return type slot, right after the `->`. If you read it out loud, you'll read "returns Never", which is exactly correct.

NoReturn, on the other hand, does *not* read well in that slot: "returns NoReturn". Huh? I mean, I suppose you won't misunderstand it, but it makes no sense whatsoever *as a type name*.

But it’s *not* a type. You’ll never have an instance of it. Since it’s not a type name, it doesn’t make sense that it needs to look like one. What it is doing is telling you something about the behavior of the function itself, not its return value. Its return value, if there were one, is irrelevant, since the function, by its very nature, will never even get to the point where it would return it. Either it’s going to kill the app via a fatalError or something, or we have something like dispatch_main() which will keep executing until the program stops, and one way or another, it won’t return.

For that reason, frankly, I don’t understand why we want to change this from being an attribute, which seems to me the more natural and logical choice to describe this behavior. If we *do* have to change it, though, NoReturn conveys the most clearly to the reader what it does.

+1 for @noreturn
We don't have to change it.
We have to keep it.

this is so unfortunate… IMHO the proposal is the right move because it goes into the direction of unifying things in the language. the problem is that it is difficult to see it without looking at the language as a whole. then we realize that this can be connected to the change of dynamicType to a function or to the fact that .Type and .Self might also warrant a revisiting.

from a practical point of view, a @noreturn function is just so much different than any other function. this shouldn't be "unified". we can discuss if bottom types and normal types can be unified from a theoretical/academical point of view. but in the real world, a @noreturn function does not return at all, whereas most other function does return execution to its caller. To honor this view, a function that returns `Void` is meant to return, it just doesn't return any particular value. But `Void` should be the type with no values, not the type with exactly one value, so a function that returns `Void` shouldn't be able to return, because there can be no `Void` value. `Void` is an unconstructable type, and yet it is different from `@noreturn`. That would be a unification ;) . The whole concept of return-values is so much different in imperative programming than it is in Haskell and with "denotational semantics". Therefore we have 1) functions that return a value, e.g. `Int`, 2) functions that return no value (`Void`), and 3) functions that doesn't return at all (`@noreturn`) => I would like to keep it that way.

Consider for a moment that the bottom type is a technical aspect of the runtime., the thing that the compiler needs so avoid some internal magic while steering towards expressing more things that can be expressed with protocols, using protocols. So that would give the compiler what it needs to have more internal symmetry. But then nothing says that our needs are the same as the compiler’s, particularly when it comes to expressivity. So that leaves us with the possibility of having a bottom type, and having something based on it that can present a more user friendly interface. And while we are at it, nothing says that the user facing side has to be universal, fitting all possible use cases. So then that opens up the possibility of

1) have a bottom type
2) have use site derived notions (the ones we users will learn) that are internally linkable to 1), but outside of what we care about

which bring us back to something like the following scenario:

1) create a protocol SwiftBottomType { } [ the core team might defend the idea that it should really be BuiltinBottomType, but the argument also goes that BuiltinXxxxLiteral can be converted to SwiftXxxxLiteral ]. This is something only the compiler cares about, but a building block for what we need. it would be simple to enforce in the compiler that SwiftXXXXX protocols cannot be the target of any user defined conformances if need be.
In fact, these SwiftXxxxxx protocols could be considered so critical for the existence of the language/compiler (i.e. ‘below' the stdlib) that might might not even be represented in the sodlib, but directly manufactured into the TEXT.__swift3_builtin (don’t quote me on this one versus the meaning of the __swift2_proto??? can't recall its name at the moment) section of the libswiftRuntime.a (runtime lib already deals with all the metadata loading, low level existential, and internal reflection)

then :
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinBooleanLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinExtendedGraphemeClusterLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinFloatLiteralConvertible)
...

can become (or stay as it is but, the point is that they are unified, and have become a pattern for future extensibility)

BUILTIN_CORE_PROTOCOL_(SwiftBooleanLiteralConvertible) // btw, they can all retain the BuiltinXxxxxxxx pattern
BUILTIN_CORE_PROTOCOL_(SwiftExtendedGraphemeClusterLiteralConvertible)
BUILTIN_CORE_PROTOCOL_(SwiftFloatLiteralConvertible)
BUILTIN_CORE_PROTOCOL_(SwiftBottomType) // one of the the new guys

2) then create a enum NoReturn: SwiftBottomType {} that we learn about (and name it Never, or …. to match the returning situation. And as time goes, there may be other synonymous that will be built with the best possible user facing name for these circumstances.

When looking at this question and a couple of other related ones, a pattern should form, whose rational is self evident (I am listing a couple others in a separate doc just because IMHO it is a somewhat elegant binding for the low level)

btw, I know that BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_ have to be treated differently, but I think it is still possible to use the pattern they form to express other critically essential language notions via Protocols as opposed to contextual keywords (eg .Type .Self ) or some other types of secret hand-shakes.

For example at the moment they all are statically declared in the compiler, which also means that adding a new one requires recompiling the compiler, or that users cannot follow in the footsteps with their own literal convertibles (ours have to remain on the other side of a possible very smart thing the compiler would learn to do in the future). Which means that nothing says the following cannot be done

Replace :

BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinBooleanLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinExtendedGraphemeClusterLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinFloatLiteralConvertible)
BUILTIN_LITERAL_CONVERTIBLE_PROTOCOL_(BuiltinIntegerLiteralConvertible)
...

with

BUILTIN_CORE_PROTOCOL_(SwiftLiteralConvertible) // a single core protocol to flag for the compiler the entire literal convertible pattern
BUILTIN_CORE_PROTOCOL_(SwiftBottomType) // one of the the new core guys

BUILTIN_SPECIALISED_PROTOCOL_(BuiltinBooleanLiteralConvertible, SwiftLiteralConvertible)
BUILTIN_SPECIALISED_PROTOCOL_(BuiltinExtendedGraphemeClusterLiteralConvertible, SwiftLiteralConvertible)

and then maybe the second type can be opened to us too… or these secondary definitions get out of the c++ code and back into the sodlib .swift code, which means that we can pattern some MyOwnSmartLiteralConvertibleThatISwearWillBehaveLikeYours after this model and have it equally discoverable as the lib's

reading your code is a very humbling experience.. I just think some additional symmetries might simplify certain things.