From 23144573a871726bca6e271ff80168cf5acba640 Mon Sep 17 00:00:00 2001 From: steamproof <93405617+pbkx@users.noreply.github.com> Date: Sun, 31 May 2026 20:10:17 -0700 Subject: [PATCH 1/2] borrowck: avoid ICE describing fields on generic params --- .../rustc_borrowck/src/diagnostics/mod.rs | 1 + ...-describe-field-generic-param-owned-box.rs | 56 +++++++++++++++++++ ...cribe-field-generic-param-owned-box.stderr | 9 +++ 3 files changed, 66 insertions(+) create mode 100644 tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.rs create mode 100644 tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 248396ba9849b..0b21ab419886b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -525,6 +525,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ty::Array(ty, _) | ty::Slice(ty) => { self.describe_field_from_ty(ty, field, variant_index, including_tuple_field) } + ty::Param(_) => Some(field.index().to_string()), ty::Closure(def_id, _) | ty::Coroutine(def_id, _) => { // We won't be borrowck'ing here if the closure came from another crate, // so it's safe to call `expect_local`. diff --git a/tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.rs b/tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.rs new file mode 100644 index 0000000000000..95a34f173fbd3 --- /dev/null +++ b/tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.rs @@ -0,0 +1,56 @@ +// Regression test for #155344. +// Borrowck diagnostics should not ICE when describing a field access on a generic parameter. + +//@ edition: 2024 + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "pointee_sized"] +pub trait PointeeSized {} + +#[lang = "meta_sized"] +pub trait MetaSized: PointeeSized {} + +#[lang = "sized"] +pub trait Sized: MetaSized {} + +#[lang = "legacy_receiver"] +pub trait LegacyReceiver {} + +impl LegacyReceiver for &T {} +impl LegacyReceiver for &mut T {} + +#[lang = "copy"] +pub trait Copy {} + +impl Copy for *mut () {} + +#[lang = "drop"] +pub trait Drop { + fn drop(&mut self); +} + +unsafe extern "C" { + fn free(_: *mut ()); +} + +unsafe fn transmute(_: T) -> U { + loop {} +} + +#[repr(transparent)] +pub struct NonNull(pub *const T); + +#[lang = "owned_box"] +pub struct Box(NonNull, A); + +impl Drop for Box { + fn drop(&mut self) { + unsafe { + free(transmute::, *mut _>(self.0)); + //~^ ERROR cannot move out of `self.0` which is behind a mutable reference + } + } +} diff --git a/tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.stderr b/tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.stderr new file mode 100644 index 0000000000000..00fc198bac231 --- /dev/null +++ b/tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of `self.0` which is behind a mutable reference + --> $DIR/borrowck-describe-field-generic-param-owned-box.rs:52:50 + | +LL | free(transmute::, *mut _>(self.0)); + | ^^^^^^ move occurs because `self.0` has type `NonNull`, which does not implement the `Copy` trait + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0507`. From 5a7ca04b70c4f33c04820f9467b5ba1e14fedf8b Mon Sep 17 00:00:00 2001 From: steamproof <93405617+pbkx@users.noreply.github.com> Date: Fri, 5 Jun 2026 01:00:31 -0700 Subject: [PATCH 2/2] Use field-index fallback for undescribed fields --- compiler/rustc_borrowck/src/diagnostics/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 0b21ab419886b..564b6f09f0095 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -525,7 +525,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ty::Array(ty, _) | ty::Slice(ty) => { self.describe_field_from_ty(ty, field, variant_index, including_tuple_field) } - ty::Param(_) => Some(field.index().to_string()), ty::Closure(def_id, _) | ty::Coroutine(def_id, _) => { // We won't be borrowck'ing here if the closure came from another crate, // so it's safe to call `expect_local`. @@ -538,9 +537,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { Some(self.infcx.tcx.hir_name(var_id).to_string()) } _ => { - // Might need a revision when the fields in trait RFC is implemented - // (https://github.com/rust-lang/rfcs/pull/1546) - bug!("End-user description not implemented for field access on `{:?}`", ty); + // This can happen for field accesses on `Box`: the field is + // described from the boxed type, which may have no named fields + Some(field.index().to_string()) } } }