Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
acnologia000 opened this issue Sep 14, 2019 · 11 comments · Fixed by #64914
Assignees
Labels
A-borrow-checker Area: The borrow checker C-bug Category: This is a bug. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ P-medium Medium priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@acnologia000
Copy link

acnologia000 commented Sep 14, 2019

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

@Centril Centril added A-borrow-checker Area: The borrow checker I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ I-nominated T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Sep 14, 2019
@Centril
Copy link
Contributor

Centril commented Sep 14, 2019

@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)?

@Centril Centril changed the title internal compiler error ICE: borrowck/check_loans: assertion failed: self.bccx.region_scope_tree.scopes_intersect(...) Sep 14, 2019
@Centril
Copy link
Contributor

Centril commented Sep 14, 2019

cc @matthewjasper

@jonas-schievink jonas-schievink added the C-bug Category: This is a bug. label Sep 14, 2019
@acnologia000
Copy link
Author

acnologia000 commented Sep 15, 2019

@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
Copy link
Contributor

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

@acnologia000
Copy link
Author

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

@hskang9
Copy link

hskang9 commented Sep 17, 2019

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
Copy link

hskang9 commented Sep 17, 2019

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)

@hellow554
Copy link
Contributor

hellow554 commented Sep 19, 2019

Minimized it:

struct Project;
struct Value;

static settings_dir: String = format!("");

fn from_string(_: String) -> Value {
    Value
}
fn set_editor(_: Value) {}

fn main() {
    let settings_data = from_string(settings_dir);
    let args: i32 = 0;

    match args {
        ref x if x == &0 => set_editor(settings_data),
        ref x if x == &1 => set_editor(settings_data),
        _ => unimplemented!(),
    }
}

@hellow554
Copy link
Contributor

hellow554 commented Sep 19, 2019

It has been introduced somewhere between 37ff5d3...8869ee0 in 85334c5
It has been fixed somewhere between 78ca1bd...0b680cf in b8ec4c4

@pnkfelix pnkfelix added the regression-from-stable-to-stable Performance or correctness regression from one stable version to another. label Sep 19, 2019
@pnkfelix
Copy link
Member

triage: stable-to-stable regression. Fixed in beta. Once release happens (scheduled for next week), it will be fixed.

@pnkfelix
Copy link
Member

(only remaining question I have is whether to add the reduced example as a regression test or not. The example looks different enough from #62107 (comment) that I think a regression test may be warranted.)

@pnkfelix pnkfelix reopened this Sep 19, 2019
@pnkfelix pnkfelix added E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. P-medium Medium priority and removed I-nominated labels Sep 19, 2019
@pnkfelix pnkfelix self-assigned this Sep 19, 2019
@bors bors closed this as completed in fe5fad8 Oct 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-borrow-checker Area: The borrow checker C-bug Category: This is a bug. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ P-medium Medium priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants