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

Internal compiler error librustc/ty/layout.rs:1627:25 #50371

Closed
eun-ice opened this issue May 1, 2018 · 22 comments
Closed

Internal compiler error librustc/ty/layout.rs:1627:25 #50371

eun-ice opened this issue May 1, 2018 · 22 comments
Assignees
Labels
C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ P-high High priority regression-from-stable-to-beta Performance or correctness regression from stable to beta. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Milestone

Comments

@eun-ice
Copy link

eun-ice commented May 1, 2018

I cannot isolate what exactly makes rustc crash, but I get an internal compiler error on Mac OSX and Linux.

The code compiles fine with an older nightly:

rustc 1.25.0-nightly (5313e8728 2018-02-17)
binary: rustc
commit-hash: 5313e8728f028cb7914f3c9f02804158a5732b52
commit-date: 2018-02-17
host: x86_64-apple-darwin
release: 1.25.0-nightly
LLVM version: 6.0

But it doesn't work with the current nightly:

rustc 1.27.0-nightly (79252ff4e 2018-04-29)
binary: rustc
commit-hash: 79252ff4e25d82f9fe856cb66f127b79cdace163
commit-date: 2018-04-29
host: x86_64-apple-darwin
release: 1.27.0-nightly
LLVM version: 6.0

The error is

INFO 2018-05-01T16:07:59Z: rustc_trans::base: trans_instance(std::ptr::read_volatile::<std::option::Option<std::collections::VecDeque<iobytes::IoBytes>>>)
INFO 2018-05-01T16:07:59Z: rustc_trans::base: trans_instance(std::ptr::read_volatile::<std::option::Option<usize>>)
INFO 2018-05-01T16:07:59Z: rustc_trans::base: trans_instance(std::ptr::read_volatile::<std::option::Option<metalio::mio_shared::MioEventloopMessage>>)
INFO 2018-05-01T16:07:59Z: rustc_trans::base: trans_instance(std::ptr::write_volatile::<std::option::Option<usize>>)
thread 'main' panicked at 'assertion failed: `(left == right)`
 left: `1`,
right: `0`', librustc/ty/layout.rs:1627:25
stack backtrace:
  0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
  1: std::sys_common::backtrace::print
  2: std::panicking::default_hook::{{closure}}
  3: std::panicking::default_hook
  4: rustc::util::common::panic_hook
  5: std::panicking::rust_panic_with_hook
  6: std::panicking::begin_panic_fmt
  7: rustc::ty::layout::<impl rustc_target::abi::TyLayoutMethods<'tcx, C> for &'tcx rustc::ty::TyS<'tcx>>::field
  8: rustc_trans::mir::place::PlaceRef::project_field
  9: rustc_trans::intrinsic::trans_intrinsic_call
 10: rustc_trans::mir::block::<impl rustc_trans::mir::FunctionCx<'a, 'tcx>>::trans_terminator
 11: rustc_trans::mir::trans_mir
 12: rustc_trans::base::trans_instance
 13: rustc_trans::trans_item::MonoItemExt::define
 14: rustc_trans::base::compile_codegen_unit
 15: rustc::ty::maps::<impl rustc::ty::maps::config::QueryConfig<'tcx> for rustc::ty::maps::queries::compile_codegen_unit<'tcx>>::compute
 16: rustc::dep_graph::graph::DepGraph::with_task_impl
 17: rustc::ty::context::tls::with_related_context
 18: rustc::ty::maps::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::force_query_with_job
 19: rustc::ty::maps::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::get_query
 20: rustc::ty::maps::<impl rustc::ty::context::TyCtxt<'a, 'tcx, 'lcx>>::compile_codegen_unit
 21: rustc_trans::base::trans_crate
 22: <rustc_trans::LlvmTransCrate as rustc_trans_utils::trans_crate::TransCrate>::trans_crate
 23: rustc::util::common::time
 24: rustc_driver::driver::phase_4_translate_to_llvm
 25: rustc_driver::driver::compile_input::{{closure}}
 26: rustc::ty::context::tls::enter_context
 27: <std::thread::local::LocalKey<T>>::with
 28: rustc::ty::context::TyCtxt::create_and_enter
 29: rustc_driver::driver::compile_input
 30: rustc_driver::run_compiler_impl
 31: <scoped_tls::ScopedKey<T>>::set
 32: syntax::with_globals
 33: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
 34: __rust_maybe_catch_panic
 35: rustc_driver::run
 36: rustc_driver::main
 37: std::rt::lang_start::{{closure}}
 38: std::panicking::try::do_call
 39: __rust_maybe_catch_panic
 40: std::rt::lang_start_internal
 41: main
query stack during panic:
#0 [compile_codegen_unit] compile_codegen_unit
end of query stack

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.27.0-nightly (79252ff4e 2018-04-29) running on x86_64-apple-darwin

note: compiler flags: -C opt-level=3 --crate-type lib

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


@pietroalbini
Copy link
Member

Thanks for reporting this issue! Can you post here the code that crashes the compiler?

@pietroalbini pietroalbini added I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. C-bug Category: This is a bug. labels May 1, 2018
@eun-ice
Copy link
Author

eun-ice commented May 1, 2018

It is a larger project I cannot share yet, I tried to isolate the relevant code but failed.

Can you tell me how to find out which files/types are causing this issue? That would help me create a reproducer.

@kennytm
Copy link
Member

kennytm commented May 1, 2018

Repro I think:

use std::ptr::write_volatile;

fn main() {
    let mut a = Some(1usize);
    unsafe {
        write_volatile(&mut a, None);
    }
}

@pietroalbini pietroalbini added this to the 1.27 milestone May 1, 2018
@eun-ice
Copy link
Author

eun-ice commented May 1, 2018

@kennytm Thank you, that is a reproducer.

To further narrow down, code does work properly with

rustc 1.27.0-nightly (65d201f7d 2018-04-18)
binary: rustc
commit-hash: 65d201f7d682ad921ac6e67ac07f922aa63a8ce4
commit-date: 2018-04-18
host: x86_64-apple-darwin
release: 1.27.0-nightly
LLVM version: 6.0

@pietroalbini
Copy link
Member

@eun-ice Thanks! I'm running a bisect between the two nightlies you linked, should be ready in a few minutes.

@pietroalbini
Copy link
Member

The bisect run points at #49420 as the cause of the regression. cc @nox @eddyb

@eun-ice
Copy link
Author

eun-ice commented May 2, 2018

It gets even weirder.

The reproducer by @kennytm works fine with nightly-2018-04-18 but fails with current nightly.

The following also fails with nightly-2018-04-18 and current nightly, but works fin with nightly-2018-02-17

So clearly the commit you isolated cannot be the only problem?

use std::ptr::write_volatile;

enum Some {
    A,
    B,
}

trait FooTrait<T> {
    fn get(&mut self) -> Option<T>;
}

struct FooStruct<T> {
    some: Option<T>
}

impl<T> FooTrait<T> for FooStruct<T> {
    fn get(&mut self) -> Option<T> {
        self.some.take()
    }
}

fn main() {
    let foo: Box<FooTrait<Some>> = Box::new(FooStruct { some: Some(Some::A) });
    let mut a = Some(foo);
    unsafe {
        write_volatile(&mut a, None);
    }
}

@nox
Copy link
Contributor

nox commented May 2, 2018

Option<Box<FooTrait<Some>>> is a niche-filled enum, while Option<usize> is a tagged enum. I've made both use ScalarPair in two separate PRs (#49383, #49420).

This is an actual bug, in the implementation of the volatile_store intrinsic.

@nox
Copy link
Contributor

nox commented May 2, 2018

Actually, I would rather say the bug is in the layout itself, should we have a field for the other part of the pair?

@pietroalbini pietroalbini added I-nominated T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 2, 2018
@eun-ice
Copy link
Author

eun-ice commented May 2, 2018

Sorry, I do not have a meaningful answer to this, as I am just a humble Rust user. Maybe @pietroalbini @kennytm can chime in?

On a side note: Is write_volatile/read_volatile even needed or can I just use write/read. I guard access to the memory cell using an atomic with Ordering::Acquire/Ordering::Release anyways?

@pietroalbini
Copy link
Member

@eun-ice I've nominated this to be discussed at the next compiler team meeting (and they're way more experienced than me). Since this is a regression, we'll get this fixed before the 1.27 release ;)

@eddyb
Copy link
Member

eddyb commented May 2, 2018

The implementation of volatile_write is suboptimal, it should look more like OperandValue::store (with the bx.store calls replaced with bx.volatile_store, and the memcpy_ty one made volatile).
That would also fix this issue's bug with scalar pairs being mistaken for pair-like Rust types.

@eun-ice AFAIK volatile is mostly for communicating with hardware, not synchronization.

@eun-ice
Copy link
Author

eun-ice commented May 2, 2018

@eddyb thanks for your response.

So if I guard pure memory access (no memmaps or anything) using an AtomicBool like this

fn write(&self) {
    if self.guard.compare_and_swap(false, true, Ordering::Acquire) == false {
        ptr:write_volatile(...)
        self.guard.store(false, Ordering::Release);
    }
}

fn read(&self) {
    if self.guard.compare_and_swap(false, true, Ordering::Acquire) == false {
        ptr:read_volatile(...)
        self.guard.store(false, Ordering::Release);
    }
}

Is ptr::read/ptr::write sufficient here or do I need ptr::read_volatile/ptr::write_volatile?

From what I heard in theory the write_volatile makes sure the compiler does not reorder this instruction. Especially if the compiler chose to move the read/write after the Release it would be a problem.

But I haven't found any documentation on how Rust does this (besides the hint that Rust does not yet have a defined memory model yet)

@eddyb
Copy link
Member

eddyb commented May 2, 2018

@eun-ice I'm not well-versed in synchronization primitives, I just know volatile loads/stores aren't needed. I'd suggest asking @Amanieu (the author of parking_lot) about such patterns.

@kennytm
Copy link
Member

kennytm commented May 2, 2018

@eun-ice You could use compiler_fence to prevent reordering by the compiler (or fence to also prevent runtime reordering by CPU).

@Amanieu
Copy link
Member

Amanieu commented May 2, 2018

@eun-ice If the guard ensures that only the current thread can read/write the protected value (which seems to be the case) then you do not need volatile accesses.

@eun-ice
Copy link
Author

eun-ice commented May 2, 2018

@Amanieu thank you for your comment. Do you think the compiler fence is needed to prevent Rust from ordering the read/write after the release of the guard?

@Amanieu
Copy link
Member

Amanieu commented May 2, 2018

@eun-ice That's not necessary, the Ordering::Acquire and Ordering::Release already enforce the ordering.

@eun-ice
Copy link
Author

eun-ice commented May 2, 2018

@Amanieu I am so grateful, thank you.

@eun-ice
Copy link
Author

eun-ice commented May 2, 2018

@nikomatsakis nikomatsakis added P-high High priority and removed I-nominated labels May 3, 2018
@nikomatsakis
Copy link
Contributor

triage: P-high

This looks like a severe problem, @eddyb will fix.

@pietroalbini pietroalbini added regression-from-stable-to-beta Performance or correctness regression from stable to beta. and removed regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. labels May 9, 2018
@eddyb
Copy link
Member

eddyb commented May 10, 2018

(@nox expressed interest in working on this)

bors added a commit that referenced this issue May 14, 2018
Fix volatile_store and nontemporal_store

Fixes #50371.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ P-high High priority regression-from-stable-to-beta Performance or correctness regression from stable to beta. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

7 participants