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 when using Box<T, A> with non-zero sized A #78459

Closed
exrook opened this issue Oct 28, 2020 · 7 comments · Fixed by #94043
Closed

ICE when using Box<T, A> with non-zero sized A #78459

exrook opened this issue Oct 28, 2020 · 7 comments · Fixed by #94043
Labels
A-allocators Area: Custom and system allocators A-layout Area: Memory layout of types 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

@exrook
Copy link
Contributor

exrook commented Oct 28, 2020

While working on #77438, I've run into the following ICE. It seems to be caused by the type layout code not expecting Box to have more than 3 fields, in this case the fat pointer containing two fields, plus the AllocRef instance. On further consideration, the issue also appears with Box<T, A> as long as A is non zero sized.

This ICE was likely not encountered during testing of #77187 because in the case of Box<T, Global>, Global is zero sized. In the example below, removing the borrow of Global will cause the compilation to succeed.

@eddyb could you take a look at this? :)

cc @TimDiekmann you may run into this as well on RawVec

Code

Old code

Playground link

#![feature(allocator_api)]

fn main() {
    Box::new_in(&[0, 1], &std::alloc::Global);
}

New, more minimal code

Playground link

#![feature(allocator_api)]

fn main() {
    Box::new_in((), &std::alloc::Global);
}

Meta

rustc --version --verbose:

rustc 1.49.0-nightly (fd542592f 2020-10-26) running on x86_64-unknown-linux-gnu - playground
rustc 1.48.0-beta.3 (4708ac76e 2020-10-15) running on x86_64-unknown-linux-gnu - local dev environment

Error output

assert!(i < this.fields.count());

thread 'rustc' panicked at 'assertion failed: i < this.fields.count()', /rustc/fd542592f08ca0d1f7255600115c2eafdf6b5da7/compiler/rustc_middle/src/ty/layout.rs:2056:17
Backtrace

From playground

thread 'rustc' panicked at 'assertion failed: i < this.fields.count()', /rustc/fd542592f08ca0d1f7255600115c2eafdf6b5da7/compiler/rustc_middle/src/ty/layout.rs:2056:17
stack backtrace:
   0: std::panicking::begin_panic
   1: rustc_middle::ty::layout::<impl rustc_target::abi::TyAndLayoutMethods<C> for &rustc_middle::ty::TyS>::field
   2: <rustc_target::abi::TyAndLayout<&rustc_middle::ty::TyS> as rustc_codegen_llvm::type_of::LayoutLlvmExt>::scalar_pair_element_llvm_type
   3: <rustc_target::abi::TyAndLayout<&rustc_middle::ty::TyS> as rustc_codegen_llvm::type_of::LayoutLlvmExt>::scalar_pair_element_llvm_type
   4: <rustc_target::abi::call::FnAbi<&rustc_middle::ty::TyS> as rustc_codegen_llvm::abi::FnAbiLlvmExt>::llvm_type
   5: rustc_codegen_llvm::mono_item::<impl rustc_codegen_ssa::traits::declare::PreDefineMethods for rustc_codegen_llvm::context::CodegenCx>::predefine_fn
   6: rustc_codegen_llvm::base::compile_codegen_unit::module_codegen
   7: rustc_query_system::dep_graph::graph::DepGraph<K>::with_task
   8: rustc_codegen_llvm::base::compile_codegen_unit
   9: rustc_codegen_ssa::base::codegen_crate
  10: <rustc_codegen_llvm::LlvmCodegenBackend as rustc_codegen_ssa::traits::backend::CodegenBackend>::codegen_crate
  11: rustc_interface::passes::QueryContext::enter
  12: rustc_interface::queries::Queries::ongoing_codegen
  13: rustc_interface::queries::<impl rustc_interface::interface::Compiler>::enter
  14: rustc_span::with_source_map
  15: scoped_tls::ScopedKey<T>::set
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

@exrook exrook 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 Oct 28, 2020
@jonas-schievink jonas-schievink added the A-layout Area: Memory layout of types label Oct 28, 2020
@camelid camelid added the A-allocators Area: Custom and system allocators label Oct 28, 2020
@rust-lang-glacier-bot rust-lang-glacier-bot added the glacier ICE tracked in rust-lang/glacier. label Oct 28, 2020
@exrook exrook changed the title ICE when using Box<&T, A> with fat &T ICE when using Box<T, A> with non-zero sized A Oct 30, 2020
@rmja
Copy link

rmja commented Dec 21, 2020

This ice is still showing up in nightly-2020-12-21. We are using it over in Drone OS in embedded programming to allocate from heaps located on externally mounted sdram.

@beepster4096
Copy link
Contributor

Vec is not affected by this, and can even be used to get a Box.

#![feature(allocator_api)]

fn main(){
    let vec = Vec::new_in(&std::alloc::Global);

    let _: Box<[()], _> = vec.into_boxed_slice();
}

This code did not ICE on playground.

@exrook
Copy link
Contributor Author

exrook commented Feb 8, 2021

@drmeepster Interestingly, trying to print the Box created in that way gives the same ICE as #81270

#![feature(allocator_api)]

fn main(){
    let vec = Vec::new_in(&std::alloc::Global);
    let a: Box<[()], _> = vec.into_boxed_slice();
    println!("{:?}", a);
}

playground

error: internal compiler error: /rustc/23adf9fd843da7a3394c824b056f93151aaa40ad/compiler/rustc_codegen_ssa/src/mir/operand.rs:132:38: Deref of by-Ref operand OperandRef(Ref((%"std::boxed::Box<[()], &std::alloc::Global>"*:%"std::boxed::Box<[()], &std::alloc::Global>"* %0), None, Align { pow2: 3 }) @ TyAndLayout { ty: std::boxed::Box<[()], &std::alloc::Global>, layout: Layout { fields: Arbitrary { offsets: [Size { raw: 0 }, Size { raw: 16 }], memory_index: [0, 1] }, variants: Single { index: 0 }, abi: Aggregate { sized: true }, largest_niche: Some(Niche { offset: Size { raw: 0 }, scalar: Scalar { value: Pointer, valid_range: 1..=18446744073709551615 } }), align: AbiAndPrefAlign { abi: Align { pow2: 3 }, pref: Align { pow2: 3 } }, size: Size { raw: 24 } } })

@tdelabro
Copy link
Contributor

Hello,
I get this error in two flavor:

By ref:

    let my_allocator = unsafe { Locked::new(Heap::new(0xc00000 as *const usize, false)) };
    let a = Box::new_in(42usize, &my_allocator);

Produce the following:

thread 'rustc' panicked at 'assertion failed: i < this.fields.count()', /rustc/04caa632dd10c2bf64b69524c7f9c4c30a436877/compiler/rustc_middle/src/ty/layout.rs:2172:21
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.51.0-nightly (04caa632d 2021-01-30) running on x86_64-apple-darwin

note: compiler flags: -Z unstable-options -C opt-level=3 -C panic=abort -C embed-bitcode=no --crate-type staticlib

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

query stack during panic:
end of query stack

Without ref:

    let my_allocator = unsafe { Locked::new(Heap::new(0xc00000 as *const usize, false)) };
    let a = Box::new_in(42usize, my_allocator);

Cause:

error: internal compiler error: /rustc/04caa632dd10c2bf64b69524c7f9c4c30a436877/compiler/rustc_codegen_ssa/src/mir/operand.rs:133:38: Deref of by-Ref operand OperandRef(Ref((%"alloc::boxed::Box<core::mem::MaybeUninit<usize>, dynamic_memory_management::Locked<dynamic_memory_management::allocator::Heap>>"*:  %6 = alloca %"alloc::boxed::Box<core::mem::MaybeUninit<usize>, dynamic_memory_management::Locked<dynamic_memory_management::allocator::Heap>>", align 4), None, Align { pow2: 2 }) @ TyAndLayout { ty: alloc::boxed::Box<core::mem::MaybeUninit<usize>, dynamic_memory_management::Locked<dynamic_memory_management::allocator::Heap>>, layout: Layout { fields: Arbitrary { offsets: [Size { raw: 0 }, Size { raw: 4 }], memory_index: [0, 1] }, variants: Single { index: 0 }, abi: Aggregate { sized: true }, largest_niche: Some(Niche { offset: Size { raw: 0 }, scalar: Scalar { value: Pointer, valid_range: 1..=4294967295 } }), align: AbiAndPrefAlign { abi: Align { pow2: 2 }, pref: Align { pow2: 3 } }, size: Size { raw: 32 } } })

thread 'rustc' panicked at 'Box<Any>', compiler/rustc_errors/src/lib.rs:958: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.51.0-nightly (04caa632d 2021-01-30) running on x86_64-apple-darwin

note: compiler flags: -Z unstable-options -C opt-level=3 -C panic=abort -C embed-bitcode=no --crate-type staticlib

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

Where Locked<Heap> does implement both Allocator and GlobalAlloc traits.

@hansihe
Copy link

hansihe commented Feb 25, 2021

I'm hitting this issue too, on code that basically equates to this:

struct Bump { ... }
impl Clone for Bump { ... }

struct Thing(Box<u32, Bump>);

Seems like there are plenty of ways to reproduce this in here, but if a minimal test case is needed, I would be happy to try to provide one.


I just made a repro, wasn't really that tricky.

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=ddb8f9240ade89f24fcb345c8ddfb647

@hansihe
Copy link

hansihe commented Feb 25, 2021

As far as I understand it, the issue is as follows:

  • std Box is special cased, it has the #[lang = "owned_box"] attribute
  • This corresponds to AdtDef::is_box(), which returns true if the type as been annotated to be a owned_box
  • Somewhere, some code which uses is_box makes an assumption that such a box data type only contains one field, the inner pointer itself.
  • This causes the allocator struct field to be removed. This breaks when there is a non ZST allocator field that needs to be accessed in generated code.
  • I'm guessing this might be related to the special deref move semantics for boxes? Is the case where the compiler should call Drop for the Allocator for the box in the case where a deref move is performed even handled correctly as is today?

@tdelabro
Copy link
Contributor

tdelabro commented Apr 8, 2021

It seems that @glandium is the one that developed the feature, in #58457.
He had been warned of the incomming issue, #50882 (comment), and opt for a "workaround", #50882 (comment).

@glandium can you give us more information about the problem you faced, the workaround you choose, any hint for why it isn't working, and maybe give us possible path to explore ?

@bors bors closed this as completed in 6dc62f4 Feb 18, 2022
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Jun 15, 2022
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Jun 15, 2022
bors added a commit to rust-lang-ci/rust that referenced this issue Jun 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-allocators Area: Custom and system allocators A-layout Area: Memory layout of types 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

Successfully merging a pull request may close this issue.

8 participants