rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
96.8k stars 12.5k forks source link

ICE: The type checker should prevent reading from a never-written local #69487

Closed DutchGhost closed 2 years ago

DutchGhost commented 4 years ago

I tried this code:

#![feature(const_trait_impl)]
#![feature(fn_traits)]
#![feature(unboxed_closures)]

struct Closure;

impl const FnOnce<&usize> for Closure {
    type Output = usize;

    extern "rust-call" fn call_once(self, arg: &usize) -> Self::Output {
        *arg
    }
}

enum Bug<T = [(); Closure.call_once(&0) ]> {
    V(T),
}

I expected to see this happen: Maybe it should've compiled? Maybe it should've just emitted an error explaining I did something wrong?

Instead, this happened: It crashed!

Meta

rustc --version --verbose:

1.43.0-nightly (6fd8798f4 2020-02-25)
Backtrace

``` error: internal compiler error: src/librustc_mir/interpret/eval_context.rs:143: The type checker should prevent reading from a never-written local thread 'rustc' panicked at 'Box', src/librustc_errors/lib.rs:881:9 stack backtrace: 0: backtrace::backtrace::libunwind::trace at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/libunwind.rs:86 1: backtrace::backtrace::trace_unsynchronized at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.44/src/backtrace/mod.rs:66 2: std::sys_common::backtrace::_print_fmt at src/libstd/sys_common/backtrace.rs:78 3: ::fmt at src/libstd/sys_common/backtrace.rs:59 4: core::fmt::write at src/libcore/fmt/mod.rs:1052 5: std::io::Write::write_fmt at src/libstd/io/mod.rs:1428 6: std::sys_common::backtrace::_print at src/libstd/sys_common/backtrace.rs:62 7: std::sys_common::backtrace::print at src/libstd/sys_common/backtrace.rs:49 8: std::panicking::default_hook::{{closure}} at src/libstd/panicking.rs:204 9: std::panicking::default_hook at src/libstd/panicking.rs:224 10: rustc_driver::report_ice 11: std::panicking::rust_panic_with_hook at src/libstd/panicking.rs:474 12: std::panicking::begin_panic 13: rustc_errors::HandlerInner::bug 14: rustc_errors::Handler::bug 15: rustc::util::bug::opt_span_bug_fmt::{{closure}} 16: rustc::ty::context::tls::with_opt::{{closure}} 17: rustc::ty::context::tls::with_opt 18: rustc::util::bug::opt_span_bug_fmt 19: rustc::util::bug::bug_fmt 20: rustc_mir::interpret::operand::>::access_local 21: rustc_mir::interpret::operand::>::eval_place_to_op 22: rustc_mir::interpret::operand::>::eval_operand 23: rustc_mir::interpret::step::>::eval_rvalue_into_place 24: rustc_mir::interpret::step::>::run 25: rustc_mir::const_eval::eval_queries::const_eval_raw_provider 26: rustc::ty::query::__query_compute::const_eval_raw 27: rustc::ty::query::::compute 28: rustc::dep_graph::graph::DepGraph::with_task_impl 29: rustc::ty::query::plumbing::::get_query 30: rustc_mir::const_eval::eval_queries::const_eval_validated_provider 31: rustc::ty::query::__query_compute::const_eval_validated 32: rustc::ty::query::::compute 33: rustc::dep_graph::graph::DepGraph::with_task_impl 34: rustc::ty::query::plumbing::::get_query 35: rustc_mir::const_eval::eval_queries::const_eval_validated_provider 36: rustc::ty::query::__query_compute::const_eval_validated 37: rustc::ty::query::::compute 38: rustc::dep_graph::graph::DepGraph::with_task_impl 39: rustc::ty::query::plumbing::::get_query 40: rustc::mir::interpret::queries::::const_eval_resolve 41: rustc::ty::sty::Const::eval::{{closure}} 42: ::fold_const 43: ::fold_ty 44: rustc::ty::fold::TypeFoldable::fold_with 45: rustc::ty::fold::TypeFoldable::fold_with 46: rustc_infer::traits::project::normalize 47: rustc_infer::infer::InferCtxt::partially_normalize_associated_types_in 48: as core::iter::traits::iterator::Iterator>::next 49: rustc_typeck::check::wfcheck::check_where_clauses 50: rustc::ty::context::GlobalCtxt::enter_local 51: rustc_typeck::check::wfcheck::check_item_well_formed 52: rustc::ty::query::__query_compute::check_item_well_formed 53: rustc::ty::query::::compute 54: rustc::dep_graph::graph::DepGraph::with_task_impl 55: rustc::ty::query::plumbing::::get_query 56: rustc::ty::query::plumbing::::ensure_query 57: __rust_maybe_catch_panic at src/libpanic_unwind/lib.rs:86 58: rustc_data_structures::sync::par_for_each_in 59: __rust_maybe_catch_panic at src/libpanic_unwind/lib.rs:86 60: rustc_hir::hir::Crate::par_visit_all_item_likes 61: rustc_typeck::check_crate 62: rustc_interface::passes::analysis 63: rustc::ty::query::__query_compute::analysis 64: rustc::dep_graph::graph::DepGraph::with_task_impl 65: rustc::ty::query::plumbing::::get_query 66: rustc::ty::context::tls::enter_global 67: rustc_interface::interface::run_compiler_in_existing_thread_pool note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. 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.43.0-nightly (6fd8798f4 2020-02-25) running on x86_64-unknown-linux-gnu note: compiler flags: -C opt-level=3 -C codegen-units=1 --crate-type lib note: some of the compiler flags provided by cargo are hidden query stack during panic: #0 [const_eval_raw] const-evaluating `Bug::{{constant}}#0` #1 [const_eval_validated] const-evaluating + checking `Bug::{{constant}}#0` #2 [const_eval_validated] const-evaluating + checking `Bug::{{constant}}#0` #3 [check_item_well_formed] processing `Bug` #4 [analysis] running analysis passes on this crate end of query stack error: aborting due to previous error ```

oli-obk commented 4 years ago

this is a general issue with const eval. Typeck needs to const eval certain constants, for which we may not have invoked typeck yet. This ordering issue has existed since 1.0 afaik.

oli-obk commented 4 years ago

A simpler repro and one that works on stable is

struct Bug {
    A: [(); {
        let x: usize;
        x
    }],
}

taken from #72115

Alexendoo commented 3 years ago

Original no longer ICEs since #78961

https://github.com/rust-lang/rust/issues/69487#issuecomment-627157837 still ICEs

matthiaskrgr commented 3 years ago

Olis example ICEs since 1.36.

@rustbot modify labels: +regression-from-stable-to-stable

camelid commented 3 years ago

Assigning P-medium and removing I-prioritize as discussed in the prioritization working group.

DemiMarie commented 3 years ago

Looks like rustc emits an error before ICEing. Perhaps we should only ICE if no error has been reported yet?

oli-obk commented 3 years ago

yes and no. There are a gazillion similar ICEs hiding in CTFE. It's not meant to be run on code that fails to type check/borrowck. I believe we need to add a flag to mir::Body that marks it as "poisoned due to errors" so that when MIR borrowck runs (which presumably emitted the above error), we know about those errors when doing CTFE and just return an AlreadyErrored silent failure

Badel2 commented 2 years ago

Run into this while fuzzing, is this the same issue?

Code

fn main() {
    [9; || [9; []]];
}

Error output

error[E0308]: mismatched types
 --> src/main.rs:2:16
  |
2 |     [9; || [9; []]];
  |                ^^ expected `usize`, found array of 0 elements
  |
  = note: expected type `usize`
            found array `[_; 0]`

error: internal compiler error: compiler/rustc_const_eval/src/interpret/eval_context.rs:198:17: The type checker should prevent reading from a never-written local

thread 'rustc' panicked at 'Box<dyn Any>', compiler/rustc_errors/src/lib.rs:1171:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Backtrace

``` Compiling playground v0.0.1 (/playground) error[E0308]: mismatched types --> src/main.rs:2:16 | 2 | [9; || [9; []]]; | ^^ expected `usize`, found array of 0 elements | = note: expected type `usize` found array `[_; 0]` error: internal compiler error: compiler/rustc_const_eval/src/interpret/eval_context.rs:198:17: The type checker should prevent reading from a never-written local thread 'rustc' panicked at 'Box', compiler/rustc_errors/src/lib.rs:1171:9 stack backtrace: 0: std::panicking::begin_panic:: 1: std::panic::panic_any:: 2: ::bug 3: ::bug 4: rustc_middle::ty::context::tls::with_opt::::{closure#0}, ()> 5: rustc_middle::util::bug::opt_span_bug_fmt:: 6: rustc_middle::util::bug::bug_fmt 7: >::run 8: rustc_const_eval::const_eval::eval_queries::eval_to_allocation_raw_provider 9: rustc_query_system::query::plumbing::get_query:: 10: ::eval_to_allocation_raw 11: rustc_const_eval::const_eval::eval_queries::eval_to_const_value_raw_provider 12: rustc_query_system::query::plumbing::try_execute_query::, core::result::Result>> 13: ::eval_to_const_value_raw 14: ::const_eval_global_id 15: ::const_eval_resolve 16: ::const_eval_resolve 17: rustc_trait_selection::traits::const_evaluatable::is_const_evaluatable 18: ::progress_changed_obligations 19: >::process_obligations::> 20: ::select_with_constness_where_possible 21: ::type_inference_fallback 22: ::enter::<&rustc_middle::ty::context::TypeckResults, ::enter::{closure#1}, &rustc_middle::ty::context::TypeckResults>::{closure#0}> 23: rustc_typeck::check::typeck 24: rustc_query_system::query::plumbing::try_execute_query::> 25: ::typeck 26: ::par_body_owners:: 27: rustc_typeck::check::typeck_item_bodies 28: rustc_query_system::query::plumbing::try_execute_query::> 29: rustc_query_system::query::plumbing::get_query:: 30: ::time::<(), rustc_typeck::check_crate::{closure#7}> 31: rustc_typeck::check_crate 32: rustc_interface::passes::analysis 33: rustc_query_system::query::plumbing::try_execute_query::>> 34: rustc_query_system::query::plumbing::get_query:: 35: ::enter::> 36: ::enter::, rustc_errors::ErrorReported>> 37: rustc_span::with_source_map::, rustc_interface::interface::create_compiler_and_run, rustc_driver::run_compiler::{closure#1}>::{closure#1}> 38: >::set::, rustc_driver::run_compiler::{closure#1}>::{closure#0}, core::result::Result<(), rustc_errors::ErrorReported>>::{closure#0}::{closure#0}, core::result::Result<(), rustc_errors::ErrorReported>> note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. 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.59.0-nightly (48a5999fc 2021-12-01) running on x86_64-unknown-linux-gnu note: compiler flags: -C embed-bitcode=no -C codegen-units=1 -C debuginfo=2 --crate-type bin note: some of the compiler flags provided by cargo are hidden query stack during panic: #0 [eval_to_allocation_raw] const-evaluating + checking `main::{constant#0}` #1 [eval_to_const_value_raw] simplifying constant for the type system `main::{constant#0}` #2 [typeck] type-checking `main` #3 [typeck_item_bodies] type-checking all item bodies #4 [analysis] running analysis passes on this crate end of query stack For more information about this error, try `rustc --explain E0308`. error: could not compile `playground` due to previous error ```

oli-obk commented 2 years ago

This may be fixed on master now, can someone check and add a regression test if it is indeed fixed?

Badel2 commented 2 years ago

Just checked on commit 9cdefd763b910ffd1d42233a8c752ab5fd84ca4d:

https://github.com/rust-lang/rust/issues/69487#issuecomment-627157837 is fixed (feel free to add the regression test):

error[E0601]: `main` function not found in crate `fuzz_input`
 --> fuzz_input.rs:1:1
  |
1 | / struct Bug {
2 | |     A: [(); {
3 | |         let x: usize;
4 | |         x
5 | |     }],
6 | | }
  | |_^ consider adding a `main` function to `fuzz_input.rs`

error[E0381]: use of possibly-uninitialized variable: `x`
 --> fuzz_input.rs:4:9
  |
4 |         x
  |         ^ use of possibly-uninitialized `x`

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0381, E0601.
For more information about an error, try `rustc --explain E0381`.

But https://github.com/rust-lang/rust/issues/69487#issuecomment-984897859 is not fixed:

error[E0308]: mismatched types
 --> fuzz_input.rs:3:16
  |
3 |     [9; || [9; []]];
  |                ^^ expected `usize`, found array of 0 elements
  |
  = note: expected type `usize`
            found array `[_; 0]`

error: internal compiler error: rust/compiler/rustc_const_eval/src/interpret/eval_context.rs:202:17: The type checker should prevent reading from a never-written local

thread 'rustc' panicked at 'Box<dyn Any>', rust/compiler/rustc_errors/src/lib.rs:1160:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Also the original example https://github.com/rust-lang/rust/issues/69487#issue-571503341 is now a different ICE (this doesn't happen in stable but it does happen in beta, feel free to open a new issue if needed):

error[E0601]: `main` function not found in crate `fuzz_input`
  --> fuzz_input.rs:1:1
   |
1  | / #![feature(const_trait_impl)]
2  | | #![feature(fn_traits)]
3  | | #![feature(unboxed_closures)]
4  | |
...  |
16 | |     V(T),
17 | | }
   | |_^ consider adding a `main` function to `fuzz_input.rs`

error: internal compiler error: rust/compiler/rustc_middle/src/ty/layout.rs:3020:21: argument to function with "rust-call" ABI is not a tuple

thread 'rustc' panicked at 'Box<dyn Any>', rust/compiler/rustc_errors/src/lib.rs:1160:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Alexendoo commented 2 years ago

https://github.com/rust-lang/rust/issues/69487#issuecomment-984897859 errors rather than an ICEs now (#95125)

error[E0308]: mismatched types
 --> <anon>:2:16
  |
2 |     [9; || [9; []]];
  |                ^^ expected `usize`, found array of 0 elements
  |
  = note: expected type `usize`
            found array `[_; 0]`

error[E0080]: it is undefined behavior to use this value
 --> <anon>:2:9
  |
2 |     [9; || [9; []]];
  |         ^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
  |
  = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
  = note: the raw bytes of the constant (size: 8, align: 8) {
              __ __ __ __ __ __ __ __                         β”‚ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘
          }
DemiMarie commented 2 years ago

#69487 (comment) errors rather than an ICEs now (#95125)

error[E0308]: mismatched types
 --> <anon>:2:16
  |
2 |     [9; || [9; []]];
  |                ^^ expected `usize`, found array of 0 elements
  |
  = note: expected type `usize`
            found array `[_; 0]`

error[E0080]: it is undefined behavior to use this value
 --> <anon>:2:9
  |
2 |     [9; || [9; []]];
  |         ^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
  |
  = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
  = note: the raw bytes of the constant (size: 8, align: 8) {
              __ __ __ __ __ __ __ __                         β”‚ β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘
          }

That error is completely bogus. A better fix would be for const eval to run typechk and borrowchk itself if necessary.

oli-obk commented 2 years ago

We tried that, it's unclear why it didn't work here yet and requires further analysis.