Return tuple from a funcion

Below code worked fine with me:

fn get_weights(gdp_sale: Vec<Model>) -> (f64, f64) {
    let mut constant = 1f64;
    let mut slope = 1f64;
    let accepted_diff = 0.01f64;
    loop{
        let (new_constant, new_slope) = step_cost_function_for(&gdp_sale, constant, slope);
        if (constant - new_constant).abs() <= accepted_diff
            && (slope - new_slope).abs() <= accepted_diff
        {
            return (new_constant, new_slope)  // problem happen if the `return` removed 
        }
        else {
            constant = new_constant;
            slope = new_slope;
            println!("new values for constant and slope are {}, {}", new_constant, new_slope);
        }

    }
}

But if I removed the return word, I get the below error:

error[E0308]: mismatched types
  --> src/main.rs:75:13
   |
75 |             (new_constant, new_slope)
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found tuple
   |
   = note: expected type `()`
              found type `(f64, f64)`

error: aborting due to previous error

That is because of some Never type ( ! ) magic. loop will return ! as in, it will never return, so trying to use implicit return (Without using the return keyword) would invalidate this. A ! can be coerced to any type in the compiler's eyes, therefore this is valid:

fn no_return() -> usize {
    loop {} 
}

because ! coerces into usize. On the other hand, return will break out of the loop and therefore return from the closest function scope, get_weights. This error will also appear because the else statement of the if expression returns (), and it takes priority. Note too, that these expressions all have the same value, !:

let x = loop {};
let x = continue;
let x = break;
let x = return;
let x = std::process::exit();
let x = panic!();
2 Likes

Thanks a lot for the comprehensive explanation.