Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix "implicitly returns '()' as its body has no tail or 'return' expression?

Tags:

types

rust

New to Rust and programming. I'm trying to code a program to calculate the state sales tax on items entered by the user. With some help, I think I"m near the end, but I have this one error I don't understand:

4 fn read_one() -> String { expected struct 'st::string::String', found () implicitly returns '()' as its body has no tail or 'return' expression

The code is below:

use::std::io;
use::std::collections::HashMap;

fn read_one() -> String {
    let mut words = String::new();
    io::stdin().read_line(&mut words)
        .ok()
        .expect("Failed to read line.");
}

fn main() {

    let mut tax_rates = HashMap::new();
    tax_rates.insert("AL".to_string(), 0.04);
    tax_rates.insert("AK".to_string(), 0.00);
    tax_rates.insert("AZ".to_string(), 0.056);
    tax_rates.insert("AR".to_string(), 0.65);
    tax_rates.insert("CA".to_string(), 0.725);
    tax_rates.insert("CO".to_string(), 0.029);
    tax_rates.insert("CT".to_string(), 0.635);
    tax_rates.insert("DE".to_string(), 0.00);
    tax_rates.insert("DC".to_string(), 0.06);
    tax_rates.insert("FL".to_string(), 0.06);
    tax_rates.insert("GA".to_string(), 0.04);
    tax_rates.insert("HI".to_string(), 0.04);
    tax_rates.insert("ID".to_string(), 0.06);
    tax_rates.insert("IL".to_string(), 0.0625);
    tax_rates.insert("IN".to_string(), 0.07);
    tax_rates.insert("IA".to_string(), 0.06);
    tax_rates.insert("KS".to_string(), 0.065);
    tax_rates.insert("KY".to_string(), 0.06);
    tax_rates.insert("LA".to_string(), 0.0445);
    tax_rates.insert("ME".to_string(), 0.055);
    tax_rates.insert("MD".to_string(), 0.06);
    tax_rates.insert("MA".to_string(), 0.0625);
    tax_rates.insert("MI".to_string(), 0.06);
    tax_rates.insert("MN".to_string(), 0.06875);
    tax_rates.insert("MS".to_string(), 0.07);
    tax_rates.insert("MO".to_string(), 0.0425);
    tax_rates.insert("MT".to_string(), 0.00);
    tax_rates.insert("NE".to_string(), 0.055);
    tax_rates.insert("NV".to_string(), 0.0685);
    tax_rates.insert("NH".to_string(), 0.00);
    tax_rates.insert("NJ".to_string(), 0.06625);
    tax_rates.insert("NM".to_string(), 0.05125);
    tax_rates.insert("NY".to_string(), 0.04);
    tax_rates.insert("NC".to_string(), 0.0475);
    tax_rates.insert("ND".to_string(), 0.05);
    tax_rates.insert("OH".to_string(), 0.0575);
    tax_rates.insert("OK".to_string(), 0.045);
    tax_rates.insert("OR".to_string(), 0.00);
    tax_rates.insert("PA".to_string(), 0.06);
    tax_rates.insert("RI".to_string(), 0.07);
    tax_rates.insert("PR".to_string(), 0.115);
    tax_rates.insert("SC".to_string(), 0.06);
    tax_rates.insert("SD".to_string(), 0.045);
    tax_rates.insert("TN".to_string(), 0.07);
    tax_rates.insert("TX".to_string(), 0.0625);
    tax_rates.insert("UT".to_string(), 0.0485);
    tax_rates.insert("VA".to_string(), 0.043);
    tax_rates.insert("VT".to_string(), 0.06);
    tax_rates.insert("WA".to_string(), 0.065);
    tax_rates.insert("WV".to_string(), 0.06);
    tax_rates.insert("WI".to_string(), 0.05);
    tax_rates.insert("WY".to_string(), 0.04);

    println!("In what state are you making your purchase?");
    let state = read_one();
    let state = state.trim().to_uppercase();

    println!("How many items are you purchasing?");
    let mut purchase_number = read_one();
    let mut purchase_number = purchase_number.trim().parse::<i32>().unwrap();

    match tax_rates.get(&state) {
        Some(rate) => {
            println!("The tax rate for {} is ({}).", state, rate);
        }
        None => {
            println!("None.");
        }
    }

    let mut tax_vec = Vec::new();
    let mut cost_vec = Vec::new();

    for item_number in 0..purchase_number {
        println!("What is the cost of item number {}?", item_number);
        let item_cost = read_one();
        let item_cost = item_cost.trim().parse::<f64>().unwrap();

        match tax_rates.get(&state) {
            Some(rate) => {
                let tax_amount = item_cost * rate;
                let fin_cost = item_cost + tax_amount;
                println!("The tax amount for item {} is: {:.2}", 
                item_number, tax_amount);
                println!("The final cost of item number {} is: {:.2}",
                item_number, fin_cost);

                tax_vec.push(tax_amount);
                cost_vec.push(fin_cost);
            }

            None => {
                println!("None.");
            }
        }   
    }

    println!("{:?}", tax_vec);
    println!("{:?}", cost_vec);
}
like image 927
muffledcry Avatar asked Dec 28 '19 00:12

muffledcry


Video Answer


2 Answers

To return a value from a function you have two options in rust:

  1. Use a return <some value>; expression
  2. End the function with an expression or a value without a semicolon
// returns the value '1' of type 'u8' without using a 'return'
fn return_one() -> u8 {
    1
}

When neither of these options is used i.e. the function block ends with a semicolon like your function does, then the value that is returned is () aka the unit type. This value is also returned from functions that do not declare a return type like this one:

// This function returns the unit type '()', 
// because it ends with a semicolon and has no return expressions.
fn print_to_console(message: &str) {
    println!(message);
}
like image 89
FlyingFoX Avatar answered Oct 17 '22 11:10

FlyingFoX


Add words at the end of the function, to state what the final value should be. In your current version it is declared as returning String, but ends with a call to a function that returns nothing.

like image 20
Daniel Earwicker Avatar answered Oct 17 '22 09:10

Daniel Earwicker