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 with aligned enum #92464

Closed
MiSawa opened this issue Dec 31, 2021 · 4 comments
Closed

ICE with aligned enum #92464

MiSawa opened this issue Dec 31, 2021 · 4 comments
Labels
A-codegen Area: Code generation A-const-eval Area: Constant evaluation (MIR interpretation) C-bug Category: This is a bug. glacier ICE tracked in rust-lang/glacier. 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.

Comments

@MiSawa
Copy link
Contributor

MiSawa commented Dec 31, 2021

Code

#[allow(dead_code)]
#[repr(align(8))]
enum Aligned {
    Zero = 0,
    One = 1,
}

fn main() {
    let aligned = Aligned::Zero;
    println!("{}", aligned as u8);
}

Meta

rustc --version --verbose:

rustc 1.59.0-nightly (b60e32c82 2021-12-30)
binary: rustc
commit-hash: b60e32c82864d841e87359333af1e6d1f9cff9ee
commit-date: 2021-12-30
host: x86_64-unknown-linux-gnu
release: 1.59.0-nightly
LLVM version: 13.0.0

Error output

error: internal compiler error: /rustc/b60e32c82864d841e87359333af1e6d1f9cff9ee/compiler/rustc_const_eval/src/interpret/operand.rs:324:13: primitive read failed for type: Aligned
  --> ./ice.rs:10:14
   |
10 |     println!("{}", aligned as u8);
   |              ^^^^

thread 'rustc' panicked at 'Box<dyn Any>', /rustc/b60e32c82864d841e87359333af1e6d1f9cff9ee/compiler/rustc_errors/src/lib.rs:1115:9
note: run with `RUST_BACKTRACE=1` environment variable to display a 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 (b60e32c82 2021-12-30) running on x86_64-unknown-linux-gnu

query stack during panic:
#0 [optimized_mir] optimizing MIR for `main`
#1 [collect_and_partition_mono_items] collect_and_partition_mono_items
end of query stack
error: aborting due to previous error
Backtrace

error: internal compiler error: /rustc/b60e32c82864d841e87359333af1e6d1f9cff9ee/compiler/rustc_const_eval/src/interpret/operand.rs:324:13: primitive read failed for type: Aligned
  --> ./ice.rs:10:14
   |
10 |     println!("{}", aligned as u8);
   |              ^^^^

thread 'rustc' panicked at 'Box<dyn Any>', /rustc/b60e32c82864d841e87359333af1e6d1f9cff9ee/compiler/rustc_errors/src/lib.rs:1115:9
stack backtrace:
   0: std::panicking::begin_panic::<rustc_errors::ExplicitBug>
   1: std::panic::panic_any::<rustc_errors::ExplicitBug>
   2: <rustc_errors::HandlerInner>::span_bug::<rustc_span::span_encoding::Span>
   3: <rustc_errors::Handler>::span_bug::<rustc_span::span_encoding::Span>
   4: rustc_middle::ty::context::tls::with_opt::<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, ()>
   5: rustc_middle::util::bug::opt_span_bug_fmt::<rustc_span::span_encoding::Span>
   6: rustc_middle::util::bug::span_bug_fmt::<rustc_span::span_encoding::Span>
   7: <rustc_const_eval::interpret::eval_context::InterpCx<rustc_mir_transform::const_prop::ConstPropMachine>>::eval_rvalue_into_place
   8: <rustc_mir_transform::const_prop::ConstPropagator as rustc_middle::mir::visit::MutVisitor>::visit_body
   9: <rustc_mir_transform::const_prop::ConstProp as rustc_middle::mir::MirPass>::run_pass
  10: rustc_mir_transform::pass_manager::run_passes
  11: rustc_mir_transform::optimized_mir
  12: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::plumbing::QueryCtxt, rustc_query_system::query::caches::DefaultCache<rustc_span::def_id::DefId, &rustc_middle::mir::Body>>
  13: <rustc_query_impl::Queries as rustc_middle::ty::query::QueryEngine>::optimized_mir
  14: <rustc_middle::ty::context::TyCtxt>::instance_mir
  15: rustc_monomorphize::collector::collect_neighbours
  16: rustc_monomorphize::collector::collect_items_rec
  17: <rustc_session::session::Session>::time::<(), rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}>
  18: rustc_monomorphize::collector::collect_crate_mono_items
  19: rustc_monomorphize::partitioning::collect_and_partition_mono_items
  20: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::plumbing::QueryCtxt, rustc_query_system::query::caches::DefaultCache<(), (&std::collections::hash::set::HashSet<rustc_span::def_id::DefId, core::hash::BuildHasherDefault<rustc_hash::FxHasher>>, &[rustc_middle::mir::mono::CodegenUnit])>>
  21: rustc_query_system::query::plumbing::get_query::<rustc_query_impl::queries::collect_and_partition_mono_items, rustc_query_impl::plumbing::QueryCtxt>
  22: <rustc_query_impl::Queries as rustc_middle::ty::query::QueryEngine>::collect_and_partition_mono_items
  23: <rustc_codegen_llvm::LlvmCodegenBackend as rustc_codegen_ssa::traits::backend::CodegenBackend>::codegen_crate
  24: <rustc_session::session::Session>::time::<alloc::boxed::Box<dyn core::any::Any>, rustc_interface::passes::start_codegen::{closure#0}>
  25: <rustc_interface::queries::Queries>::ongoing_codegen
  26: <rustc_interface::interface::Compiler>::enter::<rustc_driver::run_compiler::{closure#1}::{closure#2}, core::result::Result<core::option::Option<rustc_interface::queries::Linker>, rustc_errors::ErrorReported>>
  27: rustc_span::with_source_map::<core::result::Result<(), rustc_errors::ErrorReported>, rustc_interface::interface::create_compiler_and_run<core::result::Result<(), rustc_errors::ErrorReported>, rustc_driver::run_compiler::{closure#1}>::{closure#1}>
  28: rustc_interface::interface::create_compiler_and_run::<core::result::Result<(), rustc_errors::ErrorReported>, rustc_driver::run_compiler::{closure#1}>
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 (b60e32c82 2021-12-30) running on x86_64-unknown-linux-gnu

query stack during panic:
#0 [optimized_mir] optimizing MIR for `main`
#1 [collect_and_partition_mono_items] collect_and_partition_mono_items
end of query stack
error: aborting due to previous error

@MiSawa MiSawa 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 Dec 31, 2021
@MiSawa
Copy link
Contributor Author

MiSawa commented Dec 31, 2021

FYI, also fails in stable rustc 1.57.0 (f1edd0429 2021-11-29). https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=72d716ba5a7f274d8c518b82236688b8

@bugadani
Copy link
Contributor

bugadani commented Jan 1, 2022

Slightly different example, different error message, probably the same cause:

#[repr(align(2))] // 2, 4, 8 crashes, 1 compiles
enum Aligned {
    Zero = 0,
    One = 1,
}

pub fn main() {
    println!("{}", tou8(Aligned::Zero))
}

fn tou8(al: Aligned) -> u8 {
    al as u8
}
error: internal compiler error: /rustc/b60e32c82864d841e87359333af1e6d1f9cff9ee/compiler/rustc_codegen_ssa/src/mir/operand.rs:118:18: not immediate: OperandRef(Ref((%Aligned*:  %2 = alloca %Aligned, align 2), None, Align { pow2: 1 }) @ TyAndLayout { ty: Aligned, layout: Layout { fields: Arbitrary { offsets: [Size { raw: 0 }], memory_index: [0] }, variants: Multiple { tag: Scalar { value: Int(I8, false), valid_range: 0..=1 }, tag_encoding: Direct, tag_field: 0, variants: [Layout { fields: Arbitrary { offsets: [], memory_index: [] }, variants: Single { index: 0 }, abi: Aggregate { sized: true }, largest_niche: None, align: AbiAndPrefAlign { abi: Align { pow2: 1 }, pref: Align { pow2: 3 } }, size: Size { raw: 2 } }, Layout { fields: Arbitrary { offsets: [], memory_index: [] }, variants: Single { index: 1 }, abi: Aggregate { sized: true }, largest_niche: None, align: AbiAndPrefAlign { abi: Align { pow2: 1 }, pref: Align { pow2: 3 } }, size: Size { raw: 2 } }] }, abi: Aggregate { sized: true }, largest_niche: Some(Niche { offset: Size { raw: 0 }, scalar: Scalar { value: Int(I8, false), valid_range: 0..=1 } }), align: AbiAndPrefAlign { abi: Align { pow2: 1 }, pref: Align { pow2: 3 } }, size: Size { raw: 2 } } })

@RalfJung
Copy link
Member

RalfJung commented Jan 3, 2022

So looks like we have that same problem both in the CTFE engine and in the codegen backend. Fun. At least we are consistent. ;)

@RalfJung RalfJung added A-codegen Area: Code generation A-const-eval Area: Constant evaluation (MIR interpretation) labels Jan 3, 2022
@rust-lang-glacier-bot rust-lang-glacier-bot added the glacier ICE tracked in rust-lang/glacier. label Jan 5, 2022
bors added a commit to rust-lang-ci/rust that referenced this issue Feb 3, 2022
Temporary fix for the layout of aligned enums

Fix for the issue rust-lang#92464

~~I was after this issue for quite some time now, I have a temporary fix for it.
I think the current problem is [here](https://github.com/ouz-a/rust/blob/e75f96763f99d56d03ada939fe05cbeb2254888d/compiler/rustc_middle/src/ty/layout.rs#L1305-L1310) created `tag` value might be wrong, because when I checked `min` and `max` values it's always between 0..1, which results in wrong size comparison in a few lines down below.
I think `min` and `max` values don't take `#[repr(aligned(8))]` into consideration and just act from base values assigned inside the enum. If what I am saying is true, aligned enums were created with the wrong layout for some time.~~

~~As stated in the title this is only a temporary fix and I think this needs further investigation, if someone wants to mentor it I would like to work on that too.~~ 😸

**Edit: Weird some tests fail now going to close this for now...**

**Edit2: I made it work again.**

I think I figured out the main problem of the issue, layout types of aligned enums with custom discriminant types were not handled, which resulted in confusing(such as this issue) behavior down the line, this is a kinda hacky fix for the issue.
@JohnTitor
Copy link
Member

Fixed by #92932, closing.

GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Jul 5, 2022
Fix repr(align) enum handling

`enum`, for better or worse, supports `repr(align)`. That has already caused a bug in rust-lang#92464, which was "fixed" in rust-lang#92932, but it turns out that that fix is wrong and caused rust-lang#96185.

So this reverts rust-lang#92932 (which fixes rust-lang#96185), and attempts another strategy for fixing rust-lang#92464: special-case enums when doing a cast, re-using the code to load the discriminant rather than assuming that the enum has scalar layout. This works fine for the interpreter.

However, rust-lang#92464 contained another testcase that was previously not in the test suite -- and after adding it, it ICEs again. This is not surprising; codegen needs the same patch that I did in the interpreter. Probably this has to happen [around here](https://github.com/rust-lang/rust/blob/d32ce37a171663048a4c4a536803434e40f52bd6/compiler/rustc_codegen_ssa/src/mir/rvalue.rs#L276). Unfortunately I don't know how to do that -- the interpreter can load a discriminant from an operand, but codegen can only do that from a place. `@oli-obk` `@eddyb` `@bjorn3` any idea?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-codegen Area: Code generation A-const-eval Area: Constant evaluation (MIR interpretation) C-bug Category: This is a bug. glacier ICE tracked in rust-lang/glacier. 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.
Projects
None yet
Development

No branches or pull requests

5 participants