What does returning "!" mean in Rust? - rust

Recently I came across a function in Rust that returned ! instead of basic type, like this:
fn my_function() -> ! {
// ...
}
What does it mean? I was unable to find piece of information about this in The Rust Book. What data does this function return with such indicator?

It means the function never returns (usually because it unconditionally panics or otherwise ends the program, or because it contains an infinite loop that prevents a return from ever happening).
The appendix describes it as:
! Always empty bottom type for diverging functions
where "diverging" means "never returns".

To give some additional context:
! is the never type; it's a type that has no possible value, so it can never be created. If a function returns !, this means that it never completes.
Examples:
fn panics() -> ! {
panic!()
}
fn loops_forever() -> ! {
loop { }
}
At the moment, the ! type is unstable, so it can only be used in return position. In the future, when the never type is stabilized, we will be able to write things like Result<T, !> (a result that's never an error).
Note that ! can be coerced to any other type. This means that ! is a subtype of every other type. It is often called the "bottom type" because of this. It means that we are allowed to write, for example:
let x: i32 = if some_condition {
42
} else {
panic!("`!` is coerced to `i32`")
};
Since ! doesn't work on stable Rust (except in return position), there's a workaround to get a similar type:
enum Never {}
This enum has no variants, so it can never be created, so it's equivalent to !.

Related

Why is it that panic!(_) can be returned with or without a ;?

Looking at question number 3 here.
As an example, I've edited as such.
fn main() {
never_return();
// println!("Failed!");
}
fn never_return() -> ! {
// Implement this function, don't modify the fn signatures
panic!("stop")
}
The expectation when returning something from a fn is without a trailing ;. In the above case, the panic!(_) returns a type never and does what I would expect it to. However, the same fn signature, returning !, compiles to the same regardless of whether there is a ; after the panic macro or not. I'm assuming this is the case because of the intrinsics of a panic? But couldn't find a technical explanation to it that I understood.
Why is this the case?
I think you're misunderstanding the ! type.
The panic! macro does not "return a type never", rather it never returns.
By using a fn foo() -> ! signature, you're declaring that this function never actually returns, and invoking another function/macro that never returns satisfies that.
Similarly, the following compiles:
fn never_returns() -> ! {
loop { }
}
since it loops forever, it never returns

Apparent unused variable in match statement

I am implementing a simple library system to keep track of my pdfs.
I have a Subject enum and a Entry struct defined as follows:
pub enum Subject {
Math,
Programming,
CompSci,
Language,
Misc,
None
}
pub struct Entry {
pub subject: Subject
}
I am trying to implement a function that will operate on a vector of Entry's and return a Vec<&Entry> whose entries match a given Subject.
I have a simple Library struct that is a wrapper around a Vec<Entry>:
pub struct Library {
pub entries: Vec<Entry>
}
In order to do so, I need to iterate through entries and filter only the elements whose .subject field correspond to the desired subject. To accomplish this I have created a function that will return a predicate function.
Here is the get_subject function:
impl Library {
pub fn get_subject(&self, subject: Subject) -> Vec<&Entry> {
let pred = subject_pred(subject);
self.entries.iter().filter(pred).collect::<Vec<&Entry>>()
}
}
which calls the function subject_pred to create the correct predicate function:
// Return a PREDICATE that returns true when
// the passed ENTRY matches the desired SUBJECT
fn subject_pred(subject_UNUSED: Subject) -> impl FnMut(&&Entry) -> bool {
|e: &&Entry| if matches!(&e.subject, subject_UNUSED) {
true
} else {
false
}
}
Here's the problem. This syntax compiles just fine but apparently the subject_UNUSED local variable in subject_pred is "unused". I am flabbergasted as my syntax clearly shows intent to match with the passed subject_UNUSED. When I test out this function on a vector of entries, the predicate always returns true (hence why I am receiving the "unused" warning) but I have literally no idea why.
If anyone could explain why the match statement is always matched, that would be greatly appreciated. I tried using a regular match statement but the same warning is popping up, and this is not the behavior that I am trying to code. If I don't include the subject_UNUSED in a traditional match statement, the compiler tells me that I have to cover the Math, Programming, CompSci, Language, Misc and None variants of my enum, which indicates to me that everything up until that point is good.
You cannot match against a variable. What you've done is equivalent to
matches!(&e.subject, some_subject)
That matches any Subject, just like a wildcard (_), except it also captures it in the some_subject variable (can be used in a guard like matches!(&e.subject, subject_UNUSED if subject_UNUSED == ...)). Neither the captured variable nor the parameter (which is shadowed by it) are used.
What you need to do is to #[derive(PartialEq)] then use ==:
if e.subject == subject_UNUSED { ... }
By the way, your code also has other problems: you don't move into the closure and you're taking owned entries but produce borrowed.

What is the use of `!` as return type in Rust? [duplicate]

This question already has answers here:
Why would I use divergent functions?
(3 answers)
Closed 5 years ago.
I have recently seen a code like this:
fn read() -> ! {
unimplemented!()
}
fn read2() {
}
fn main() {
read2();
read();
}
I could not find any information about the ! as return type of fn read() anywhere so I don't have any idea what is this and what for.
The only thing I have found seems useless for me:
Using ! as a return type indicates to the Rust compiler that this function never returns
I don't understand what it does since omitting the type also says that the function returns nothing (the unit type actually).
Unit () is not nothing, it is a type, with one possible value also written ().
Furthermore, when a function returns unit (or "nothing" as you say), it actually returns. The Never type ! specifies that the function never returns, i.e. quits the program.
This is typically the return type of a panic macro:
let s = match i {
1 => "one",
2 => "two",
_ => panic!("Error"),
}
In this example, note that ! can "take the role" of all the types. The compiler does not complain that one branch has type &str and another has type !.
For your information, here is a little history of the Never type.

Returning from inside for loop causes type mismatch

I am attempting to return a function pointer, which is located inside a for loop, from a function located in an impl of a struct.
fn locate_func(&self, string: &str) -> fn() -> bool {
let mut func;
for alt in &self.alts {
return alt.func;
}
}
There will be an if statement inside the for loop in the future, but as I am testing things at the very moment, it looks rather generic, and somewhat illogical.
The above code in my mind, is supposed to return the pointer to alt.func(), which clearly is a pointer, as it tells me so should I remove the return and semicolon of that line.
error[E0308]: mismatched types
--> src\main.rs:42:3
|
42 | for alt in &self.alts
| ^ expected fn pointer, found ()
|
= note: expected type `fn() -> bool`
= note: found type `()`
Above is the error that is caused upon running locate_func(). I am clearly missing something as the aforementioned code is not working properly. Any hints?
Your for-loop is the last expression inside the function. The compiler expects the last expression to evaluate to the return type. But all loops evaluate to () (unit or void), so the compiler has a classic type mismatch there.
The correct question to ask yourself is: what would happen if the return inside of the loop wouldn't be executed (for example, because the loop isn't executed at all, because self.alts is empty)? This would lead to problems, wouldn't it?
So you have to return a valid object after the for-loop to cover that case. But if you are certain that the spot after the loop will never be reached you can use unreachable!(); to tell the compiler what you already know. However, if the program will reach this spot, it will panic! So better make sure, you know for certain how the program behaves.

How to write a fn that processes input and returns an iterator instead of the full result?

Forgive me if this is a dumb question, but I'm new to Rust, and having a hard time writing this toy program to test my understanding.
I want a function that given a string, returns the first word in each line, as an iterator (because the input could be huge, I don't want to buffer the result as an array). Here's the program I wrote which collects the result as an array first:
fn get_first_words(input: ~str) -> ~[&str] {
return input.lines_any().filter_map(|x| x.split_str(" ").nth(0)).collect();
}
fn main() {
let s = ~"Hello World\nFoo Bar";
let words = get_words(s);
for word in words.iter() {
println!("{}", word);
}
}
Result (as expected):
Hello
Foo
How do I modify this to return an Iterator instead? I'm apparently not allowed to make Iterator<&str> the return type. If I try #Iterator<&str>, rustc says
error: The managed box syntax is being replaced by the `std::gc::Gc` and `std::rc::Rc` types. Equivalent functionality to managed trait objects will be implemented but is currently missing.
I can't figure out for the life of me how to make that work.
Similarly, trying to return ~Iterator<&str> makes rustc complain that the actual type is std::iter::FilterMap<....blah...>.
In C# this is really easy, as you simply return the result of the equivalent map call as an IEnumerable<string>. Then the callee doesn't have to know what the actual type is that's returned, it only uses methods available in the IEnumerable interface.
Is there nothing like returning an interface in Rust??
(I'm using Rust 0.10)
I believe that the equivalent of the C# example would be returning ~Iterator<&str>. This can be done, but must be written explicitly: rather than returning x, return ~x as ~Iterator<&'a str>. (By the way, your function is going to have to take &'a str rather than ~str—if you don’t know why, ask and I’ll explain.)
This is not, however, idiomatic Rust because it is needlessly inefficient. The idiomatic Rust is to list the return type explicitly. You can specify it in one place like this if you like:
use std::iter::{FilterMap, Map};
use std::str::CharSplits;
type Foo = FilterMap<'a, &'a str, &'a str,
Map<'a, &'a str, &'a str,
CharSplits<'a, char>>>
And then list Foo as the return type.
Yes, this is cumbersome. At present, there is no such thing as inferring a return type in any way. This has, however, been discussed and I believe it likely that it will come eventually in some syntax similar to fn foo<'a>(&'a str) -> Iterator<&'a str>. For now, though, there is no fancy sugar.

Resources