Skip to content

Array patterns and tuple patterns don't properly check for Sized #150040

Description

@theemathas

The code below shouldn't compile, since it creates a variable y of type &[str; 2]. This type is invalid, since str is not Sized. However, it compiles without errors.

// Compiles without errors
fn main() {
    // y has type &[str; 2]
    let ref y @ [ref x, _];
    x = "";
}

I can also create a variable of type [str; 2] without a reference indirection.

// Compiles without errors
fn main() {
    // y has type [str; 2]
    let [[ref x, _], y];
    x = "";
}

Furthermore, if the array has length 0, I can even initialize the variable, and take its address.

// Compiles without errors
fn main() {
    // y has type [str; 0]
    let [[ref x], [_, y @ ..]];
    x = "";
    y = [];
    let z = &raw const y as *const ();
    println!("{z:p}");
}

Here are some other variants of this weirdness:

Code using tuple patterns instead of array patterns
// Compiles without errors
fn main() {
    // z has type &(str, str)
    let ref z @ (ref x, ref y);
    x = "";
    y = "";
}
Code that prints type information about this invalid type
// Compiles and runs without errors

trait TypeInfo: std::any::Any {
    fn type_name(&self) -> &'static str {
        std::any::type_name::<Self>()
    }
    fn size(&self) -> usize {
        size_of_val(self)
    }
    fn align(&self) -> usize {
        align_of_val(self)
    }
}
impl<T: ?Sized + 'static> TypeInfo for T {}

fn main() {
    // y has type [[i32]; 0]
    let [[ref x], [_, y @ ..]];
    x = &[] as &[i32];
    y = [];
    let z: &dyn TypeInfo = &y;
    assert_eq!("[[i32]; 0]", z.type_name());
    assert_eq!(0, z.size());
    assert_eq!(4, z.align());
    println!("{:?}", z.type_id());
}
Code that stores this invalid type in a const
const A: &dyn Send = {
    // y has type [str; 0]
    let [[ref x], [_, y @ ..]];
    x = "";
    y = [];
    &{y}
};

Meta

Reproducible on the playground with version 1.94.0-nightly (2025-12-14 0208ee09be465f69005a)

Activity

  1. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    C-bugCategory: This is a bug.
    A-patternsRelating to patterns and pattern matching
    T-typesRelevant to the types team, which will review and decide on the PR/issue.
    on Dec 16, 2025
  2. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Dec 16, 2025
  3. lcnr commented on Dec 16, 2025

    @lcnr
    Contributor

    We should probably check wf of non-trivial patterns.

    Or ideally, just check wf of all let statements 🤷 cc @rust-lang/types if one of u wants to look into this

  4. theemathas commented on Jan 31, 2026

    @theemathas
    ContributorAuthor

    This can also cause an ICE.

    #![expect(unused)]
    
    trait Trait {}
    impl<T: ?Sized> Trait for T {}
    
    fn main() {
        // x has type [(str, str); 0]
        let [[(ref a, ref b)], [_, x @ ..]];
        a = "";
        b = "";
        x = [];
        let _: &dyn Trait = &x;
    }
    Error output
    note: no errors encountered even though delayed bugs were created
    
    note: those delayed bugs will now be shown as internal compiler errors
    
    error: internal compiler error: encountered unexpected unsized field in layout of (str, str): TyAndLayout {
                                        ty: str,
                                        layout: Layout {
                                            size: Size(0 bytes),
                                            align: AbiAlign {
                                                abi: Align(1 bytes),
                                            },
                                            backend_repr: Memory {
                                                sized: false,
                                            },
                                            fields: Array {
                                                stride: Size(1 bytes),
                                                count: 0,
                                            },
                                            largest_niche: None,
                                            uninhabited: false,
                                            variants: Single {
                                                index: 0,
                                            },
                                            max_repr_align: None,
                                            unadjusted_abi_align: Align(1 bytes),
                                            randomization_seed: 13921294091492507170,
                                        },
                                    }
      |
      = note: delayed at /rustc-dev/a293cc4af8b26701c42738381c0c6f9d2ba881e0/compiler/rustc_ty_utils/src/layout.rs:104:32
                 0: <rustc_errors::DiagCtxtInner>::emit_diagnostic
                 1: <rustc_errors::DiagCtxtHandle>::emit_diagnostic
                 2: <rustc_span::ErrorGuaranteed as rustc_errors::diagnostic::EmissionGuarantee>::emit_producing_guarantee
                 3: <rustc_errors::DiagCtxtHandle>::delayed_bug::<alloc::string::String>
                 4: rustc_ty_utils::layout::map_error
                 5: rustc_ty_utils::layout::layout_of_uncached::{closure#3}
                 6: rustc_ty_utils::layout::layout_of_uncached
                 7: rustc_ty_utils::layout::layout_of
                 8: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::layout_of::make_query_vtable::{closure#1}::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 16]>>
                 9: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::SemiDynamicQueryDispatcher<rustc_query_system::query::caches::DefaultCache<rustc_middle::ty::PseudoCanonicalInput<rustc_middle::ty::Ty>, rustc_middle::query::erase::ErasedData<[u8; 16]>>, false, true, false>, false>
                10: rustc_query_impl::query_impl::layout_of::get_query_non_incr::__rust_end_short_backtrace
                11: <rustc_middle::ty::layout::LayoutCx as rustc_middle::ty::layout::LayoutOf>::spanned_layout_of
                12: rustc_ty_utils::layout::layout_of_uncached
                13: rustc_ty_utils::layout::layout_of
                14: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::layout_of::make_query_vtable::{closure#1}::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 16]>>
                15: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::SemiDynamicQueryDispatcher<rustc_query_system::query::caches::DefaultCache<rustc_middle::ty::PseudoCanonicalInput<rustc_middle::ty::Ty>, rustc_middle::query::erase::ErasedData<[u8; 16]>>, false, true, false>, false>
                16: rustc_query_impl::query_impl::layout_of::get_query_non_incr::__rust_end_short_backtrace
                17: <rustc_mir_transform::known_panics_lint::KnownPanicsLint as rustc_mir_transform::pass_manager::MirLint>::run_lint
                18: rustc_mir_transform::run_analysis_to_runtime_passes
                19: rustc_mir_transform::mir_drops_elaborated_and_const_checked
                20: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::mir_drops_elaborated_and_const_checked::make_query_vtable::{closure#1}::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 8]>>
                21: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::SemiDynamicQueryDispatcher<rustc_data_structures::vec_cache::VecCache<rustc_span::def_id::LocalDefId, rustc_middle::query::erase::ErasedData<[u8; 8]>, rustc_query_system::dep_graph::graph::DepNodeIndex>, false, false, false>, false>
                22: rustc_query_impl::query_impl::mir_drops_elaborated_and_const_checked::get_query_non_incr::__rust_end_short_backtrace
                23: <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners::<rustc_interface::passes::run_required_analyses::{closure#1}::{closure#0}>::{closure#0}
                24: rustc_interface::passes::analysis
                25: rustc_query_impl::plumbing::__rust_begin_short_backtrace::<rustc_query_impl::query_impl::analysis::make_query_vtable::{closure#1}::{closure#0}, rustc_middle::query::erase::ErasedData<[u8; 0]>>
                26: rustc_query_system::query::plumbing::try_execute_query::<rustc_query_impl::SemiDynamicQueryDispatcher<rustc_query_system::query::caches::SingleCache<rustc_middle::query::erase::ErasedData<[u8; 0]>>, false, false, false>, false>
                27: rustc_query_impl::query_impl::analysis::get_query_non_incr::__rust_end_short_backtrace
                28: <rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>::{closure#2} as core::ops::function::FnOnce<(&rustc_session::session::Session, rustc_middle::ty::context::CurrentGcx, alloc::sync::Arc<rustc_data_structures::jobserver::Proxy>, &std::sync::once_lock::OnceLock<rustc_middle::ty::context::GlobalCtxt>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_middle::arena::Arena>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_hir::Arena>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2})>>::call_once::{shim:vtable#0}
                29: rustc_interface::interface::run_compiler::<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}
                30: std::sys::backtrace::__rust_begin_short_backtrace::<rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>
                31: <std::thread::lifecycle::spawn_unchecked<rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1} as core::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
                32: <std::sys::thread::unix::Thread>::new::thread_start
                33: <unknown>
                34: clone
              
    
    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: please make sure that you have updated to the latest nightly
    
    note: please attach the file at `/playground/rustc-ice-2026-01-31T04_07_12-50.txt` to your bug report
    
    note: rustc 1.95.0-nightly (a293cc4af 2026-01-30) running on x86_64-unknown-linux-gnu
    
    note: compiler flags: --crate-type bin -C embed-bitcode=no -C codegen-units=1 -C debuginfo=2
    
    note: some of the compiler flags provided by cargo are hidden
    
    query stack during panic:
    end of query stack
    
  5. added
    I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jan 31, 2026
  6. s7tya commented on May 27, 2026

    @s7tya
    Contributor

    A slightly smaller code snippet that still causes an ICE:

    #[allow(unused)]
    
    fn main() {
        let [(ref a, b), x];
        a = "";
        b = 5;
    }
  7. added 2 commits that reference this issue on Jun 10, 2026
    7570cff
    1bc4eb3
  8. added 6 commits that reference this issue on Jun 10, 2026
    fcb54aa
    aa7e6ff
    c1ed23c
    9f98787
    91f75be
    902f01b
  9. added a commit that references this issue on Jun 11, 2026
    220f0fa
  10. theemathas commented on Jun 12, 2026

    @theemathas
    ContributorAuthor

    Reopening due to a revert in #157795

  11. added
    S-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issue
    S-bug-has-testStatus: This bug is tracked inside the repo by a `known-bug` test.
    on Jun 28, 2026
  12. matthiaskrgr commented on Aug 6, 2026

    @matthiaskrgr
    Member

    the middle example from #150040 (comment) will crash with --emit=mir

    thread 'rustc' (2738477) panicked at /rustc-dev/7608eb7b07eaf93f16d7cf5bcb2098eca87503df/compiler/rustc_const_eval/src/interpret/projection.rs:167:13:
    assertion failed: !base.layout().is_sized()
    
    
  13. s7tya commented on Aug 12, 2026

    @s7tya
    Contributor

    Finally fixed in #157841

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-patternsRelating to patterns and pattern matchingA-type-systemArea: Type systemC-bugCategory: This is a bug.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️S-bug-has-testStatus: This bug is tracked inside the repo by a `known-bug` test.S-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions