Skip to content

Add section about diverging functions #960

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 18, 2018
Merged

Conversation

msehnout
Copy link
Contributor

Fix #146

@msehnout
Copy link
Contributor Author

Strange, the fail seems to be in this code:

fn main() {
    fn some_fn() -> () {
        return ()
    }

    let a: () = some_fn();
    println!("This functions returns and you can see this line.")
}

but it works for me with rustc 1.21, any ideas?

@steveklabnik
Copy link
Member

That is...... very odd. Let me restart it, maybe it's flaky or something? No idea.

@msehnout msehnout force-pushed the master branch 2 times, most recently from 86b8f3f to 74419e9 Compare November 23, 2017 16:28
@msehnout
Copy link
Contributor Author

For some reason works like this:

fn some_fn() {
    ()
}

fn main() {
    let a: () = some_fn();
    println!("This functions returns and you can see this line.")
}

@projektir
Copy link
Contributor

This is a really cool example and I love seeing this! Given that I don't actually understand diverging functions I gave it a read to try to, well, understand them, so I have a few comments:

The never type and it's relationship to the unit type strike me as fairly advanced topics. [also, ! is not yet a type in stable Rust], and it seems the terms used here are not necessarily very precise (and I'm not sure how necessary it is to get into all these details in an RBE example). I.e., ! is considered "uninhabited" as opposed to "empty", it seems, and also it's not the only "uninhabited" type out there.

Diverging functions never return. Their return type in Rust is denoted by !, which is an empty type.

I feel this is tough to read. You say it never returns, but then it has a return type. I get what this means, but maybe something like this would read better:

Diverging functions never return. They are specified/marked by using ! in place of the return type.

Maybe provide a fn foo() -> ! example along with it.

I had trouble understanding the main example used. I imagine this is the relevant piece of code:

let addition: u32 = match i%2 == 1 {
   true => i,
   false => continue,
};

Is it the false => continue portion? I think it's important to mention that not just functions, but also expressions, can be divergent, especially since the final example you use uses expressions. I think this should be very clearly specified. What does that actually do? What gets added to acc? I think it would be very helpful to lay out all these small details very explicitly because this may be the first time someone's seeing divergent functions.

@msehnout
Copy link
Contributor Author

Thanks for comments. I will look into them soon.

btw this is the source of information I used: https://github.com/rust-lang/rfcs/blob/master/text/1216-bang-type.md

@steveklabnik
Copy link
Member

Any update on this PR?

@msehnout
Copy link
Contributor Author

Sorry, I totally forgot about this PR. I submitted a modified version based on the comment above, is it better now?

Copy link
Member

@steveklabnik steveklabnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! Thanks so much. No worries about forgetting, it happens to all of us.

I have some small formatting things, and then this is good to go!

@@ -0,0 +1 @@
# Syntax
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like this was accidentally included

It is also the return type of functions that loop forever (e.g. `loop {}`) like network servers or functions that terminates the process (e.g. `exit()`).



Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you remove these extra blank lines please?

}
```

Although this might seem like an abstract concept, it is in fact very useful and often handy. The main advantage of this type is that it can be cast to any other one and therefore used at places where an exact type is required, for instance in `match` branches. This allows us to write code like this:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you wrap this to 80 columns please?

```

As opposed to this function, which will never return the control back to the caller.
```rust
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you put whitespace above this line, to separate the paragraph from the code please?

As opposed to all the other types, this one cannot be instantiated, because the set of all possible values this type can have is empty. Note, that it is different from the `()` type, which has exactly one possible value.

For example, this functions returns as usual, although there is no information in the return value.
```rust
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you put whitespace above this line, to separate the paragraph from the code please?

}
```

As opposed to all the other types, this one cannot be instantiated, because the set of all possible values this type can have is empty. Note, that it is different from the `()` type, which has exactly one possible value.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you wrap this to 80 columns please?

@msehnout
Copy link
Contributor Author

All requested changes should be fixed now.

@msehnout
Copy link
Contributor Author

I'm starting to dislike Travis. Previous checks went just fine a the last one failed without changing the code. I tried to remove the #feature[...] line as it is nightly only, but it is still failing, this time because the feature is not stable yet. Was there any change in the CI?


As opposed to this function, which will never return the control back to the caller.

```rust
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can change this to rust,ignore so this block doesn't get doc tested, since it uses an unstable feature (and travis ci uses stable rust right now)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and maybe add that #[feature(...)] line back in so readers know this is an unstable featuree

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I didn't know about the ignore option. :-)

@marioidival
Copy link
Member

@msehnout Thank you!

@marioidival marioidival merged commit d5ec87e into rust-lang:master Mar 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants