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

Borrow checking fails in case a closure appears in a const expression #81899

Closed
YohDeadfall opened this issue Feb 8, 2021 · 8 comments · Fixed by #97457
Closed

Borrow checking fails in case a closure appears in a const expression #81899

YohDeadfall opened this issue Feb 8, 2021 · 8 comments · Fixed by #97457
Labels
A-borrow-checker Area: The borrow checker C-bug Category: This is a bug. const-generics-bad-diagnostics An error is correctly emitted, but is confusing, for `min_const_generics`. E-needs-test Call for participation: Writing correctness tests. glacier ICE tracked in rust-lang/glacier. 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

@YohDeadfall
Copy link
Contributor

The following code causes compiler panics due to the first line without which the issue isn't reproducible. Calling the function outside of a constant context emits the right compiler errors.

Code

const CACHE: &[u32] = &const_sort(&[2, 3, 1], |a, b| a < b); // that line is a failure reason
const fn const_sort<F, const N: usize>(v: &[u32; N], mut is_less: F) -> [u32; N]
where
    F: FnMut(&u32, &u32) -> bool,
{
    let mut r = [0; N];
    
    let mut i = 0;
    while i < N {
        r[i] = v[i];
        i += 1;
    }
    
    let mut i = 1;
    while i < N {
        if is_less(&r[i], &r[i - 1]) {
            let tmp = r[i];
            
            r[i] = r[i - 1];
            
            let mut j = i - 1;
            while j > 0 && is_less(&tmp, &r[j - 1]) {
			    r[j] = r[j - 1];
			    j -= 1;
	    	}
	    	
	    	r[j] = tmp;
	    }
	    i += 1;
    }
    
    r
}

Meta

rustc --version --verbose:

<version>

Error output

   Compiling playground v0.0.1 (/playground)
thread 'rustc' panicked at 'called `Option::unwrap()` on a `None` value', compiler/rustc_mir/src/borrow_check/region_infer/mod.rs:2136:35
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.52.0-nightly (9778068cb 2021-02-07) running on x86_64-unknown-linux-gnu

note: compiler flags: -C embed-bitcode=no -C codegen-units=1 -C debuginfo=2 --crate-type lib

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

query stack during panic:
#0 [mir_borrowck] borrow-checking `CACHE`
#1 [analysis] running analysis passes on this crate
end of query stack
error: could not compile `playground`
Backtrace

   0: rust_begin_unwind
             at /rustc/9778068cbc1e06cc3685422323ff38a2f397de26/library/std/src/panicking.rs:493:5
   1: core::panicking::panic_fmt
             at /rustc/9778068cbc1e06cc3685422323ff38a2f397de26/library/core/src/panicking.rs:92:14
   2: core::panicking::panic
             at /rustc/9778068cbc1e06cc3685422323ff38a2f397de26/library/core/src/panicking.rs:50:5
   3: rustc_mir::borrow_check::region_infer::RegionInferenceContext::find_outlives_blame_span
   4: rustc_mir::borrow_check::do_mir_borrowck
   5: rustc_infer::infer::InferCtxtBuilder::enter
   6: rustc_mir::borrow_check::mir_borrowck
   7: core::ops::function::FnOnce::call_once
   8: rustc_middle::ty::query::<impl rustc_query_system::query::config::QueryAccessors<rustc_middle::ty::context::TyCtxt> for rustc_middle::ty::query::queries::mir_borrowck>::compute
   9: rustc_query_system::dep_graph::graph::DepGraph<K>::with_task_impl
  10: rustc_data_structures::stack::ensure_sufficient_stack
  11: rustc_query_system::query::plumbing::force_query_with_job
  12: rustc_query_system::query::plumbing::get_query_impl
  13: rustc_query_system::query::plumbing::ensure_query_impl
  14: rustc_session::utils::<impl rustc_session::session::Session>::time
  15: rustc_interface::passes::analysis
  16: rustc_middle::ty::query::<impl rustc_query_system::query::config::QueryAccessors<rustc_middle::ty::context::TyCtxt> for rustc_middle::ty::query::queries::analysis>::compute
  17: rustc_query_system::dep_graph::graph::DepGraph<K>::with_task_impl
  18: rustc_data_structures::stack::ensure_sufficient_stack
  19: rustc_query_system::query::plumbing::force_query_with_job
  20: rustc_query_system::query::plumbing::get_query_impl
  21: rustc_interface::passes::QueryContext::enter
  22: rustc_interface::queries::<impl rustc_interface::interface::Compiler>::enter
  23: rustc_span::with_source_map
  24: rustc_interface::interface::create_compiler_and_run
  25: rustc_span::with_session_globals

@YohDeadfall YohDeadfall added C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 8, 2021
@jonas-schievink jonas-schievink added A-borrow-checker Area: The borrow checker I-prioritize Issue: Indicates that prioritization has been requested for this issue. A-const-generics Area: const generics (parameters and arguments) labels Feb 8, 2021
@LeSeulArtichaut
Copy link
Contributor

LeSeulArtichaut commented Feb 8, 2021

FWIW, replacing the function body with todo!() still gives an ICE:

const CACHE: &[u32] = &const_sort(&[2, 3, 1], |a, b| a < b); // that line is a failure reason
const fn const_sort<F, const N: usize>(v: &[u32; N], mut is_less: F) -> [u32; N]
where
    F: FnMut(&u32, &u32) -> bool,
{
    todo!()
}

@LeSeulArtichaut LeSeulArtichaut added the regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. label Feb 8, 2021
@memoryruins
Copy link
Contributor

Minimized slightly further, without const generics:

const _CONST: &[u8] = &f(&[], |_| {});

const fn f<F>(_: &[u8], _: F) -> &[u8]
where
    F: FnMut(&u8),
{
    panic!()
}
backtrace
thread 'rustc' panicked at 'called `Option::unwrap()` on a `None` value', compiler/rustc_mir/src/borrow_check/region_infer/mod.rs:2136:35
stack backtrace:
   0: rust_begin_unwind
             at /rustc/9778068cbc1e06cc3685422323ff38a2f397de26/library/std/src/panicking.rs:493:5
   1: core::panicking::panic_fmt
             at /rustc/9778068cbc1e06cc3685422323ff38a2f397de26/library/core/src/panicking.rs:92:14
   2: core::panicking::panic
             at /rustc/9778068cbc1e06cc3685422323ff38a2f397de26/library/core/src/panicking.rs:50:5
   3: rustc_mir::borrow_check::region_infer::RegionInferenceContext::find_outlives_blame_span
   4: rustc_mir::borrow_check::do_mir_borrowck
   5: rustc_infer::infer::InferCtxtBuilder::enter
   6: rustc_mir::borrow_check::mir_borrowck
   7: core::ops::function::FnOnce::call_once
   8: rustc_middle::ty::query::<impl rustc_query_system::query::config::QueryAccessors<rustc_middle::ty::context::TyCtxt> for rustc_middle::ty::query::queries::mir_borrowck>::compute
   9: rustc_query_system::dep_graph::graph::DepGraph<K>::with_task_impl
  10: rustc_data_structures::stack::ensure_sufficient_stack
  11: rustc_query_system::query::plumbing::force_query_with_job
  12: rustc_query_system::query::plumbing::get_query_impl
  13: rustc_query_system::query::plumbing::ensure_query_impl
  14: rustc_session::utils::<impl rustc_session::session::Session>::time
  15: rustc_interface::passes::analysis
  16: rustc_middle::ty::query::<impl rustc_query_system::query::config::QueryAccessors<rustc_middle::ty::context::TyCtxt> for rustc_middle::ty::query::queries::analysis>::compute
  17: rustc_query_system::dep_graph::graph::DepGraph<K>::with_task_impl
  18: rustc_data_structures::stack::ensure_sufficient_stack
  19: rustc_query_system::query::plumbing::force_query_with_job
  20: rustc_query_system::query::plumbing::get_query_impl
  21: rustc_interface::passes::QueryContext::enter
  22: rustc_interface::queries::<impl rustc_interface::interface::Compiler>::enter
  23: rustc_span::with_source_map
  24: rustc_interface::interface::create_compiler_and_run
  25: rustc_span::with_session_globals

The ICE occurs back to 1.41.0. In 1.40.0, it errors with

error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
 --> <source>:3:12
  |
3 | const fn f<F>(_: &[u8], _: F) -> &[u8]
  |            ^
  |
  = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
  = help: add `#![feature(const_fn)]` to the crate attributes to enable

By making small changes such as making the closure no longer take paramters or removing the reference at

- const _CONST: &[u8] = &f(&[], |_| {});
+ const _CONST: &[u8] = f(&[], |_| {});

It errors, instead of an ICE, on stable 1.49.0 and nightly with

error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
 --> src/lib.rs:3:12
  |
3 | const fn f<F>(_: &[u8], _: F) -> &[u8]
  |            ^
  |
  = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
  = help: add `#![feature(const_fn)]` to the crate attributes to enable

error[E0658]: panicking in constant functions is unstable
 --> src/lib.rs:7:5
  |
7 |     panic!()
  |     ^^^^^^^^
  |
  = note: see issue #51999 <https://github.com/rust-lang/rust/issues/51999> for more information
  = help: add `#![feature(const_panic)]` to the crate attributes to enable
  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 2 previous errors

@LeSeulArtichaut LeSeulArtichaut added regression-from-stable-to-stable Performance or correctness regression from one stable version to another. and removed regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. A-const-generics Area: const generics (parameters and arguments) labels Feb 8, 2021
@matthiaskrgr
Copy link
Member

matthiaskrgr commented Feb 8, 2021

searched nightlies: from nightly-2020-08-16 to nightly-2021-02-03
regressed nightly: nightly-2020-12-28
searched commits: from 0b644e4 to 257becb
regressed commit: 1d517af

edit: for this #81899 (comment) code sample

bisected with cargo-bisect-rustc v0.6.0

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc --test-dir=/home/matthias/vcs/github/rust_bisect/foo --start=2020-08-16 --end=2021-02-03

@jyn514
Copy link
Member

jyn514 commented Feb 10, 2021

cc @lcnr

@LeSeulArtichaut
Copy link
Contributor

LeSeulArtichaut commented Feb 10, 2021

Just to clarify, AFAICT, this issue is not due to #79135, the min_const_generics stabilization just allowed code with const generics to run into this. @memoryruins's MCVE ICEs before #79135 and shows that this is a borrowck bug not related to const generics

@apiraino apiraino added P-medium Medium priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Feb 10, 2021
@apiraino
Copy link
Contributor

Assigning P-medium as discussed as part of the Prioritization Working Group procedure and removing I-prioritize.

@estebank estebank added const-generics-bad-diagnostics An error is correctly emitted, but is confusing, for `min_const_generics`. F-min_const_generics labels Feb 11, 2021
fanninpm added a commit to fanninpm/glacier that referenced this issue Feb 11, 2021
@rust-lang-glacier-bot rust-lang-glacier-bot added the glacier ICE tracked in rust-lang/glacier. label Feb 12, 2021
@johnkjellberg
Copy link

I'm not sure if this is identical problem or not. The error message is:

thread 'rustc' panicked at 'called `Option::unwrap()` on a `None` value', compiler/rustc_mir/src/borrow_check/region_infer/mod.rs:2136:35

/.../

query stack during panic:
#0 [mir_borrowck] borrow-checking `COPY`
#1 [analysis] running analysis passes on this crate
end of query stack

and my code is:

#[derive(Clone, Copy)]
pub struct Something;
impl Something {
  pub const fn copy(&self) -> Self {
      *self
  }
}

pub const CLOSURE: &'static dyn Fn(&mut u8) = &(|_| ());
const BASE : Something = Something{};

const COPY : (&'static dyn Fn(&mut u8), &'static Something) = (CLOSURE, &(BASE.copy()) );

I need both parts or the COPY tuple for the error to trigger and I'm unsure why. And also, if I put &(BASE.copy() in its own const the bug is not triggered.

@JohnTitor
Copy link
Member

Triage: No longer ICE with the latest nightly, I guess #87795 fixed it? Marking as E-needs-test.

@JohnTitor JohnTitor added the E-needs-test Call for participation: Writing correctness tests. label Aug 15, 2021
JohnTitor added a commit to JohnTitor/rust that referenced this issue May 27, 2022
bors added a commit to rust-lang-ci/rust that referenced this issue May 27, 2022
…askrgr

Rollup of 6 pull requests

Successful merges:

 - rust-lang#95214 (Remove impossible panic note from `Vec::append`)
 - rust-lang#97411 (Print stderr consistently)
 - rust-lang#97453 (rename `TyKind` to `RegionKind` in comment in rustc_middle)
 - rust-lang#97457 (Add regression test for rust-lang#81899)
 - rust-lang#97458 (Modify `derive(Debug)` to use `Self` in struct literal to avoid redundant error)
 - rust-lang#97462 (Add more eslint rules)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors closed this as completed in 29ac9b1 May 28, 2022
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. const-generics-bad-diagnostics An error is correctly emitted, but is confusing, for `min_const_generics`. E-needs-test Call for participation: Writing correctness tests. glacier ICE tracked in rust-lang/glacier. 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.