Repository: rust
Issue: Internal Compiler Error
Labels: I-ICE,T-compiler,C-bug

<!--
Thank you for finding an Internal Compiler Error! 🧊  If possible, try to provide
a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for
how to create smaller examples.

http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/

-->

### Code

```Rust
use chrono::{Local, Timelike, Utc};
use tokio_postgres::{NoTls, Row};
use tokio::time::Duration;
use tokio_postgres::types::ToSql;

type GenericError = Box<dyn std::error::Error>;


async fn get_temperature(config: &Configuration) -> Result<f32, GenericError>{
    let esp32_host = format!("http://{}/temperature", config.controller_ip_address).to_string();
    let resp = reqwest::get(esp32_host)
        .await?
        .text()
        .await?;
    let value = resp.parse::<f32>().unwrap();
    return Ok(value);
}


async fn manage_ac(on: bool) -> Result<(), GenericError>{
    log_ac_command(if on { "turn_on" } else { "turn_off"}, "").await?;
    return Ok(());
}

async fn postgres_command(sql: &str, params: &[&(dyn ToSql + Sync)] ) -> Result<u64, Box<dyn std::error::Error>> {
    let dev_postgress = "host=localhost user=user password=password dbname=dbname";
    let (client, connection) = tokio_postgres::connect(dev_postgress, NoTls).await?;
    tokio::spawn(async move {
        if let Err(e) = connection.await {
            log_message(format!("connection error: {}", e).as_str());
        }
    });
    let result = client.execute( sql, params).await?;
    log_message(format!("Command Result: {}", result).as_str());
    Ok(result)
}

async fn postgres_query(sql: &str, params: &[&(dyn ToSql + Sync)] ) -> Result<Vec<Row>, Box<dyn std::error::Error>> {
    let dev_postgress = "host=localhost user=user password=password dbname=xxx";
    let (client, connection) = tokio_postgres::connect(dev_postgress, NoTls).await?;
    tokio::spawn(async move {
        if let Err(e) = connection.await {
            log_message(format!("connection error: {}", e).as_str());
        }
    });
    let result = client.query( sql, params).await?;
    log_message(format!("Query [{}] was successful", sql).as_str());
    Ok(result)
}

async fn log_temperature(temperature: f32) -> Result<(), Box<dyn std::error::Error>>{
    let insert = "INSERT INTO temperature(timestamp, value) VALUES($1, $2)";
    let timestamp = Local::now();
    let result = postgres_command(insert, &[&timestamp, &temperature]).await?;
    log_message(format!("Temperature Log Result: {}", result).as_str());
    Ok(())
}

struct Configuration {
    active_hours_utc: (u32, u32),
    controller_ip_address: String,
    loop_interval_seconds: Duration,
    target_temperature: f32,
}

async fn read_config_value_as_string(name: &str) -> Result<String, Box<dyn std::error::Error>>{
    let sql = "SELECT value FROM configuration where name = '$1'";
    let rows = postgres_query(sql, &[&name]).await?;
    Ok(rows[0].get(0))
}

async fn read_config() -> Result<Configuration, Box<dyn std::error::Error>> {

    let target_temp_str = read_config_value_as_string("target_temperature").await?;
    let loop_interval_str  = read_config_value_as_string("loop_interval_seconds").await?;
    let controller_ip  = read_config_value_as_string("controller_ip_address").await?;
    let config = Configuration {
        active_hours_utc : (20, 11),
        target_temperature : target_temp_str.parse().unwrap(),
        loop_interval_seconds: Duration::from_secs(loop_interval_str.parse().unwrap()),
        controller_ip_address: controller_ip.parse().unwrap()
    };
    Ok(config)
}

async fn log_ac_command(command: &str, state: &str) -> Result<(), Box<dyn std::error::Error>>{
    let insert = "INSERT INTO ac_management(timestamp, command, state) VALUES($1, $2, $3)";
    let timestamp = Local::now();
    let result = postgres_command(insert, &[&timestamp, &command, &state]).await?;
    log_message(format!("Temperature Log Result: {}", result).as_str());
    Ok(())
}

fn log_message(message: &str) -> () {
    let timestamp = Local::now();
    println!("{} {:?}", timestamp.format("%Y-%m-%d %H:%M:%S%.3f %:z"), message);
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = read_config().await?;
    let target_temp = config.target_temperature;
    let mut ac_is_on = false;
    let mut last_read = -1.0;
    // exit(0);
    loop {
        let temperature = get_temperature(&config).await;
        match temperature {
            Ok(t) => {
                last_read = t;
                log_message(format!("The temperature is {}", t).as_str());
                let result = log_temperature(t).await;
                match result {
                    Ok(()) => {
                        log_message(format!("Successful write to DB").as_str());
                    }
                    Err(err) => log_message(format!("Error writing to DB: {}", err).as_str())
                }
            }
            Err(err) => {
                log_message(format!("Temperature retrieval error: {}", err).as_str());
            }
        }
        let current_hour = Utc::now().hour();
        let (start_hour, stop_hour) =  config.active_hours_utc;

        let app_is_active = current_hour >= start_hour
            && (start_hour <= stop_hour && current_hour < stop_hour)
            || (start_hour > stop_hour && current_hour < stop_hour);
        if !app_is_active && ac_is_on {
            match manage_ac(false).await {
                Ok(()) => {
                    ac_is_on = false;
                    log_message("AC was turned off because the application is deactivated");
                }
                Err(err) => {
                    log_message(format!("Error occurred when turning AC off: {}", err).as_str());
                }
            }

        }
        if app_is_active {
            if last_read < target_temp && ac_is_on {
                match manage_ac(false).await {
                    Ok(()) => {
                        ac_is_on = false;
                        log_message(format!("AC was turned off because temperature went down to {}", last_read).as_str());
                    }
                    Err(err) => {
                        log_message(format!("Error occurred when turning AC off: {}", err).as_str());
                    }
                }

            } else if last_read > target_temp + 2.0 && !ac_is_on {
                match manage_ac(true).await {
                    Ok(()) => {
                        ac_is_on = true;
                        log_message(format!("AC was turned on because temperature went up to {}", last_read).as_str());
                    }
                    Err(err) => {
                        log_message(format!( "Error occurred when turning AC on: {}", err).as_str());
                    }
                }
            }
        }
        tokio::time::sleep(config.loop_interval_seconds).await;
    }
}

```


### Meta
<!--
If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions.
-->

`rustc --version --verbose`:
```
rustc 1.57.0 (f1edd0429 2021-11-29)
binary: rustc
commit-hash: f1edd0429582dd29cccacaf50fd134b05593bd9c
commit-date: 2021-11-29
host: x86_64-unknown-linux-gnu
release: 1.57.0
LLVM version: 13.0.0

```

### Error output

```
   Compiling stats_collector v0.1.0 (/home/al/work/smart/master/stats_collector)
thread 'rustc' panicked at 'attempted to read from stolen value: rustc_middle::mir::Body', compiler/rustc_mir_transform/src/check_unsafety.rs:445:36
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

error: internal compiler error: unexpected panic

note: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: rustc 1.57.0 (f1edd0429 2021-11-29) running on x86_64-unknown-linux-gnu

note: compiler flags: -C embed-bitcode=no -C debuginfo=2 -C incremental --crate-type bin

note: some of the compiler flags provided by cargo are hidden

query stack during panic:
#0 [unsafety_check_result] unsafety-checking `manage_ac`
#1 [analysis] running analysis passes on this crate
end of query stack
error: could not compile `stats_collector`

```

<!--
Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your
environment. E.g. `RUST_BACKTRACE=1 cargo build`.
-->
<details><summary><strong>Backtrace</strong></summary>
<p>

```
<backtrace>
```

</p>
</details>