Skip to content

ICE: borrowck/check_loans: assertion failed: self.bccx.region_scope_tree.scopes_intersect(...) #64453

Closed
@flippedoffbit

Description

@flippedoffbit

err :

D:\work\rust\web_api_rust>cargo build
   Compiling web_api_rust v0.1.0 (D:\work\rust\web_api_rust)
warning: unused variable: `x`
  --> src\response_builder.rs:13:20
   |
13 | pub fn file_server(x:&str) {
   |                    ^ help: consider prefixing with an underscore: `_x`
   |
   = note: #[warn(unused_variables)] on by default

thread 'rustc' panicked at 'assertion failed: self.bccx.region_scope_tree.scopes_intersect(old_loan.kill_scope,      
                                             new_loan.kill_scope)', src\librustc_borrowck\borrowck\check_loans.rs:493:9
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/blob/master/CONTRIBUTING.md#bug-reports    

note: rustc 1.37.0 (eae3437df 2019-08-13) running on x86_64-pc-windows-msvc

note: compiler flags: -C debuginfo=2 -C incremental --crate-type bin

note: some of the compiler flags provided by cargo are hidden

error: Could not compile `web_api_rust`.

code i was compiling :

main.rs

use std::env;
use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};
use std::fs::File;

mod request_proc;
mod thread_pool;
mod response_builder;
mod misc;
fn main() {
    //Getting thread pool size from environment variable (to be set by user)
    //using 2 threads per route as default in case variable is not set
    //this can be hardcoded or read from a file , hence optional
    let pool_size: usize = match env::var("THREAD_POOL_SIZE_FOR_EACH_ROUTE") {
        // value of 'THREAD_POOL_SIZE_FOR_EACH_ROUTE' is returned as string that needs to
        // be parsed into usize ,in case of errors we are using default values
        Ok(var) => match var.parse() {
            Ok(val) => val,
            Err(_err) => {
                println!("> Parse Error :{}'THREAD_POOL_SIZE_FOR_EACH_ROUTE' can only have unsigned integer Value",_err);
                println!("> using default value for THREAD_POOL_SIZE_FOR_EACH_ROUTE");
                2
            }
        },
        Err(_s) => 2,
    };

    //Getting listening port  from environment variable (to be set by user)
    //using 0.0.0.0:7878 as defaut port in case variable is not set
    //this can be hardcoded or read from a file , hence optional
    let port = match env::var("RUST_SERVER_PORT") {
        Ok(var) => var,
        Err(_s) => {
            println!(
                "> failed at reading :{} 'RUST_SERVER_PORT' using default",
                _s
            );
            "0.0.0.0:7878".to_string()
        }
    };

    //spitting basic chatter to notify user that application is running and reporting settings being used
    // again totally optional but helpful
    println!("> edit 'RUST_SERVER_PORT' environment variable to change server listening port");
    println!(
        "> edit 'THREAD_POOL_SIZE_FOR_EACH_ROUTE' environment variable to change thread pool size"
    );
    println!(
        "> Using {} as thread pool size for each route \n> using {} as port",
        pool_size, port
    );

    // binding a listner on our designated port for listening for Tcp requests
    // binding to a port might fail in case if we are bining to port that needs
    // elivated privelleges to access or port is busy(being used by another application)
    // or port/Ip are unavailable or wrong , its a good idea to report details to user
    let listner = match TcpListener::bind(&port) {
        Ok(val) => val,
        Err(err) => panic!("> Binding failure : {}", err),
    };

    //declaring string pattern for all routes
    let home_route = "/".to_string();
    let route_2 = "/r2".to_string();
    let route_3 = "/r3".to_string();
    //making thread pool for each route
    let home_pool = thread_pool::ThreadPool::new(pool_size);
    let route2pool = thread_pool::ThreadPool::new(pool_size);
    let route3pool = thread_pool::ThreadPool::new(pool_size);
    //buffer to store request
    let mut req_buffer = [0; 512];
    let test_file = fopen("x.html".to_string());
    // listening to incoming requests in an infinite loop
    // listner.incoming() waits until a request comes in
    // and returns a 'std::result::Result<std::net::TcpStream, std::io::Error>' whenever a request drops
    // which should be unwrapped/matched to get 'std::net::TcpStream' which contains our Tcp request
    // and acts a portal to send back the response for incoming Tcp request
    // assume 'std::net::TcpStream' as a special envelope that is used to recieve Tcp request
    // and send Tcp respose
    for stream in listner.incoming() {
        // getting actual Tcp::stream from Result type given by listener
        let mut stream = match stream {
            Ok(val) => val,
            Err(_err) => {
                println!("> Failed at Unwrapping Stream :{}", _err);
                continue;
            }
        };

        // stream does not returns Tcp request directly , instead it writes it into
        // empty byte array we provid
        match stream.read(&mut req_buffer) {
            Ok(_val) => {}
            Err(err) => println!("> Failed at reading Request into buffer :{}", err),
        };

        // parsing request (which is stored in req_buffer) from [u8] to more readable and usable data structure
        let request =
            request_proc::parse_request(&mut String::from_utf8_lossy(&req_buffer).to_string())
                .unwrap();
        // using match as case-switch to send requests to be executed in different thread-pools
        match request {
            // compairing refrance to path inside request to routes and
            // accordingly execute appropriate functions in designated thread pools
            ref path if path.path == home_route => home_pool.execute(|| home(stream, request,&test_file)),
            ref path if path.path == route_2 => route2pool.execute(|| route1(stream)),
            ref path if path.path == route_3 => route3pool.execute(|| route2(stream)),

            // _ handles all the cases that cannot be handled in our defined paths
            // since we dont have what user is asking for so according to internet standard
            // we will return Error 404
            // we will send response by stream.write(b"some response") method in stream
            // response is always written as &[u8] (refrance to byte array)
            // stream.write returns an Result<usize> that should be checked as there is a real
            // possibility of respose writing failure
            // if everything goes well it returns number bytes sent as response (which is useless in most cases)
            _ => err(stream),
        }
    }
}

fn home(mut stream: TcpStream, request: request_proc::Request,fdata:&String) {
    println!("{}", request.to_string());
    match stream.write(format!("HTTP/1.1 200 OK \nContent-Type: text/html \r\n\r\n  {} ",fdata).as_bytes()){
        Err(err) => println!("> write error : {}", err),
        Ok(_val) => {}
    }
}

fn route1(mut stream: TcpStream) {
    match stream
        .write("HTTP/1.1 200 OK \nContent-Type: text/html \r\n\r\n hello from route 1".as_bytes())
    {
        Err(err) => println!("> write error : {}", err),
        Ok(_val) => {}
    }
}

fn route2(mut stream: TcpStream) {
    match stream
        .write("HTTP/1.1 200 OK \nContent-Type: text/html \r\n\r\n hello from route 2".as_bytes())
    {
        Err(err) => println!("> write error : {}", err),
        Ok(_val) => {}
    }
}

fn err(mut stream: TcpStream) {
    let res = "Error 404 , not found".as_bytes().to_vec();
    let reponse = response_builder::response_builder_text(response_builder::Text::Html,&res);
    match stream.write(reponse.as_bytes()) {
        Err(err) => println!("> write error : {}", err),
        Ok(_val) => {}
    }
}
// set env var for speed optimization during release build <RUSTFLAGS="-C target-cpu=native">

#[inline(always)] 
fn fopen(fname :String) -> String{
    //let mut buffer :Vec<u8>= Vec::with_capacity(5000);
    let mut buffer : String = String::new();
    let nname = &fname[1..];
    let k = File::open(nname);
    
    match k {
    Err(_e) => { buffer = format!("{}",_e).to_string()}//"ERROR 404 NOT FOUND".to_string().into_bytes(); },
    Ok(mut fread) => {                   
        match fread.read_to_string(&mut buffer) {
            Err(_err) =>{ buffer = "UNABLE TO READ FILE".to_string() } 
            Ok(_n) => {
                println!("read {} bytes of data ", _n)
            }
        }
    }
}

    buffer
}

rest code lives at https://github.com/acnologia000/rust_web_api_example

Activity

added
I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Sep 14, 2019
Centril

Centril commented on Sep 14, 2019

@Centril
Contributor

@acnologia000 Can you please check the beta & nightly compilers to see if you can reproduce?

Also, if you can reproduce it, can you provide a backtrace (instructions in the ICE) and try to minimize the reproducer (start by adding loop {} instead of method bodies one by one and binary search your way by removing code)?

changed the title [-]internal compiler error[/-] [+]ICE: borrowck/check_loans: assertion failed: `self.bccx.region_scope_tree.scopes_intersect(...)`[/+] on Sep 14, 2019
Centril

Centril commented on Sep 14, 2019

@Centril
Contributor
flippedoffbit

flippedoffbit commented on Sep 15, 2019

@flippedoffbit
Author

@Centril after rebooting my issue seem to be gone , but i believe i should leave issue open for investigation , and beta channel test i could not test that as issue was resolved after my laptop rebooted due to system update , i apologize of being unhelpful ! , i will keep on testing and update you if i encounter any issue

hellow554

hellow554 commented on Sep 16, 2019

@hellow554
Contributor

@acnologia000 maybe it wasn't the reboot, but did you execute cargo clean in between? Then it may be a incremental compilation issue.

flippedoffbit

flippedoffbit commented on Sep 16, 2019

@flippedoffbit
Author

@hellow554 its the first time i am seeing that cargo has clean command

hskang9

hskang9 commented on Sep 17, 2019

@hskang9

I ran cargo clean, and still got the same compiler error. This is the code

code:

use structopt::StructOpt;
use std::env;
use serde_json::json;
use serde::{Serialize,Deserialize};
use std::fs;
#[macro_use] extern crate shell;
use dialoguer::{theme::ColorfulTheme, theme::CustomPromptCharacterTheme, Select, Input};
use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

#[derive(Serialize,Deserialize,Debug)]
struct Project {
    name: String,
    path: String,
    editor: String
}

#[derive(StructOpt)]
struct Cli {
    pattern: Option<String>,

    project: Option<String>
}

static settings_dir: String = format!("{}/.projectman/settings_rust.json", env::home_dir().unwrap().display());
    
fn main() {
    let default = json!({
            "commandToOpen": "code",
            "projects": []
        });
    let settings_data = serde_json::from_str(&fs::read_to_string(settings_dir).unwrap()).unwrap_or(default); 
    
    let args = Cli::from_args();
    match args.pattern {
        None => browse(settings_data),
        Some(ref x) if x == "open" => open_project(settings_data, args.project),
        Some(ref x) if x == "add" || x == "save" => add_project(settings_data),
        Some(ref x) if x == "remove" => remove_project(settings_data),
        Some(ref x) if x == "seteditor" => set_editor(settings_data),
        Some(ref _x) => {println!("Command {} not found", _x); help()}
    }
    
}

fn list_projects(settings_data: serde_json::value::Value) -> Vec<String> {
    let mut selections = vec![];
    for i in 0..settings_data["projects"].as_array().unwrap().len() {
        let selection = settings_data["projects"][i]["name"].as_str().unwrap().to_string();
        selections.push(selection.clone());
    }
    selections
}

fn browse(settings_data: serde_json::value::Value) {
    let selections = list_projects(settings_data.clone());

    let selection = Select::with_theme(&ColorfulTheme::default())
        .with_prompt("? Select project to open")
        .default(0)
        .items(&selections[..])
        .interact()
        .unwrap();
    let result = &selections[selection.clone()];
    println!("Opening {}...", result.clone());
    open_project(settings_data.clone(), Some(result.to_string()));
}

fn open_project(settings_data: serde_json::value::Value, project: Option<String>) {
    match project {
        // if input is none give selections
        None => browse(settings_data),
        // if input is in the list, open it
        Some(ref x) if check_existence(x.clone(), settings_data.clone())=> {
            let command = settings_data["commandToOpen"].as_str().unwrap(); 
            let path = find_project_path(project.clone().unwrap(), settings_data.clone());
            cmd!("{} {}", command, &path).run().unwrap();
        },
        // if the input is not in the list, call support
        Some(ref _x) => {
            println!("Project does not exist. Add it using `pm add [projectPath]` or cd till the project folder and type `pm add`");
        }
    }
}

fn add_project(settings_data: serde_json::value::Value) {
    let mut next_settings = settings_data.clone();
    let theme = CustomPromptCharacterTheme::new('\u{2692}');
    let project_name: String = Input::with_theme(&theme)
        .with_prompt("Project name ")
        .interact()
        .unwrap();
    let path = env::current_dir();
    let new_project:Project = Project{ name: project_name, path: path.unwrap().display().to_string(), editor: settings_data["commandToOpen"].as_str().unwrap().to_string()};
    let p = serde_json::to_value(new_project).unwrap();
    next_settings["projects"].as_array_mut().unwrap().push(p);

    // Save next settings file
    println!("{:?}", next_settings);
    save_settings(next_settings);
    
}

fn save_settings(settings_data: serde_json::value::Value) {
    let f = serde_json::to_string(&settings_data).unwrap();
    let mut file = File::create(&settings_dir).expect("Unable to write"); 
    file.write_all(f.as_bytes()); 
}

fn remove_project(settings_data: serde_json::value::Value) {
    let mut next_settings = settings_data.clone();
    let selections = list_projects(settings_data);

    let selection = Select::with_theme(&ColorfulTheme::default())
        .with_prompt("? Select project to remove")
        .default(0)
        .items(&selections[..])
        .interact()
        .unwrap();
    let result = &selections[selection.clone()];
    
    // Remove the project in json file
    next_settings = next_settings.as_object().unwrap().remove(result).unwrap();
    println!("{:?}", next_settings);
    save_settings(next_settings);
}

fn set_editor(settings_data: serde_json::value::Value) { 

}

fn help() {
    print!("\nUsage: pm <command>

Options:
  -V, --version                output the version number
  -h, --help                   output usage information

Commands:
  open|o [projectName]         Open one of your saved projects
  add|save [projectDirectory]  Save current directory as a project
  remove [projectName]         Remove the project
  seteditor [commandToOpen]    Set text editor to use
  edit                         Edit settings.json\n")

}

fn find_project_path(name: String, settings_data: serde_json::value::Value) -> String {
    for i in 0..settings_data["projects"].as_array().unwrap().len() {
        let project = settings_data["projects"][i]["name"].as_str().unwrap();
        let path = settings_data["projects"][i]["path"].as_str().unwrap();
        if project == name { println!("{:?}", path); return path.to_string(); }
    }
    panic!("setting file is broken");
    return "Should not execute this".to_string();
}


fn check_existence(name: String, setttings_data: serde_json::value::Value) -> bool {
    for i in 0..setttings_data["projects"].as_array().unwrap().len() {
        let project = setttings_data["projects"][i]["name"].as_str().unwrap();
        if project == name { println!("{:?}", true); return true; }
    }
    false
}
hskang9

hskang9 commented on Sep 17, 2019

@hskang9

Both code used file I/O library. In my case, my code worked before I applied writing files. Maybe borrowing check makes an error in writing files in current rust nightly compiler.

My compiler environment is : nightly-x86_64-unknown-linux-gnu - rustc 1.39.0-nightly (96d07e0ac 2019-09-15)

15 remaining items

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-borrow-checkerArea: The borrow checkerC-bugCategory: This is a bug.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️P-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    Participants

    @pnkfelix@Centril@hellow554@jonas-schievink@hskang9

    Issue actions

      ICE: borrowck/check_loans: assertion failed: `self.bccx.region_scope_tree.scopes_intersect(...)` · Issue #64453 · rust-lang/rust