From 180e599d56c325513f1bcba038952b3cda17575c Mon Sep 17 00:00:00 2001 From: Adwin White Date: Sat, 27 Jun 2026 15:56:22 +0800 Subject: [PATCH 01/16] use correct typing mode in mir building for the next solver --- compiler/rustc_middle/src/ty/mod.rs | 17 ++++++++++++ compiler/rustc_mir_build/src/builder/mod.rs | 24 ++++++++++++----- compiler/rustc_mir_build/src/builder/scope.rs | 6 +++-- .../rustc_mir_build/src/check_tail_calls.rs | 3 +-- .../rustc_mir_build/src/check_unsafety.rs | 3 +-- compiler/rustc_mir_build/src/thir/cx/mod.rs | 4 +-- .../src/thir/pattern/check_match.rs | 3 +-- .../opaques/wrong-typing-mode-ice-1.rs | 27 +++++++++++++++++++ .../opaques/wrong-typing-mode-ice-1.stderr | 9 +++++++ .../opaques/wrong-typing-mode-ice-2.rs | 15 +++++++++++ 10 files changed, 94 insertions(+), 17 deletions(-) create mode 100644 tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-1.rs create mode 100644 tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-1.stderr create mode 100644 tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-2.rs diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3ea798ee45fb2..b86a51b28b022 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1127,6 +1127,23 @@ impl<'tcx> TypingEnv<'tcx> { Self::new(tcx.param_env(def_id), TypingMode::non_body_analysis()) } + /// Ideally we just use `TypingMode::PostTypeckUntilBorrowck`. + /// But that's not compatible with the old solver yet. + /// + /// FIXME: this should not be needed in the long term. + pub fn post_typeck_until_borrowck_for_mir_build( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + ) -> TypingEnv<'tcx> { + if tcx.use_typing_mode_post_typeck_until_borrowck() { + TypingEnv::new(tcx.param_env(def_id.to_def_id()), ty::TypingMode::borrowck(tcx, def_id)) + } else { + // FIXME(#132279): We're in a body, we should use a typing + // mode which reveals the opaque types defined by that body. + TypingEnv::non_body_analysis(tcx, def_id) + } + } + pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryKey) -> TypingEnv<'tcx> { TypingEnv::new(tcx.param_env_normalized_for_post_analysis(def_id), TypingMode::PostAnalysis) } diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 854a378bb993d..34a9e573a508f 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -505,9 +505,15 @@ fn construct_fn<'tcx>( ); } - // FIXME(#132279): This should be able to reveal opaque - // types defined during HIR typeck. - let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let typing_mode = if tcx.use_typing_mode_post_typeck_until_borrowck() { + TypingMode::borrowck(tcx, fn_def) + } else { + // FIXME(#132279): This should be able to reveal opaque + // types defined during HIR typeck. + TypingMode::non_body_analysis() + }; + + let infcx = tcx.infer_ctxt().build(typing_mode); let mut builder = Builder::new( thir, infcx, @@ -586,9 +592,15 @@ fn construct_const<'a, 'tcx>( _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def), }; - // FIXME(#132279): We likely want to be able to use the hidden types of - // opaques used by this function here. - let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let typing_mode = if tcx.use_typing_mode_post_typeck_until_borrowck() { + TypingMode::borrowck(tcx, def) + } else { + // FIXME(#132279): This should be able to reveal opaque + // types defined during HIR typeck. + TypingMode::non_body_analysis() + }; + + let infcx = tcx.infer_ctxt().build(typing_mode); let mut builder = Builder::new(thir, infcx, def, hir_id, span, 0, const_ty, const_ty_span, None); diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 84abb6ca70e70..4810418c4bb10 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -969,8 +969,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { tcx: self.tcx, typeck_results, module: self.tcx.parent_module(self.hir_id).to_def_id(), - // FIXME(#132279): We're in a body, should handle opaques. - typing_env: rustc_middle::ty::TypingEnv::non_body_analysis(self.tcx, self.def_id), + typing_env: ty::TypingEnv::post_typeck_until_borrowck_for_mir_build( + self.tcx, + self.def_id, + ), dropless_arena: &dropless_arena, match_lint_level: self.hir_id, whole_match_span: Some(rustc_span::Span::default()), diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs index ac9f6e384cf04..26deba3f58c5a 100644 --- a/compiler/rustc_mir_build/src/check_tail_calls.rs +++ b/compiler/rustc_mir_build/src/check_tail_calls.rs @@ -27,8 +27,7 @@ pub(crate) fn check_tail_calls(tcx: TyCtxt<'_>, def: LocalDefId) -> Result<(), E tcx, thir, found_errors: Ok(()), - // FIXME(#132279): we're clearly in a body here. - typing_env: ty::TypingEnv::non_body_analysis(tcx, def), + typing_env: ty::TypingEnv::post_typeck_until_borrowck_for_mir_build(tcx, def), is_closure, caller_def_id: def, }; diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index a5e5b9f7699b8..70e9129ffee3f 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -1093,8 +1093,7 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { body_target_features, assignment_info: None, in_union_destructure: false, - // FIXME(#132279): we're clearly in a body here. - typing_env: ty::TypingEnv::non_body_analysis(tcx, def), + typing_env: ty::TypingEnv::post_typeck_until_borrowck_for_mir_build(tcx, def), inside_adt: false, warnings: &mut warnings, suggest_unsafe_block: true, diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index eb8573dd5e886..8e654032e8b71 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -99,9 +99,7 @@ impl<'tcx> ThirBuildCx<'tcx> { Self { tcx, thir: Thir::new(body_type), - // FIXME(#132279): We're in a body, we should use a typing - // mode which reveals the opaque types defined by that body. - typing_env: ty::TypingEnv::non_body_analysis(tcx, def), + typing_env: ty::TypingEnv::post_typeck_until_borrowck_for_mir_build(tcx, def), typeck_results, body_owner: def.to_def_id(), apply_adjustments: !find_attr!(tcx, hir_id, CustomMir(..)), diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 7a38d9293724d..a757c96bd7f3d 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -39,8 +39,7 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err tcx, thir: &*thir, typeck_results, - // FIXME(#132279): We're in a body, should handle opaques. - typing_env: ty::TypingEnv::non_body_analysis(tcx, def_id), + typing_env: ty::TypingEnv::post_typeck_until_borrowck_for_mir_build(tcx, def_id), hir_source: tcx.local_def_id_to_hir_id(def_id), let_source: LetSource::None, pattern_arena: &pattern_arena, diff --git a/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-1.rs b/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-1.rs new file mode 100644 index 0000000000000..700e38cc3d8a2 --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-1.rs @@ -0,0 +1,27 @@ +//@ compile-flags: -Znext-solver +//@ edition: 2024 + +// Previously, when building MIR body, we were using typing env +// `non_body_analysis` which is wrong since we're indeed in a body. +// It caused opaque types in defining body to be not revealed. +// This caused opaque types in the defining body not to be revealed. + +#![feature(type_alias_impl_trait)] + +struct Task(F); + +impl Task { + fn spawn(&self, _: impl FnOnce() -> Foo) {} +} +type Foo = impl Sized; + +#[define_opaque(Foo)] +fn foo() { + async fn cb() {} + Task::spawn(&POOL, cb) +} + +static POOL: Task = todo!(); +//~^ ERROR: evaluation panicked + +fn main() {} diff --git a/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-1.stderr b/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-1.stderr new file mode 100644 index 0000000000000..95c000394a982 --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-1.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation panicked: not yet implemented + --> $DIR/wrong-typing-mode-ice-1.rs:24:26 + | +LL | static POOL: Task = todo!(); + | ^^^^^^^ evaluation of `POOL` failed here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-2.rs b/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-2.rs new file mode 100644 index 0000000000000..e27858b6b6fa0 --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/wrong-typing-mode-ice-2.rs @@ -0,0 +1,15 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Previously, when building MIR body, we were using typing env +// `non_body_analysis` which is wrong since we're indeed in a body. +// It caused opaque types in defining body to be not revealed. +// This caused opaque types in the defining body not to be revealed. + +#![feature(type_alias_impl_trait)] +fn main() { + struct Foo(U); + type U = impl Copy; + let foo: _ = Foo(()); + let Foo(()) = foo; +} From 1316aa8049b15926165ce7f6631fce51f545bd77 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Mon, 29 Jun 2026 13:00:05 +0900 Subject: [PATCH 02/16] Instatiate binder instead of skipping when suggesting functiom arg error --- .../src/error_reporting/traits/suggestions.rs | 18 +++-- .../iterator-item-suggest-no-ice.rs | 22 ++++++ .../iterator-item-suggest-no-ice.stderr | 71 +++++++++++++++++++ 3 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.rs create mode 100644 tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 4e3a31f0e84b5..3c702f8871c42 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4872,12 +4872,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }) } else if let Some(where_pred) = where_pred.as_projection_clause() && let Some(failed_pred) = failed_pred.as_projection_clause() - && let Some(found) = failed_pred.skip_binder().term.as_type() + && let Some(found) = + failed_pred.map_bound(|pred| pred.term.as_type()).transpose().map(|term| { + self.instantiate_binder_with_fresh_vars( + expr.span, + BoundRegionConversionTime::FnCall, + term, + ) + }) { type_diffs = vec![TypeError::Sorts(ty::error::ExpectedFound { - expected: where_pred - .skip_binder() - .projection_term + expected: self + .instantiate_binder_with_fresh_vars( + expr.span, + BoundRegionConversionTime::FnCall, + where_pred.map_bound(|pred| pred.projection_term), + ) .expect_ty() .to_ty(self.tcx, ty::IsRigid::No), found, diff --git a/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.rs b/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.rs new file mode 100644 index 0000000000000..89a37d8c75a31 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.rs @@ -0,0 +1,22 @@ +//! Regression test for +//@ compile-flags: -Znext-solver + +trait FooMut { + fn bar(&self, _: I) + where + for<'b> &'b I: Iterator; + + fn bar(&self, _: I) + //~^ ERROR: the name `bar` is defined multiple times + where + I: Iterator, + { + let collection = vec![_I].iter().map(|x| ()); + //~^ ERROR: cannot find value `_I` in this scope + self.bar(collection); + //~^ ERROR: `&'b _` is not an iterator + //~| ERROR: type mismatch resolving `<&_ as Iterator>::Item == &()` + } +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr b/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr new file mode 100644 index 0000000000000..0bd604d03fdf2 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr @@ -0,0 +1,71 @@ +error[E0428]: the name `bar` is defined multiple times + --> $DIR/iterator-item-suggest-no-ice.rs:9:5 + | +LL | / fn bar(&self, _: I) +LL | | where +LL | | for<'b> &'b I: Iterator; + | |_______________________________________________- previous definition of the value `bar` here +LL | +LL | / fn bar(&self, _: I) +LL | | +LL | | where +LL | | I: Iterator, +... | +LL | | } + | |_____^ `bar` redefined here + | + = note: `bar` must be defined only once in the value namespace of this trait + +error[E0425]: cannot find value `_I` in this scope + --> $DIR/iterator-item-suggest-no-ice.rs:14:31 + | +LL | let collection = vec![_I].iter().map(|x| ()); + | ^^ not found in this scope + +error[E0277]: `&'b _` is not an iterator + --> $DIR/iterator-item-suggest-no-ice.rs:16:18 + | +LL | self.bar(collection); + | --- ^^^^^^^^^^ `&'b _` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `for<'b> Iterator` is not implemented for `&'b _` +note: required by a bound in `FooMut::bar` + --> $DIR/iterator-item-suggest-no-ice.rs:7:24 + | +LL | fn bar(&self, _: I) + | --- required by a bound in this associated function +LL | where +LL | for<'b> &'b I: Iterator; + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `FooMut::bar` + +error[E0271]: type mismatch resolving `<&_ as Iterator>::Item == &()` + --> $DIR/iterator-item-suggest-no-ice.rs:16:18 + | +LL | self.bar(collection); + | --- ^^^^^^^^^^ types differ + | | + | required by a bound introduced by this call + | +note: the method call chain might not have had the expected associated types + --> $DIR/iterator-item-suggest-no-ice.rs:14:35 + | +LL | let collection = vec![_I].iter().map(|x| ()); + | -------- ^^^^^^ ----------- `Iterator::Item` remains `<{type error} as Iterator>::Item` here + | | | + | | `Iterator::Item` is `<{type error} as Iterator>::Item` here + | this expression has type `Vec<{type error}>` +note: required by a bound in `FooMut::bar` + --> $DIR/iterator-item-suggest-no-ice.rs:7:33 + | +LL | fn bar(&self, _: I) + | --- required by a bound in this associated function +LL | where +LL | for<'b> &'b I: Iterator; + | ^^^^^^^^^^^^^ required by this bound in `FooMut::bar` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0271, E0277, E0425, E0428. +For more information about an error, try `rustc --explain E0271`. From c61c52f51de4d41929a9a20f5921afa73e5718cf Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Thu, 2 Jul 2026 23:20:11 -0700 Subject: [PATCH 03/16] detect cycles during valtree construction for self-referential consts --- .../src/const_eval/valtrees.rs | 91 ++++++++++++------- compiler/rustc_middle/src/error.rs | 9 ++ .../rustc_middle/src/mir/interpret/error.rs | 2 + .../rustc_middle/src/mir/interpret/queries.rs | 7 ++ .../cyclic-const-generic-issue-144719.rs | 20 ++++ .../cyclic-const-generic-issue-144719.stderr | 19 ++++ .../const_in_pattern/cyclic-const-dag-pass.rs | 13 +++ .../cyclic-const-long-chain-issue-144719.rs | 24 +++++ ...yclic-const-long-chain-issue-144719.stderr | 10 ++ .../cyclic-const-mutual-issue-144719.rs | 14 +++ .../cyclic-const-mutual-issue-144719.stderr | 10 ++ .../cyclic-const-pattern-issue-144719.rs | 13 +++ .../cyclic-const-pattern-issue-144719.stderr | 10 ++ 13 files changed, 211 insertions(+), 31 deletions(-) create mode 100644 tests/ui/const-generics/adt_const_params/cyclic-const-generic-issue-144719.rs create mode 100644 tests/ui/const-generics/adt_const_params/cyclic-const-generic-issue-144719.stderr create mode 100644 tests/ui/consts/const_in_pattern/cyclic-const-dag-pass.rs create mode 100644 tests/ui/consts/const_in_pattern/cyclic-const-long-chain-issue-144719.rs create mode 100644 tests/ui/consts/const_in_pattern/cyclic-const-long-chain-issue-144719.stderr create mode 100644 tests/ui/consts/const_in_pattern/cyclic-const-mutual-issue-144719.rs create mode 100644 tests/ui/consts/const_in_pattern/cyclic-const-mutual-issue-144719.stderr create mode 100644 tests/ui/consts/const_in_pattern/cyclic-const-pattern-issue-144719.rs create mode 100644 tests/ui/consts/const_in_pattern/cyclic-const-pattern-issue-144719.stderr diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 1c6b623bbf267..1b6c948657e0d 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -1,4 +1,5 @@ use rustc_abi::{BackendRepr, FieldIdx, VariantIdx}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ValTreeCreationError}; use rustc_middle::traits::ObligationCause; @@ -17,13 +18,15 @@ use crate::interpret::{ intern_const_alloc_recursive, }; -#[instrument(skip(ecx), level = "debug")] +#[instrument(skip(ecx, visited, settled), level = "debug")] fn branches<'tcx>( ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>, field_count: usize, variant: Option, num_nodes: &mut usize, + visited: &mut FxHashSet>, + settled: &mut FxHashMap, EvalToValTreeResult<'tcx>>, ) -> EvalToValTreeResult<'tcx> { let place = match variant { Some(variant) => ecx.project_downcast(place, variant).unwrap(), @@ -45,7 +48,7 @@ fn branches<'tcx>( for i in 0..field_count { let field = ecx.project_field(&place, FieldIdx::from_usize(i)).unwrap(); - let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?; + let valtree = const_to_valtree_inner(ecx, &field, num_nodes, visited, settled)?; branches.push(ty::Const::new_value(*ecx.tcx, valtree, field.layout.ty)); } @@ -57,39 +60,53 @@ fn branches<'tcx>( Ok(ty::ValTree::from_branches(*ecx.tcx, branches)) } -#[instrument(skip(ecx), level = "debug")] +#[instrument(skip(ecx, visited, settled), level = "debug")] fn slice_branches<'tcx>( ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>, num_nodes: &mut usize, + visited: &mut FxHashSet>, + settled: &mut FxHashMap, EvalToValTreeResult<'tcx>>, ) -> EvalToValTreeResult<'tcx> { let n = place.len(ecx).unwrap_or_else(|_| panic!("expected to use len of place {place:?}")); let mut elems = Vec::with_capacity(n as usize); for i in 0..n { let place_elem = ecx.project_index(place, i).unwrap(); - let valtree = const_to_valtree_inner(ecx, &place_elem, num_nodes)?; + let valtree = const_to_valtree_inner(ecx, &place_elem, num_nodes, visited, settled)?; elems.push(ty::Const::new_value(*ecx.tcx, valtree, place_elem.layout.ty)); } Ok(ty::ValTree::from_branches(*ecx.tcx, elems)) } -#[instrument(skip(ecx), level = "debug")] +#[instrument(skip(ecx, visited, settled), level = "debug")] fn const_to_valtree_inner<'tcx>( ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>, num_nodes: &mut usize, + visited: &mut FxHashSet>, + settled: &mut FxHashMap, EvalToValTreeResult<'tcx>>, ) -> EvalToValTreeResult<'tcx> { let tcx = *ecx.tcx; let ty = place.layout.ty; debug!("ty kind: {:?}", ty.kind()); + if let Some(&result) = settled.get(place) { + return result; + } + + if visited.contains(place) { + return Err(ValTreeCreationError::CyclicConst); + } + if *num_nodes >= VALTREE_MAX_NODES { return Err(ValTreeCreationError::NodesOverflow); } - match ty.kind() { + visited.insert(place.clone()); + + let result = ensure_sufficient_stack(|| match ty.kind() { ty::FnDef(..) => { *num_nodes += 1; Ok(ty::ValTree::zst(tcx)) @@ -108,7 +125,7 @@ fn const_to_valtree_inner<'tcx>( // Since the returned valtree does not contain the type or layout, we can just // switch to the base type. place.layout = ecx.layout_of(*base).unwrap(); - ensure_sufficient_stack(|| const_to_valtree_inner(ecx, &place, num_nodes)) + const_to_valtree_inner(ecx, &place, num_nodes, visited, settled) } ty::RawPtr(_, _) => { @@ -120,16 +137,16 @@ fn const_to_valtree_inner<'tcx>( // We could allow wide raw pointers where both sides are integers in the future, // but for now we reject them. if matches!(val.layout.backend_repr, BackendRepr::ScalarPair(..)) { - return Err(ValTreeCreationError::NonSupportedType(ty)); + Err(ValTreeCreationError::NonSupportedType(ty)) + } else { + let val = val.to_scalar(); + // We are in the CTFE machine, so ptr-to-int casts will fail. + // This can only be `Ok` if `val` already is an integer. + match val.try_to_scalar_int() { + Ok(val) => Ok(ty::ValTree::from_scalar_int(tcx, val)), + Err(_) => Err(ValTreeCreationError::NonSupportedType(ty)), + } } - let val = val.to_scalar(); - // We are in the CTFE machine, so ptr-to-int casts will fail. - // This can only be `Ok` if `val` already is an integer. - let Ok(val) = val.try_to_scalar_int() else { - return Err(ValTreeCreationError::NonSupportedType(ty)); - }; - // It's just a ScalarInt! - Ok(ty::ValTree::from_scalar_int(tcx, val)) } // Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to @@ -138,33 +155,39 @@ fn const_to_valtree_inner<'tcx>( ty::Ref(_, _, _) => { let derefd_place = ecx.deref_pointer(place).report_err()?; - const_to_valtree_inner(ecx, &derefd_place, num_nodes) + const_to_valtree_inner(ecx, &derefd_place, num_nodes, visited, settled) } - ty::Str | ty::Slice(_) | ty::Array(_, _) => slice_branches(ecx, place, num_nodes), + ty::Str | ty::Slice(_) | ty::Array(_, _) => { + slice_branches(ecx, place, num_nodes, visited, settled) + } // Trait objects are not allowed in type level constants, as we have no concept for // resolving their backing type, even if we can do that at const eval time. We may // hypothetically be able to allow `dyn StructuralPartialEq` trait objects in the future, // but it is unclear if this is useful. ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType(ty)), - ty::Tuple(elem_tys) => branches(ecx, place, elem_tys.len(), None, num_nodes), + ty::Tuple(elem_tys) => { + branches(ecx, place, elem_tys.len(), None, num_nodes, visited, settled) + } ty::Adt(def, _) => { if def.is_union() { - return Err(ValTreeCreationError::NonSupportedType(ty)); + Err(ValTreeCreationError::NonSupportedType(ty)) } else if def.variants().is_empty() { bug!("uninhabited types should have errored and never gotten converted to valtree") + } else { + let variant = ecx.read_discriminant(place).report_err()?; + branches( + ecx, + place, + def.variant(variant).fields.len(), + def.is_enum().then_some(variant), + num_nodes, + visited, + settled, + ) } - - let variant = ecx.read_discriminant(place).report_err()?; - branches( - ecx, - place, - def.variant(variant).fields.len(), - def.is_enum().then_some(variant), - num_nodes, - ) } // FIXME(oli-obk): we could look behind opaque types @@ -186,7 +209,11 @@ fn const_to_valtree_inner<'tcx>( | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::UnsafeBinder(_) => Err(ValTreeCreationError::NonSupportedType(ty)), - } + }); + + visited.remove(place); + settled.insert(place.clone(), result); + result } /// Valtrees don't store the `MemPlaceMeta` that all dynamically sized values have in the interpreter. @@ -257,7 +284,9 @@ pub(crate) fn eval_to_valtree<'tcx>( debug!(?place); let mut num_nodes = 0; - const_to_valtree_inner(&ecx, &place, &mut num_nodes) + let mut visited = FxHashSet::default(); + let mut settled = FxHashMap::default(); + const_to_valtree_inner(&ecx, &place, &mut num_nodes, &mut visited, &mut settled) } /// Converts a `ValTree` to a `ConstValue`, which is needed after mir diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 2823b7ba4e22e..ae2695987ff13 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -144,6 +144,15 @@ pub(crate) struct InvalidConstInValtree { pub global_const_id: String, } +#[derive(Diagnostic)] +#[diag("constant {$global_const_id} cannot be used as pattern")] +#[note("constants whose type references itself cannot be used as patterns")] +pub(crate) struct CyclicConstInValtree { + #[primary_span] + pub span: Span, + pub global_const_id: String, +} + #[derive(Diagnostic)] #[diag("internal compiler error: reentrant incremental verify failure, suppressing message")] pub(crate) struct Reentrant; diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 7d9f6903d3ef0..e2c67b29943d6 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -105,6 +105,8 @@ pub enum ValTreeCreationError<'tcx> { InvalidConst, /// Values of this type, or this particular value, are not supported as valtrees. NonSupportedType(Ty<'tcx>), + /// Trying to valtree this constant would cause the valtree to have cycles. + CyclicConst, /// The error has already been handled by const evaluation. ErrorHandled(ErrorHandled), } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 51cf856a2d477..5e060dfb0e137 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -232,6 +232,13 @@ impl<'tcx> TyCtxt<'tcx> { }); Err(ReportedErrorInfo::allowed_in_infallible(handled).into()) } + ValTreeCreationError::CyclicConst => { + let handled = self.dcx().emit_err(error::CyclicConstInValtree { + span, + global_const_id: cid.display(self), + }); + Err(ReportedErrorInfo::allowed_in_infallible(handled).into()) + } ValTreeCreationError::ErrorHandled(handled) => Err(handled), } } diff --git a/tests/ui/const-generics/adt_const_params/cyclic-const-generic-issue-144719.rs b/tests/ui/const-generics/adt_const_params/cyclic-const-generic-issue-144719.rs new file mode 100644 index 0000000000000..64dd496ada58d --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/cyclic-const-generic-issue-144719.rs @@ -0,0 +1,20 @@ +//! Const generic variant of #144719 + +#![feature(adt_const_params, unsized_const_params)] +#![allow(incomplete_features)] + +use std::marker::ConstParamTy; + +#[derive(PartialEq, Eq, ConstParamTy)] +struct Thing(&'static Thing); + +static X: Thing = Thing(&X); +const Y: &Thing = &X; + +fn foo() -> usize { 0 } + +fn main() { + foo::(); + //~^ ERROR constant main::{constant#0} cannot be used as pattern + //~| ERROR constant main::{constant#0} cannot be used as pattern +} diff --git a/tests/ui/const-generics/adt_const_params/cyclic-const-generic-issue-144719.stderr b/tests/ui/const-generics/adt_const_params/cyclic-const-generic-issue-144719.stderr new file mode 100644 index 0000000000000..2b278d6aba183 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/cyclic-const-generic-issue-144719.stderr @@ -0,0 +1,19 @@ +error: constant main::{constant#0} cannot be used as pattern + --> $DIR/cyclic-const-generic-issue-144719.rs:17:11 + | +LL | foo::(); + | ^ + | + = note: constants whose type references itself cannot be used as patterns + +error: constant main::{constant#0} cannot be used as pattern + --> $DIR/cyclic-const-generic-issue-144719.rs:17:11 + | +LL | foo::(); + | ^ + | + = note: constants whose type references itself cannot be used as patterns + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/consts/const_in_pattern/cyclic-const-dag-pass.rs b/tests/ui/consts/const_in_pattern/cyclic-const-dag-pass.rs new file mode 100644 index 0000000000000..cecf55d23e6b7 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cyclic-const-dag-pass.rs @@ -0,0 +1,13 @@ +//@ run-pass +//! Regression test: shared references to the same static (DAG) must not be +//! misidentified as cyclic during valtree construction. + +#[derive(PartialEq)] +struct Pair(&'static i32, &'static i32); + +static X: i32 = 42; +const P: Pair = Pair(&X, &X); + +fn main() { + if let P = P {} +} diff --git a/tests/ui/consts/const_in_pattern/cyclic-const-long-chain-issue-144719.rs b/tests/ui/consts/const_in_pattern/cyclic-const-long-chain-issue-144719.rs new file mode 100644 index 0000000000000..39d22558b15dd --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cyclic-const-long-chain-issue-144719.rs @@ -0,0 +1,24 @@ +//! Regression test for #144719: long reference cycles shouldn't +//! overflow the stack. +//@ rustc-env:RUST_MIN_STACK=3000000 + +#[derive(PartialEq, Copy, Clone)] +struct Thing(&'static Thing); + +const N: usize = 8000; +static A: Thing = Thing(&B[0]); +static B: [Thing; N] = { + let mut x = [Thing(&A); N]; + let mut i = 0; + while i < N - 1 { + x[i] = Thing(&B[i + 1]); + i += 1; + } + x +}; +const C: &Thing = &A; + +fn main() { + if let C = C {} + //~^ ERROR constant C cannot be used as pattern +} diff --git a/tests/ui/consts/const_in_pattern/cyclic-const-long-chain-issue-144719.stderr b/tests/ui/consts/const_in_pattern/cyclic-const-long-chain-issue-144719.stderr new file mode 100644 index 0000000000000..a549081a26475 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cyclic-const-long-chain-issue-144719.stderr @@ -0,0 +1,10 @@ +error: constant C cannot be used as pattern + --> $DIR/cyclic-const-long-chain-issue-144719.rs:22:12 + | +LL | if let C = C {} + | ^ + | + = note: constants whose type references itself cannot be used as patterns + +error: aborting due to 1 previous error + diff --git a/tests/ui/consts/const_in_pattern/cyclic-const-mutual-issue-144719.rs b/tests/ui/consts/const_in_pattern/cyclic-const-mutual-issue-144719.rs new file mode 100644 index 0000000000000..371a6a3811419 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cyclic-const-mutual-issue-144719.rs @@ -0,0 +1,14 @@ +//! Regression test for #144719: mutually recursive statics forming a +//! reference cycle caused a stack overflow during valtree construction. + +#[derive(PartialEq)] +struct Thing(&'static Thing); + +static A: Thing = Thing(&B); +static B: Thing = Thing(&A); +const C: &Thing = &A; + +fn main() { + if let C = C {} + //~^ ERROR constant C cannot be used as pattern +} diff --git a/tests/ui/consts/const_in_pattern/cyclic-const-mutual-issue-144719.stderr b/tests/ui/consts/const_in_pattern/cyclic-const-mutual-issue-144719.stderr new file mode 100644 index 0000000000000..e26505d9ce3ef --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cyclic-const-mutual-issue-144719.stderr @@ -0,0 +1,10 @@ +error: constant C cannot be used as pattern + --> $DIR/cyclic-const-mutual-issue-144719.rs:12:12 + | +LL | if let C = C {} + | ^ + | + = note: constants whose type references itself cannot be used as patterns + +error: aborting due to 1 previous error + diff --git a/tests/ui/consts/const_in_pattern/cyclic-const-pattern-issue-144719.rs b/tests/ui/consts/const_in_pattern/cyclic-const-pattern-issue-144719.rs new file mode 100644 index 0000000000000..c54cb254b5cd8 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cyclic-const-pattern-issue-144719.rs @@ -0,0 +1,13 @@ +//! Regression test for #144719: using a self-referential static in a +//! pattern position caused a stack overflow during valtree construction. + +#[derive(PartialEq)] +struct Thing(&'static Thing); + +static X: Thing = Thing(&X); +const Y: &Thing = &X; + +fn main() { + if let Y = Y {} + //~^ ERROR constant Y cannot be used as pattern +} diff --git a/tests/ui/consts/const_in_pattern/cyclic-const-pattern-issue-144719.stderr b/tests/ui/consts/const_in_pattern/cyclic-const-pattern-issue-144719.stderr new file mode 100644 index 0000000000000..e89b6abcac33b --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cyclic-const-pattern-issue-144719.stderr @@ -0,0 +1,10 @@ +error: constant Y cannot be used as pattern + --> $DIR/cyclic-const-pattern-issue-144719.rs:11:12 + | +LL | if let Y = Y {} + | ^ + | + = note: constants whose type references itself cannot be used as patterns + +error: aborting due to 1 previous error + From 74fa6b994ab24b5653d5dd9b97b8b536128df996 Mon Sep 17 00:00:00 2001 From: Amirhossein Akhlaghpour Date: Sun, 5 Jul 2026 19:37:56 +0330 Subject: [PATCH 04/16] chore: add regression test for late-bound type method probe ICE Signed-off-by: Amirhossein Akhlaghpour --- .../ui/traits/late-bound-type-method-probe.rs | 19 +++++++++++++++++++ .../late-bound-type-method-probe.stderr | 17 +++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/ui/traits/late-bound-type-method-probe.rs create mode 100644 tests/ui/traits/late-bound-type-method-probe.stderr diff --git a/tests/ui/traits/late-bound-type-method-probe.rs b/tests/ui/traits/late-bound-type-method-probe.rs new file mode 100644 index 0000000000000..ed6b3d866d7a2 --- /dev/null +++ b/tests/ui/traits/late-bound-type-method-probe.rs @@ -0,0 +1,19 @@ +// A method probe involving a late-bound type parameter should report normal +// diagnostics instead of ICEing while structurally normalizing obligations. + +#![feature(non_lifetime_binders)] +#![allow(incomplete_features)] + +pub trait T { + fn t(&self, _: F) {} + //~^ ERROR cannot find type `F` in this scope +} + +pub fn crash(v: &V) +where + for F: T + 'static, +{ + v.t(|| {}); +} + +fn main() {} diff --git a/tests/ui/traits/late-bound-type-method-probe.stderr b/tests/ui/traits/late-bound-type-method-probe.stderr new file mode 100644 index 0000000000000..0ddeb301d5e03 --- /dev/null +++ b/tests/ui/traits/late-bound-type-method-probe.stderr @@ -0,0 +1,17 @@ +error[E0425]: cannot find type `F` in this scope + --> $DIR/late-bound-type-method-probe.rs:8:26 + | +LL | fn t(&self, _: F) {} + | ^ + | + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | + = note: similarly named trait `Fn` defined here +help: a trait with a similar name exists + | +LL | fn t(&self, _: Fn) {} + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. From 1a982425b6699f2b26552c6b44cc979a3d84543b Mon Sep 17 00:00:00 2001 From: Raushan kumar Date: Sun, 5 Jul 2026 07:00:04 +0000 Subject: [PATCH 05/16] Distinguish null reference production from null pointer dereference Introduce a dedicated panic for null reference production to distinguish producing a reference from a null pointer from an actual null pointer dereference. This emits a dedicated panic message for null reference production while preserving the existing panic for actual dereferences. --- compiler/rustc_codegen_cranelift/src/base.rs | 11 +++++++++ compiler/rustc_codegen_ssa/src/mir/block.rs | 5 ++++ .../src/const_eval/machine.rs | 1 + compiler/rustc_hir/src/lang_items.rs | 1 + compiler/rustc_middle/src/mir/syntax.rs | 1 + compiler/rustc_middle/src/mir/terminator.rs | 3 +++ compiler/rustc_middle/src/mir/visit.rs | 2 +- .../rustc_mir_transform/src/check_null.rs | 24 +++++++++---------- compiler/rustc_monomorphize/src/collector.rs | 3 +++ compiler/rustc_public/src/mir/body.rs | 2 ++ compiler/rustc_public/src/mir/pretty.rs | 3 +++ compiler/rustc_public/src/mir/visit.rs | 1 + .../src/unstable/convert/stable/mir.rs | 3 +++ compiler/rustc_span/src/symbol.rs | 1 + library/core/src/panicking.rs | 13 ++++++++++ tests/ui/mir/null/borrowed_mut_null.rs | 2 +- tests/ui/mir/null/borrowed_null.rs | 2 +- tests/ui/mir/null/borrowed_null_zst.rs | 2 +- 18 files changed, 64 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 467eceea221c8..b37fb213d945a 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -421,6 +421,17 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { source_info.span, ) } + AssertKind::NullReferenceConstructed => { + let location = fx.get_caller_location(source_info).load_scalar(fx); + + codegen_panic_inner( + fx, + rustc_hir::LangItem::PanicNullReferenceConstructed, + &[location], + *unwind, + source_info.span, + ) + } AssertKind::InvalidEnumConstruction(source) => { let source = codegen_operand(fx, source).load_scalar(fx); let location = fx.get_caller_location(source_info).load_scalar(fx); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 0173b84a4d9a1..fad93de43b272 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -789,6 +789,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // `#[track_caller]` adds an implicit argument. (LangItem::PanicNullPointerDereference, vec![location]) } + AssertKind::NullReferenceConstructed => { + // It's `fn panic_null_reference_constructed()`, + // `#[track_caller]` adds an implicit argument. + (LangItem::PanicNullReferenceConstructed, vec![location]) + } AssertKind::InvalidEnumConstruction(source) => { let source = self.codegen_operand(bx, source).immediate(); // It's `fn panic_invalid_enum_construction(source: u128)`, diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index b4a97c0b137c9..e7e1dd2ec0fb0 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -772,6 +772,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { found: eval_to_int(found)?, }, NullPointerDereference => NullPointerDereference, + NullReferenceConstructed => NullReferenceConstructed, InvalidEnumConstruction(source) => InvalidEnumConstruction(eval_to_int(source)?), }; Err(ConstEvalErrKind::AssertFailure(err)).into() diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 9c3f7789f9ed9..f0b6d0fb8dcc9 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -309,6 +309,7 @@ language_item_table! { PanicAsyncGenFnResumedPanic, sym::panic_const_async_gen_fn_resumed_panic, panic_const_async_gen_fn_resumed_panic, Target::Fn, GenericRequirement::None; PanicGenFnNonePanic, sym::panic_const_gen_fn_none_panic, panic_const_gen_fn_none_panic, Target::Fn, GenericRequirement::None; PanicNullPointerDereference, sym::panic_null_pointer_dereference, panic_null_pointer_dereference, Target::Fn, GenericRequirement::None; + PanicNullReferenceConstructed, sym::panic_null_reference_constructed, panic_null_reference_constructed, Target::Fn, GenericRequirement::None; PanicInvalidEnumConstruction, sym::panic_invalid_enum_construction, panic_invalid_enum_construction, Target::Fn, GenericRequirement::None; PanicCoroutineResumedDrop, sym::panic_const_coroutine_resumed_drop, panic_const_coroutine_resumed_drop, Target::Fn, GenericRequirement::None; PanicAsyncFnResumedDrop, sym::panic_const_async_fn_resumed_drop, panic_const_async_fn_resumed_drop, Target::Fn, GenericRequirement::None; diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 91ff3f52390e1..5a3d34cb77078 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1061,6 +1061,7 @@ pub enum AssertKind { ResumedAfterDrop(CoroutineKind), MisalignedPointerDereference { required: O, found: O }, NullPointerDereference, + NullReferenceConstructed, InvalidEnumConstruction(O), } diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 3f66fe34af622..aaa0c257925dd 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -210,6 +210,7 @@ impl AssertKind { LangItem::PanicGenFnNonePanic } NullPointerDereference => LangItem::PanicNullPointerDereference, + NullReferenceConstructed => LangItem::PanicNullReferenceConstructed, InvalidEnumConstruction(_) => LangItem::PanicInvalidEnumConstruction, ResumedAfterDrop(CoroutineKind::Coroutine(_)) => LangItem::PanicCoroutineResumedDrop, ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { @@ -287,6 +288,7 @@ impl AssertKind { ) } NullPointerDereference => write!(f, "\"null pointer dereference occurred\""), + NullReferenceConstructed => write!(f, "\"null reference produced\""), InvalidEnumConstruction(source) => { write!(f, "\"trying to construct an enum from an invalid value {{}}\", {source:?}") } @@ -387,6 +389,7 @@ impl fmt::Display for AssertKind { write!(f, "coroutine resumed after panicking") } NullPointerDereference => write!(f, "null pointer dereference occurred"), + NullReferenceConstructed => write!(f, "null reference produced"), InvalidEnumConstruction(source) => { write!(f, "trying to construct an enum from an invalid value `{source:#?}`") } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 921c54b2828c2..22f2d5c1afcac 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -668,7 +668,7 @@ macro_rules! make_mir_visitor { OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) | InvalidEnumConstruction(op) => { self.visit_operand(op, location); } - ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference | ResumedAfterDrop(_) => { + ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference | NullReferenceConstructed | ResumedAfterDrop(_) => { // Nothing to visit } MisalignedPointerDereference { required, found } => { diff --git a/compiler/rustc_mir_transform/src/check_null.rs b/compiler/rustc_mir_transform/src/check_null.rs index b589e2fff1569..beb26a20cd3f8 100644 --- a/compiler/rustc_mir_transform/src/check_null.rs +++ b/compiler/rustc_mir_transform/src/check_null.rs @@ -55,16 +55,19 @@ fn insert_null_check<'tcx>( const_: Const::Val(ConstValue::from_target_usize(0, &tcx), tcx.types.usize), })); - let pointee_should_be_checked = match context { + let (pointee_should_be_checked, assert_kind) = match context { // Borrows pointing to "null" are UB even if the pointee is a ZST. PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => { // Pointer should be checked unconditionally. - Operand::Constant(Box::new(ConstOperand { - span: source_info.span, - user_ty: None, - const_: Const::from_bool(tcx, true), - })) + ( + Operand::Constant(Box::new(ConstOperand { + span: source_info.span, + user_ty: None, + const_: Const::from_bool(tcx, true), + })), + AssertKind::NullReferenceConstructed, + ) } // Other usages of null pointers only are UB if the pointee is not a ZST. _ => { @@ -79,7 +82,7 @@ fn insert_null_check<'tcx>( source_info, StatementKind::Assign(Box::new((pointee_should_be_checked, rvalue))), )); - Operand::Copy(pointee_should_be_checked) + (Operand::Copy(pointee_should_be_checked), AssertKind::NullPointerDereference) } }; @@ -119,9 +122,6 @@ fn insert_null_check<'tcx>( )); // Emit a PointerCheck that asserts on the condition and otherwise triggers - // a AssertKind::NullPointerDereference. - PointerCheck { - cond: Operand::Copy(is_ok), - assert_kind: Box::new(AssertKind::NullPointerDereference), - } + // the chosen AssertKind. + PointerCheck { cond: Operand::Copy(is_ok), assert_kind: Box::new(assert_kind) } } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index ceb044c102f69..bb2548749ea67 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -899,6 +899,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { mir::AssertKind::NullPointerDereference => { push_mono_lang_item(self, LangItem::PanicNullPointerDereference); } + mir::AssertKind::NullReferenceConstructed => { + push_mono_lang_item(self, LangItem::PanicNullReferenceConstructed); + } mir::AssertKind::InvalidEnumConstruction(_) => { push_mono_lang_item(self, LangItem::PanicInvalidEnumConstruction); } diff --git a/compiler/rustc_public/src/mir/body.rs b/compiler/rustc_public/src/mir/body.rs index f9b5f9af951e5..b480ec74bae34 100644 --- a/compiler/rustc_public/src/mir/body.rs +++ b/compiler/rustc_public/src/mir/body.rs @@ -269,6 +269,7 @@ pub enum AssertMessage { ResumedAfterDrop(CoroutineKind), MisalignedPointerDereference { required: Operand, found: Operand }, NullPointerDereference, + NullReferenceConstructed, InvalidEnumConstruction(Operand), } @@ -342,6 +343,7 @@ impl AssertMessage { Ok("misaligned pointer dereference") } AssertMessage::NullPointerDereference => Ok("null pointer dereference occurred"), + AssertMessage::NullReferenceConstructed => Ok("null reference produced"), AssertMessage::InvalidEnumConstruction(_) => { Ok("trying to construct an enum from an invalid value") } diff --git a/compiler/rustc_public/src/mir/pretty.rs b/compiler/rustc_public/src/mir/pretty.rs index dec4044fd260b..3bef4d5cb38df 100644 --- a/compiler/rustc_public/src/mir/pretty.rs +++ b/compiler/rustc_public/src/mir/pretty.rs @@ -310,6 +310,9 @@ fn pretty_assert_message(writer: &mut W, msg: &AssertMessage) -> io::R AssertMessage::NullPointerDereference => { write!(writer, "\"null pointer dereference occurred\"") } + AssertMessage::NullReferenceConstructed => { + write!(writer, "\"null reference produced\"") + } AssertMessage::InvalidEnumConstruction(op) => { let pretty_op = pretty_operand(op); write!(writer, "\"trying to construct an enum from an invalid value {{}}\",{pretty_op}") diff --git a/compiler/rustc_public/src/mir/visit.rs b/compiler/rustc_public/src/mir/visit.rs index 5a3afc9937351..1997a7b957897 100644 --- a/compiler/rustc_public/src/mir/visit.rs +++ b/compiler/rustc_public/src/mir/visit.rs @@ -369,6 +369,7 @@ macro_rules! make_mir_visitor { AssertMessage::ResumedAfterReturn(_) | AssertMessage::ResumedAfterPanic(_) | AssertMessage::NullPointerDereference + | AssertMessage::NullReferenceConstructed | AssertMessage::ResumedAfterDrop(_) => { //nothing to visit } diff --git a/compiler/rustc_public/src/unstable/convert/stable/mir.rs b/compiler/rustc_public/src/unstable/convert/stable/mir.rs index d126304af8cde..a19dadcb20b94 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/mir.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/mir.rs @@ -559,6 +559,9 @@ impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> { } } AssertKind::NullPointerDereference => crate::mir::AssertMessage::NullPointerDereference, + AssertKind::NullReferenceConstructed => { + crate::mir::AssertMessage::NullReferenceConstructed + } AssertKind::InvalidEnumConstruction(source) => { crate::mir::AssertMessage::InvalidEnumConstruction(source.stable(tables, cx)) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 71eae246ebaff..055b3739c2818 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1535,6 +1535,7 @@ symbols! { panic_misaligned_pointer_dereference, panic_nounwind, panic_null_pointer_dereference, + panic_null_reference_constructed, panic_runtime, panic_str_2015, panic_unwind, diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 3609dd1fe2e02..46790b620127b 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -305,6 +305,19 @@ fn panic_null_pointer_dereference() -> ! { ) } +#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] +#[cfg_attr(panic = "immediate-abort", inline)] +#[track_caller] +#[lang = "panic_null_reference_constructed"] // needed by codegen for panic on null reference formation +#[rustc_nounwind] // `CheckNull` MIR pass requires this function to never unwind +fn panic_null_reference_constructed() -> ! { + if cfg!(panic = "immediate-abort") { + super::intrinsics::abort() + } + + panic_nounwind_fmt(format_args!("null reference produced"), /* force_no_backtrace */ false) +} + #[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))] #[cfg_attr(panic = "immediate-abort", inline)] #[track_caller] diff --git a/tests/ui/mir/null/borrowed_mut_null.rs b/tests/ui/mir/null/borrowed_mut_null.rs index a4660f4bf5734..1f3adede80465 100644 --- a/tests/ui/mir/null/borrowed_mut_null.rs +++ b/tests/ui/mir/null/borrowed_mut_null.rs @@ -1,6 +1,6 @@ //@ run-crash //@ compile-flags: -C debug-assertions -//@ error-pattern: null pointer dereference occurred +//@ error-pattern: null reference produced fn main() { let ptr: *mut u32 = std::ptr::null_mut(); diff --git a/tests/ui/mir/null/borrowed_null.rs b/tests/ui/mir/null/borrowed_null.rs index 2a50058a48202..6857d2e64c660 100644 --- a/tests/ui/mir/null/borrowed_null.rs +++ b/tests/ui/mir/null/borrowed_null.rs @@ -1,6 +1,6 @@ //@ run-crash //@ compile-flags: -C debug-assertions -//@ error-pattern: null pointer dereference occurred +//@ error-pattern: null reference produced fn main() { let ptr: *const u32 = std::ptr::null(); diff --git a/tests/ui/mir/null/borrowed_null_zst.rs b/tests/ui/mir/null/borrowed_null_zst.rs index 106fa00b1db5a..9a31f4c94f96a 100644 --- a/tests/ui/mir/null/borrowed_null_zst.rs +++ b/tests/ui/mir/null/borrowed_null_zst.rs @@ -1,6 +1,6 @@ //@ run-crash //@ compile-flags: -C debug-assertions -//@ error-pattern: null pointer dereference occurred +//@ error-pattern: null reference produced fn main() { let ptr: *const () = std::ptr::null(); From dabab4f18e4411fc724971ccd33af0a8f8d0316e Mon Sep 17 00:00:00 2001 From: zedddie Date: Sun, 5 Jul 2026 20:49:31 +0200 Subject: [PATCH 06/16] move batch --- .../self-type-projection-dyn-coerce.rs} | 0 .../issue-29857.rs => coherence/error-type-coherence-no-ice.rs} | 0 tests/ui/{issues/issue-3220.rs => drop/drop-value-by-method.rs} | 0 .../issue-30380.rs => drop/panic-in-drop-during-assignment.rs} | 0 .../ui/{issues/issue-33241.rs => dst/unsized-tuple-trait-tail.rs} | 0 .../lifetime-errors/elision-error-omits-lifetimeless-params.rs} | 0 .../elision-error-omits-lifetimeless-params.stderr} | 0 .../unused/for-loop-no-spurious-unused-variable-lint.rs} | 0 .../no-field-error-in-macro-expansion-for-generic.rs} | 0 .../no-field-error-in-macro-expansion-for-generic.stderr} | 0 .../{issues/issue-31776.rs => privacy/required-pub-in-blocks.rs} | 0 .../issue-3149.rs => resolve/generic-struct-and-fn-share-name.rs} | 0 .../issue-30589.rs => resolve/impl-trait-for-undeclared-type.rs} | 0 .../impl-trait-for-undeclared-type.stderr} | 0 .../error-reporting/incomplete-partial-ord-impl.rs} | 0 .../error-reporting/incomplete-partial-ord-impl.stderr} | 0 .../parenthesized-type-params-in-paths.rs} | 0 .../parenthesized-type-params-in-paths.stderr} | 0 18 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/issue-33461.rs => associated-types/self-type-projection-dyn-coerce.rs} (100%) rename tests/ui/{issues/issue-29857.rs => coherence/error-type-coherence-no-ice.rs} (100%) rename tests/ui/{issues/issue-3220.rs => drop/drop-value-by-method.rs} (100%) rename tests/ui/{issues/issue-30380.rs => drop/panic-in-drop-during-assignment.rs} (100%) rename tests/ui/{issues/issue-33241.rs => dst/unsized-tuple-trait-tail.rs} (100%) rename tests/ui/{issues/issue-30255.rs => lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.rs} (100%) rename tests/ui/{issues/issue-30255.stderr => lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.stderr} (100%) rename tests/ui/{issues/issue-30371.rs => lint/unused/for-loop-no-spurious-unused-variable-lint.rs} (100%) rename tests/ui/{issues/issue-31011.rs => macros/no-field-error-in-macro-expansion-for-generic.rs} (100%) rename tests/ui/{issues/issue-31011.stderr => macros/no-field-error-in-macro-expansion-for-generic.stderr} (100%) rename tests/ui/{issues/issue-31776.rs => privacy/required-pub-in-blocks.rs} (100%) rename tests/ui/{issues/issue-3149.rs => resolve/generic-struct-and-fn-share-name.rs} (100%) rename tests/ui/{issues/issue-30589.rs => resolve/impl-trait-for-undeclared-type.rs} (100%) rename tests/ui/{issues/issue-30589.stderr => resolve/impl-trait-for-undeclared-type.stderr} (100%) rename tests/ui/{issues/issue-3344.rs => traits/error-reporting/incomplete-partial-ord-impl.rs} (100%) rename tests/ui/{issues/issue-3344.stderr => traits/error-reporting/incomplete-partial-ord-impl.stderr} (100%) rename tests/ui/{issues/issue-32995.rs => typeck/parenthesized-type-params-in-paths.rs} (100%) rename tests/ui/{issues/issue-32995.stderr => typeck/parenthesized-type-params-in-paths.stderr} (100%) diff --git a/tests/ui/issues/issue-33461.rs b/tests/ui/associated-types/self-type-projection-dyn-coerce.rs similarity index 100% rename from tests/ui/issues/issue-33461.rs rename to tests/ui/associated-types/self-type-projection-dyn-coerce.rs diff --git a/tests/ui/issues/issue-29857.rs b/tests/ui/coherence/error-type-coherence-no-ice.rs similarity index 100% rename from tests/ui/issues/issue-29857.rs rename to tests/ui/coherence/error-type-coherence-no-ice.rs diff --git a/tests/ui/issues/issue-3220.rs b/tests/ui/drop/drop-value-by-method.rs similarity index 100% rename from tests/ui/issues/issue-3220.rs rename to tests/ui/drop/drop-value-by-method.rs diff --git a/tests/ui/issues/issue-30380.rs b/tests/ui/drop/panic-in-drop-during-assignment.rs similarity index 100% rename from tests/ui/issues/issue-30380.rs rename to tests/ui/drop/panic-in-drop-during-assignment.rs diff --git a/tests/ui/issues/issue-33241.rs b/tests/ui/dst/unsized-tuple-trait-tail.rs similarity index 100% rename from tests/ui/issues/issue-33241.rs rename to tests/ui/dst/unsized-tuple-trait-tail.rs diff --git a/tests/ui/issues/issue-30255.rs b/tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.rs similarity index 100% rename from tests/ui/issues/issue-30255.rs rename to tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.rs diff --git a/tests/ui/issues/issue-30255.stderr b/tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.stderr similarity index 100% rename from tests/ui/issues/issue-30255.stderr rename to tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.stderr diff --git a/tests/ui/issues/issue-30371.rs b/tests/ui/lint/unused/for-loop-no-spurious-unused-variable-lint.rs similarity index 100% rename from tests/ui/issues/issue-30371.rs rename to tests/ui/lint/unused/for-loop-no-spurious-unused-variable-lint.rs diff --git a/tests/ui/issues/issue-31011.rs b/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.rs similarity index 100% rename from tests/ui/issues/issue-31011.rs rename to tests/ui/macros/no-field-error-in-macro-expansion-for-generic.rs diff --git a/tests/ui/issues/issue-31011.stderr b/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.stderr similarity index 100% rename from tests/ui/issues/issue-31011.stderr rename to tests/ui/macros/no-field-error-in-macro-expansion-for-generic.stderr diff --git a/tests/ui/issues/issue-31776.rs b/tests/ui/privacy/required-pub-in-blocks.rs similarity index 100% rename from tests/ui/issues/issue-31776.rs rename to tests/ui/privacy/required-pub-in-blocks.rs diff --git a/tests/ui/issues/issue-3149.rs b/tests/ui/resolve/generic-struct-and-fn-share-name.rs similarity index 100% rename from tests/ui/issues/issue-3149.rs rename to tests/ui/resolve/generic-struct-and-fn-share-name.rs diff --git a/tests/ui/issues/issue-30589.rs b/tests/ui/resolve/impl-trait-for-undeclared-type.rs similarity index 100% rename from tests/ui/issues/issue-30589.rs rename to tests/ui/resolve/impl-trait-for-undeclared-type.rs diff --git a/tests/ui/issues/issue-30589.stderr b/tests/ui/resolve/impl-trait-for-undeclared-type.stderr similarity index 100% rename from tests/ui/issues/issue-30589.stderr rename to tests/ui/resolve/impl-trait-for-undeclared-type.stderr diff --git a/tests/ui/issues/issue-3344.rs b/tests/ui/traits/error-reporting/incomplete-partial-ord-impl.rs similarity index 100% rename from tests/ui/issues/issue-3344.rs rename to tests/ui/traits/error-reporting/incomplete-partial-ord-impl.rs diff --git a/tests/ui/issues/issue-3344.stderr b/tests/ui/traits/error-reporting/incomplete-partial-ord-impl.stderr similarity index 100% rename from tests/ui/issues/issue-3344.stderr rename to tests/ui/traits/error-reporting/incomplete-partial-ord-impl.stderr diff --git a/tests/ui/issues/issue-32995.rs b/tests/ui/typeck/parenthesized-type-params-in-paths.rs similarity index 100% rename from tests/ui/issues/issue-32995.rs rename to tests/ui/typeck/parenthesized-type-params-in-paths.rs diff --git a/tests/ui/issues/issue-32995.stderr b/tests/ui/typeck/parenthesized-type-params-in-paths.stderr similarity index 100% rename from tests/ui/issues/issue-32995.stderr rename to tests/ui/typeck/parenthesized-type-params-in-paths.stderr From 082ff2fc2040f041cab0d8ba65dfc6d278ea103b Mon Sep 17 00:00:00 2001 From: zedddie Date: Sun, 5 Jul 2026 20:49:49 +0200 Subject: [PATCH 07/16] bless batch --- .../self-type-projection-dyn-coerce.rs | 4 +++ .../coherence/error-type-coherence-no-ice.rs | 2 ++ tests/ui/drop/drop-value-by-method.rs | 7 ++++ .../drop/panic-in-drop-during-assignment.rs | 5 +-- tests/ui/dst/unsized-tuple-trait-tail.rs | 3 ++ ...elision-error-omits-lifetimeless-params.rs | 6 ++-- ...ion-error-omits-lifetimeless-params.stderr | 6 ++-- ...r-loop-no-spurious-unused-variable-lint.rs | 3 ++ ...ld-error-in-macro-expansion-for-generic.rs | 2 ++ ...rror-in-macro-expansion-for-generic.stderr | 2 +- tests/ui/privacy/required-pub-in-blocks.rs | 4 ++- .../generic-struct-and-fn-share-name.rs | 3 ++ .../resolve/impl-trait-for-undeclared-type.rs | 3 ++ .../impl-trait-for-undeclared-type.stderr | 2 +- .../incomplete-partial-ord-impl.rs | 3 ++ .../incomplete-partial-ord-impl.stderr | 2 +- ...renthesized-type-parameters-error-32995.rs | 14 -------- ...hesized-type-parameters-error-32995.stderr | 21 ------------ .../parenthesized-type-params-in-paths.rs | 17 ++++++++++ .../parenthesized-type-params-in-paths.stderr | 34 ++++++++++++++----- 20 files changed, 88 insertions(+), 55 deletions(-) delete mode 100644 tests/ui/typeck/parenthesized-type-parameters-error-32995.rs delete mode 100644 tests/ui/typeck/parenthesized-type-parameters-error-32995.stderr diff --git a/tests/ui/associated-types/self-type-projection-dyn-coerce.rs b/tests/ui/associated-types/self-type-projection-dyn-coerce.rs index 0de05c6687afb..81353e781d090 100644 --- a/tests/ui/associated-types/self-type-projection-dyn-coerce.rs +++ b/tests/ui/associated-types/self-type-projection-dyn-coerce.rs @@ -1,4 +1,8 @@ +//! Regression test for . +//! This used to ICE as coercion to trait object didn't normalize associated +//! type. //@ run-pass + #![allow(unused_variables)] use std::marker::PhantomData; diff --git a/tests/ui/coherence/error-type-coherence-no-ice.rs b/tests/ui/coherence/error-type-coherence-no-ice.rs index 9d4c9b2935a28..c66a02aa6cd27 100644 --- a/tests/ui/coherence/error-type-coherence-no-ice.rs +++ b/tests/ui/coherence/error-type-coherence-no-ice.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! This used to ICE during coherence on Error types. //@ check-pass use std::marker::PhantomData; diff --git a/tests/ui/drop/drop-value-by-method.rs b/tests/ui/drop/drop-value-by-method.rs index 2f5ca82b2fac3..78c22d30e72b5 100644 --- a/tests/ui/drop/drop-value-by-method.rs +++ b/tests/ui/drop/drop-value-by-method.rs @@ -1,4 +1,11 @@ +//! Regression test for . +//! Initially a pretty-printer bug, which omitted parentheses around `move` +//! keyword in lhs (`(move z).f()`), now this behaviour is untestable as +//! plain `move` outside a closure doesn't exist. +//! +//! Now appears to test that drop works correctly when value is moved by method. //@ run-pass + #![allow(dead_code)] #![allow(non_camel_case_types)] diff --git a/tests/ui/drop/panic-in-drop-during-assignment.rs b/tests/ui/drop/panic-in-drop-during-assignment.rs index 49fce3d150cd7..d13bc022e7c8f 100644 --- a/tests/ui/drop/panic-in-drop-during-assignment.rs +++ b/tests/ui/drop/panic-in-drop-during-assignment.rs @@ -1,5 +1,6 @@ -// check that panics in destructors during assignment do not leave -// destroyed values lying around for other destructors to observe. +//! Regression test for . +//! Check that panics in destructors during assignment do not leave +//! destroyed values lying around for other destructors to observe. //@ run-fail //@ error-pattern:panicking destructors ftw! diff --git a/tests/ui/dst/unsized-tuple-trait-tail.rs b/tests/ui/dst/unsized-tuple-trait-tail.rs index 1c497876a90da..1fc66b8a866b9 100644 --- a/tests/ui/dst/unsized-tuple-trait-tail.rs +++ b/tests/ui/dst/unsized-tuple-trait-tail.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! This used to fire LLVM assertion, and later on ICE because of +//! `t` type size incosistency between LLVM and rustc. //@ check-pass use std::fmt; diff --git a/tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.rs b/tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.rs index 6970a122b7144..246082f54f08e 100644 --- a/tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.rs +++ b/tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.rs @@ -1,6 +1,6 @@ -// -// Test that lifetime elision error messages correctly omit parameters -// with no elided lifetimes +//! Regression test for . +//! Test that lifetime elision error messages correctly omit parameters +//! with no elided lifetimes. struct S<'a> { field: &'a i32, diff --git a/tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.stderr b/tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.stderr index adb721a1cbaf1..fbabc9a56074b 100644 --- a/tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.stderr +++ b/tests/ui/lifetimes/lifetime-errors/elision-error-omits-lifetimeless-params.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifier - --> $DIR/issue-30255.rs:9:24 + --> $DIR/elision-error-omits-lifetimeless-params.rs:9:24 | LL | fn f(a: &S, b: i32) -> &i32 { | -- ^ expected named lifetime parameter @@ -11,7 +11,7 @@ LL | fn f<'a>(a: &'a S<'a>, b: i32) -> &'a i32 { | ++++ ++ ++++ ++ error[E0106]: missing lifetime specifier - --> $DIR/issue-30255.rs:14:34 + --> $DIR/elision-error-omits-lifetimeless-params.rs:14:34 | LL | fn g(a: &S, b: bool, c: &i32) -> &i32 { | -- ---- ^ expected named lifetime parameter @@ -23,7 +23,7 @@ LL | fn g<'a>(a: &'a S<'a>, b: bool, c: &'a i32) -> &'a i32 { | ++++ ++ ++++ ++ ++ error[E0106]: missing lifetime specifier - --> $DIR/issue-30255.rs:19:44 + --> $DIR/elision-error-omits-lifetimeless-params.rs:19:44 | LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 { | ----- -- ---- ^ expected named lifetime parameter diff --git a/tests/ui/lint/unused/for-loop-no-spurious-unused-variable-lint.rs b/tests/ui/lint/unused/for-loop-no-spurious-unused-variable-lint.rs index d3ac5fd9587d1..6b266d7cc522c 100644 --- a/tests/ui/lint/unused/for-loop-no-spurious-unused-variable-lint.rs +++ b/tests/ui/lint/unused/for-loop-no-spurious-unused-variable-lint.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! This used to emit unused variable warning. //@ run-pass + #![allow(unreachable_code)] #![allow(for_loops_over_fallibles)] #![deny(unused_variables)] diff --git a/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.rs b/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.rs index 078d8b2d50fc7..ed4a9a08c222c 100644 --- a/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.rs +++ b/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.rs @@ -1,3 +1,5 @@ +//! Regression test for . +//! This macro used to ICE with unprintable span. //@ dont-require-annotations: NOTE macro_rules! log { diff --git a/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.stderr b/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.stderr index 701141ee4406c..600a569a84ce2 100644 --- a/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.stderr +++ b/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.stderr @@ -1,5 +1,5 @@ error[E0609]: no field `trace` on type `&T` - --> $DIR/issue-31011.rs:5:17 + --> $DIR/no-field-error-in-macro-expansion-for-generic.rs:7:17 | LL | if $ctx.trace { | ^^^^^ unknown field diff --git a/tests/ui/privacy/required-pub-in-blocks.rs b/tests/ui/privacy/required-pub-in-blocks.rs index abe6c7ecee58e..aaf273641c917 100644 --- a/tests/ui/privacy/required-pub-in-blocks.rs +++ b/tests/ui/privacy/required-pub-in-blocks.rs @@ -1,8 +1,10 @@ +//! Regression test for . +//! Various scenarios in which `pub` is required in blocks. //@ run-pass + #![allow(dead_code)] #![allow(unused_variables)] #![allow(non_local_definitions)] -// Various scenarios in which `pub` is required in blocks struct S; diff --git a/tests/ui/resolve/generic-struct-and-fn-share-name.rs b/tests/ui/resolve/generic-struct-and-fn-share-name.rs index 76744213d51da..7bcb64ffbc80d 100644 --- a/tests/ui/resolve/generic-struct-and-fn-share-name.rs +++ b/tests/ui/resolve/generic-struct-and-fn-share-name.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! This wrongly emitted a duplicate definition of value error. //@ check-pass + #![allow(dead_code)] #![allow(non_snake_case)] diff --git a/tests/ui/resolve/impl-trait-for-undeclared-type.rs b/tests/ui/resolve/impl-trait-for-undeclared-type.rs index 94eb5839958af..e023020cd71b6 100644 --- a/tests/ui/resolve/impl-trait-for-undeclared-type.rs +++ b/tests/ui/resolve/impl-trait-for-undeclared-type.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! This used to ICE when coherence encountered an erroneous type. + use std::fmt; impl fmt::Display for DecoderError { //~ ERROR cannot find type `DecoderError` in this scope diff --git a/tests/ui/resolve/impl-trait-for-undeclared-type.stderr b/tests/ui/resolve/impl-trait-for-undeclared-type.stderr index 43d80896edf8c..72319af983dc6 100644 --- a/tests/ui/resolve/impl-trait-for-undeclared-type.stderr +++ b/tests/ui/resolve/impl-trait-for-undeclared-type.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find type `DecoderError` in this scope - --> $DIR/issue-30589.rs:3:23 + --> $DIR/impl-trait-for-undeclared-type.rs:6:23 | LL | impl fmt::Display for DecoderError { | ^^^^^^^^^^^^ not found in this scope diff --git a/tests/ui/traits/error-reporting/incomplete-partial-ord-impl.rs b/tests/ui/traits/error-reporting/incomplete-partial-ord-impl.rs index de764b3d075d3..f4e0ced169972 100644 --- a/tests/ui/traits/error-reporting/incomplete-partial-ord-impl.rs +++ b/tests/ui/traits/error-reporting/incomplete-partial-ord-impl.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Unimplemented items in impl caused ICE. + #[derive(PartialEq)] struct Thing(usize); impl PartialOrd for Thing { //~ ERROR not all trait items implemented, missing: `partial_cmp` diff --git a/tests/ui/traits/error-reporting/incomplete-partial-ord-impl.stderr b/tests/ui/traits/error-reporting/incomplete-partial-ord-impl.stderr index eac8f10fcc164..cae998c653397 100644 --- a/tests/ui/traits/error-reporting/incomplete-partial-ord-impl.stderr +++ b/tests/ui/traits/error-reporting/incomplete-partial-ord-impl.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `partial_cmp` - --> $DIR/issue-3344.rs:3:1 + --> $DIR/incomplete-partial-ord-impl.rs:6:1 | LL | impl PartialOrd for Thing { | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `partial_cmp` in implementation diff --git a/tests/ui/typeck/parenthesized-type-parameters-error-32995.rs b/tests/ui/typeck/parenthesized-type-parameters-error-32995.rs deleted file mode 100644 index e0c2ab5f303a3..0000000000000 --- a/tests/ui/typeck/parenthesized-type-parameters-error-32995.rs +++ /dev/null @@ -1,14 +0,0 @@ -// https://github.com/rust-lang/rust/issues/32995 -fn main() { - { fn f() {} } - //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait - - { fn f() -> impl ::std::marker()::Send { } } - //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait -} - -#[derive(Clone)] -struct X; - -impl ::std::marker()::Copy for X {} -//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait diff --git a/tests/ui/typeck/parenthesized-type-parameters-error-32995.stderr b/tests/ui/typeck/parenthesized-type-parameters-error-32995.stderr deleted file mode 100644 index 590cdcdb43bc3..0000000000000 --- a/tests/ui/typeck/parenthesized-type-parameters-error-32995.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/parenthesized-type-parameters-error-32995.rs:3:22 - | -LL | { fn f() {} } - | ^^^^^^^^ only `Fn` traits may use parentheses - -error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/parenthesized-type-parameters-error-32995.rs:6:29 - | -LL | { fn f() -> impl ::std::marker()::Send { } } - | ^^^^^^^^ only `Fn` traits may use parentheses - -error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/parenthesized-type-parameters-error-32995.rs:13:13 - | -LL | impl ::std::marker()::Copy for X {} - | ^^^^^^^^ only `Fn` traits may use parentheses - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0214`. diff --git a/tests/ui/typeck/parenthesized-type-params-in-paths.rs b/tests/ui/typeck/parenthesized-type-params-in-paths.rs index 0d07a76939f2a..85321cc305384 100644 --- a/tests/ui/typeck/parenthesized-type-params-in-paths.rs +++ b/tests/ui/typeck/parenthesized-type-params-in-paths.rs @@ -1,3 +1,7 @@ +//! Regression test for . +//! Test parenthesized type params syntax is forbidden for non `Fn` trait, +//! and can't be used in paths. + fn main() { let x: usize() = 1; //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait @@ -16,8 +20,21 @@ fn main() { let o : Box = Box::new(1); //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + + { fn f() {} } + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + + { fn f() -> impl ::std::marker()::Send { } } + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + } +#[derive(Clone)] +struct X; + +impl ::std::marker()::Copy for X {} +//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + fn foo() { let d : X() = Default::default(); //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait diff --git a/tests/ui/typeck/parenthesized-type-params-in-paths.stderr b/tests/ui/typeck/parenthesized-type-params-in-paths.stderr index b868011b99b24..7a8a4afbfd113 100644 --- a/tests/ui/typeck/parenthesized-type-params-in-paths.stderr +++ b/tests/ui/typeck/parenthesized-type-params-in-paths.stderr @@ -1,45 +1,63 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:2:12 + --> $DIR/parenthesized-type-params-in-paths.rs:6:12 | LL | let x: usize() = 1; | ^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:5:19 + --> $DIR/parenthesized-type-params-in-paths.rs:9:19 | LL | let b: ::std::boxed()::Box<_> = Box::new(1); | ^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:8:20 + --> $DIR/parenthesized-type-params-in-paths.rs:12:20 | LL | let p = ::std::str::()::from_utf8(b"foo").unwrap(); | ^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:11:25 + --> $DIR/parenthesized-type-params-in-paths.rs:15:25 | LL | let p = ::std::str::from_utf8::()(b"foo").unwrap(); | ^^^^^^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:14:29 + --> $DIR/parenthesized-type-params-in-paths.rs:18:29 | LL | let o : Box = Box::new(1); | ^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:17:35 + --> $DIR/parenthesized-type-params-in-paths.rs:21:35 | LL | let o : Box = Box::new(1); | ^^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-32995.rs:22:13 + --> $DIR/parenthesized-type-params-in-paths.rs:24:22 + | +LL | { fn f() {} } + | ^^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/parenthesized-type-params-in-paths.rs:27:29 + | +LL | { fn f() -> impl ::std::marker()::Send { } } + | ^^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/parenthesized-type-params-in-paths.rs:35:13 + | +LL | impl ::std::marker()::Copy for X {} + | ^^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/parenthesized-type-params-in-paths.rs:39:13 | LL | let d : X() = Default::default(); | ^^^ only `Fn` traits may use parentheses -error: aborting due to 7 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0214`. From a99be5a85997d0296b30ceb4c5b5b75ad7872a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Mon, 6 Jul 2026 11:23:47 +0200 Subject: [PATCH 08/16] update perf --- src/tools/rustc-perf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustc-perf b/src/tools/rustc-perf index c0301bc44d175..dec492af8eb74 160000 --- a/src/tools/rustc-perf +++ b/src/tools/rustc-perf @@ -1 +1 @@ -Subproject commit c0301bc44d175b9b2c5442b25049475c39d7700c +Subproject commit dec492af8eb74903879bd356648fc42d7aaf8555 From a6bd564d1ff0902271689417269fd7a3f07a9525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Mon, 22 Jun 2026 17:21:28 +0200 Subject: [PATCH 09/16] allow new licenses for rustc_perf --- src/tools/tidy/src/deps.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 9ad70538d1956..ebe3c04ea4cc4 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -244,6 +244,10 @@ const EXCEPTIONS_RUSTC_PERF: ExceptionList = &[ // tidy-alphabetical-start ("inferno", "CDDL-1.0"), ("option-ext", "MPL-2.0"), + ("terminfo", "WTFPL"), + ("wasite", "Apache-2.0 OR BSL-1.0 OR MIT"), + ("wezterm-bidi", "MIT AND Unicode-DFS-2016"), + ("whoami", "Apache-2.0 OR BSL-1.0 OR MIT"), // tidy-alphabetical-end ]; From 40114416f843186b008d65f92da937533766291b Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas Chirananthavat)" Date: Mon, 6 Jul 2026 21:06:09 +0700 Subject: [PATCH 10/16] Delete `impl_def_id` field from `ImplHeader` This field is not used anywhere. --- compiler/rustc_trait_selection/src/traits/coherence.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 41fff770374fb..1dd3019f68dfc 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -44,7 +44,6 @@ use crate::traits::{ /// bounds / where-clauses). #[derive(Clone, Debug, TypeFoldable, TypeVisitable)] pub struct ImplHeader<'tcx> { - pub impl_def_id: DefId, pub impl_args: ty::GenericArgsRef<'tcx>, pub self_ty: Ty<'tcx>, pub trait_ref: Option>, @@ -207,7 +206,6 @@ fn fresh_impl_header<'tcx>( let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); ImplHeader { - impl_def_id, impl_args, self_ty: tcx.type_of(impl_def_id).instantiate(tcx, impl_args).skip_norm_wip(), trait_ref: is_of_trait From 2740e11e40070d8baff1d1d8161839cbca5ba3d5 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 6 Jul 2026 16:09:25 +0100 Subject: [PATCH 11/16] Create simple non ICE-ing path for new trait solver --- .../src/traits/auto_trait.rs | 83 +++++++++++++++++++ src/librustdoc/clean/auto_trait.rs | 1 + 2 files changed, 84 insertions(+) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 469eb4fc0630c..d6736852e088b 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -33,6 +33,7 @@ pub struct RegionDeps<'tcx> { } pub enum AutoTraitResult { + NoImpl, ExplicitImpl, PositiveImpl(A), NegativeImpl, @@ -80,6 +81,15 @@ impl<'tcx> AutoTraitFinder<'tcx> { ) -> AutoTraitResult { let tcx = self.tcx; + if tcx.next_trait_solver_globally() { + return self.find_auto_trait_generics_next_solver( + ty, + typing_env, + trait_did, + auto_trait_callback, + ); + } + let trait_ref = ty::TraitRef::new(tcx, trait_did, [ty]); let (infcx, orig_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); @@ -175,6 +185,79 @@ impl<'tcx> AutoTraitFinder<'tcx> { AutoTraitResult::PositiveImpl(auto_trait_callback(info)) } + fn find_auto_trait_generics_next_solver( + &self, + ty: Ty<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + trait_did: DefId, + mut auto_trait_callback: impl FnMut(AutoTraitInfo<'tcx>) -> A, + ) -> AutoTraitResult { + // When the new solver is enabled globally we keep things deliberately + // simple. The precise auto-trait synthesis depends on old-solver + // internals, so here we only synthesize a simple field-based auto-trait + // impl for ADTs. + // + // If the self type is not an ADT we return `NoImpl` instead of trying + // to do anything fancy. To decide whether to emit a negative impl, we + // replace the ADT's generic arguments with inference variables and + // check whether the auto trait can hold. A true error from that probe + // becomes a `NegativeImpl`, otherwise we continue on to emit the + // imprecise field-based impl. + // + // This keeps rustdoc from ICE-ing while `-Znext-solver=globally` is + // used for testing, even if the generated synthetic impls are less + // precise. + let tcx = self.tcx; + let ty::Adt(adt_def, args) = *ty.kind() else { + return AutoTraitResult::NoImpl; + }; + + let mut disqualifying_impl = None; + tcx.for_each_relevant_impl(trait_did, ty, |impl_def_id| { + disqualifying_impl = Some(impl_def_id); + }); + if let Some(impl_def_id) = disqualifying_impl { + debug!( + "find_auto_trait_generics({:?}): possible manual impl {impl_def_id:?} found, bailing", + ty::TraitRef::new(tcx, trait_did, [ty]), + ); + return AutoTraitResult::ExplicitImpl; + } + + let (infcx, orig_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); + let field_clauses = adt_def + .all_fields() + .map(|field| field.ty(tcx, args).skip_norm_wip()) + .filter(|field_ty| field_ty.has_non_region_param()) + .map(|field_ty| { + ty::TraitPredicate { + trait_ref: ty::TraitRef::new(tcx, trait_did, [field_ty]), + polarity: ty::PredicatePolarity::Positive, + } + .upcast(tcx) + }) + .collect::>>(); + let full_user_env = ty::ParamEnv::new( + tcx.mk_clauses_from_iter(orig_env.caller_bounds().iter().chain(field_clauses)), + ); + + let fresh_args = infcx.fresh_args_for_item(DUMMY_SP, adt_def.did()); + let fresh_ty = ty::EarlyBinder::bind(tcx, ty).instantiate(tcx, fresh_args).skip_norm_wip(); + let ocx = ObligationCtxt::new(&infcx); + ocx.register_bound(ObligationCause::dummy(), orig_env, fresh_ty, trait_did); + let errors = ocx.try_evaluate_obligations(); + if !errors.is_empty() { + return AutoTraitResult::NegativeImpl; + } + + let info = AutoTraitInfo { + full_user_env, + region_data: RegionConstraintData::default(), + vid_to_region: FxIndexMap::default(), + }; + AutoTraitResult::PositiveImpl(auto_trait_callback(info)) + } + /// The core logic responsible for computing the bounds for our synthesized impl. /// /// To calculate the bounds, we call `SelectionContext.select` in a loop. Like diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index fe7e12cf1dc80..3ed08f4c5e933 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -110,6 +110,7 @@ fn synthesize_auto_trait_impl<'tcx>( (generics, ty::ImplPolarity::Negative) } + auto_trait::AutoTraitResult::NoImpl => return None, auto_trait::AutoTraitResult::ExplicitImpl => return None, }; From 84aa27d8958f75200408eb66355b69bfcad549e0 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 6 Jul 2026 16:11:03 +0100 Subject: [PATCH 12/16] Tests for `find_auto_trait_generics_next_solver` path --- .../synthetic_auto/next-solver-ambiguity.rs | 7 +++++++ .../synthetic_auto/next-solver-possible-impl.rs | 12 ++++++++++++ .../next-solver-globally.rs | 16 ++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 tests/rustdoc-html/synthetic_auto/next-solver-ambiguity.rs create mode 100644 tests/rustdoc-html/synthetic_auto/next-solver-possible-impl.rs create mode 100644 tests/rustdoc-ui/synthetic-auto-trait-impls/next-solver-globally.rs diff --git a/tests/rustdoc-html/synthetic_auto/next-solver-ambiguity.rs b/tests/rustdoc-html/synthetic_auto/next-solver-ambiguity.rs new file mode 100644 index 0000000000000..b48be49b29761 --- /dev/null +++ b/tests/rustdoc-html/synthetic_auto/next-solver-ambiguity.rs @@ -0,0 +1,7 @@ +//@ compile-flags: -Znext-solver=globally +//@ edition: 2021 +#![crate_name = "foo"] + +//@ has 'foo/struct.Foo.html' +//@ has - '//h3[@class="code-header"]' "impl<'a, 'b, T> Send for Foo<'a, 'b, T>where &'a T: Send, &'b T: Send" +pub struct Foo<'a, 'b, T: 'a + 'b>(&'a T, &'b T); diff --git a/tests/rustdoc-html/synthetic_auto/next-solver-possible-impl.rs b/tests/rustdoc-html/synthetic_auto/next-solver-possible-impl.rs new file mode 100644 index 0000000000000..145174a1961a5 --- /dev/null +++ b/tests/rustdoc-html/synthetic_auto/next-solver-possible-impl.rs @@ -0,0 +1,12 @@ +//@ compile-flags: -Znext-solver=globally + +#![feature(auto_traits)] +#![crate_name = "foo"] + +pub auto trait Marker {} + +//@ has 'foo/struct.MyType.html' +//@ !has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 'Marker for MyType' +pub struct MyType(T); + +impl Marker for MyType {} diff --git a/tests/rustdoc-ui/synthetic-auto-trait-impls/next-solver-globally.rs b/tests/rustdoc-ui/synthetic-auto-trait-impls/next-solver-globally.rs new file mode 100644 index 0000000000000..73dff8abf3a69 --- /dev/null +++ b/tests/rustdoc-ui/synthetic-auto-trait-impls/next-solver-globally.rs @@ -0,0 +1,16 @@ +// We used to ICE here while trying to synthesize auto trait impls +// with the next trait solver enabled globally. +//@ check-pass +//@ compile-flags: -Znext-solver=globally + +#![feature(const_default)] +#![feature(const_trait_impl)] + +pub struct Inner(T); + +pub struct Outer(Inner); + +impl Unpin for Inner +where + T: const std::default::Default, +{} From 35cbff9a4c977663e71a8d6a0c010a8a3faccdea Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Mon, 6 Jul 2026 17:18:27 +0200 Subject: [PATCH 13/16] rewrite `Align::max_for_target` in a more obvious way --- compiler/rustc_abi/src/lib.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index e86c7f15e9679..c2069432e6f8e 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -36,6 +36,7 @@ even other Rust compilers, such as rust-analyzer! */ +use std::cmp::min; use std::fmt; #[cfg(feature = "nightly")] use std::iter::Step; @@ -1060,14 +1061,8 @@ impl Align { /// Either `1 << (pointer_bits - 1)` or [`Align::MAX`], whichever is smaller. #[inline] pub fn max_for_target(tdl: &TargetDataLayout) -> Align { - let pointer_bits = tdl.pointer_size().bits(); - if let Ok(pointer_bits) = u8::try_from(pointer_bits) - && pointer_bits <= Align::MAX.pow2 - { - Align { pow2: pointer_bits - 1 } - } else { - Align::MAX - } + let pointer_bits = u8::try_from(tdl.pointer_size().bits()).unwrap(); + min(Align { pow2: pointer_bits - 1 }, Align::MAX) } #[inline] From 690ae7deeb3f3244b26176610f65dd42d29afafe Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Tue, 30 Jun 2026 18:46:22 +0200 Subject: [PATCH 14/16] borrowck: Inline free_region_constraint_info() to simplify the code For reference, the helper function was introduced in 2a3969a3f7077. In any case, the code becomes simpler if we remove it now, so let's remove it. --- .../src/diagnostics/explain_borrow.rs | 31 ++++++------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 1e336f1e4509d..15e3cf28aac32 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -12,7 +12,7 @@ use rustc_middle::mir::{ Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind, }; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{DesugaringKind, Span, kw, sym}; use rustc_trait_selection::error_reporting::traits::FindExprBySpan; use rustc_trait_selection::error_reporting::traits::call_kind::CallKind; @@ -574,24 +574,6 @@ fn suggest_rewrite_if_let( } impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { - fn free_region_constraint_info( - &self, - borrow_region: RegionVid, - outlived_region: RegionVid, - ) -> (ConstraintCategory<'tcx>, bool, Span, Option, Vec>) - { - let (blame_constraint, path) = self.regioncx.best_blame_constraint( - borrow_region, - NllRegionVariableOrigin::FreeRegion, - outlived_region, - ); - let BlameConstraint { category, from_closure, span, .. } = blame_constraint; - - let outlived_fr_name = self.give_region_a_name(outlived_region); - - (category, from_closure, span, outlived_fr_name, path) - } - /// Returns structured explanation for *why* the borrow contains the /// point from `location`. This is key for the "3-point errors" /// [described in the NLL RFC][d]. @@ -707,9 +689,14 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { // Here, under NLL: no cause was found. Under polonius: no cause was found, or a // boring local was found, which we ignore like NLLs do to match its diagnostics. if let Some(region) = self.regioncx.to_error_region_vid(borrow_region_vid) { - let (category, from_closure, span, region_name, path) = - self.free_region_constraint_info(borrow_region_vid, region); - if let Some(region_name) = region_name { + let (blame_constraint, path) = self.regioncx.best_blame_constraint( + borrow_region_vid, + NllRegionVariableOrigin::FreeRegion, + region, + ); + let BlameConstraint { category, from_closure, span, .. } = blame_constraint; + + if let Some(region_name) = self.give_region_a_name(region) { let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref()); BorrowExplanation::MustBeValidFor { category, From 81a18e7a94b380bae6363479174ee82b6a66745f Mon Sep 17 00:00:00 2001 From: Cypher Date: Wed, 1 Jul 2026 23:07:55 -0400 Subject: [PATCH 15/16] document blocking guarantees for `std::sync` --- library/std/src/sync/mod.rs | 8 ++++++++ library/std/src/sync/mpmc/mod.rs | 19 +++++++++++++++---- library/std/src/sync/mpsc.rs | 19 ++++++++++++++----- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 439b5b09a5ac0..5ac0ff2da9af5 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -164,6 +164,14 @@ //! [`Once`]: crate::sync::Once //! [`OnceLock`]: crate::sync::OnceLock //! [`RwLock`]: crate::sync::RwLock +//! +//! ## Blocking guarantees +//! +//! Methods that are documented not to block will never block for an unbounded length of time. +//! That is, they may internally block through platform primitives but still "behave" like they are non-blocking. This difference is invisible to most programs. +//! +//! This is only of note to platforms which disallow blocking, such as multithreaded WebAssembly on the main thread. +//! None of the implementations in `std::sync` are guaranteed to be (or remain) non-blocking in this regard. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs index a687f39431697..a34eabbccb1fc 100644 --- a/library/std/src/sync/mpmc/mod.rs +++ b/library/std/src/sync/mpmc/mod.rs @@ -15,8 +15,9 @@ //! //! 1. An asynchronous, infinitely buffered channel. The [`channel`] function //! will return a `(Sender, Receiver)` tuple where all sends will be -//! **asynchronous** (they never block). The channel conceptually has an -//! infinite buffer. +//! **asynchronous** (they never block for space to become available; see +//! [`std::sync`] for precise guarantees on blocking.) The channel +//! conceptually has an infinite buffer. //! //! 2. A synchronous, bounded channel. The [`sync_channel`] function will //! return a `(Sender, Receiver)` tuple where the storage for pending @@ -26,6 +27,7 @@ //! channel where each sender atomically hands off a message to a receiver. //! //! [`send`]: Sender::send +//! [`std::sync`]: ../index.html#blocking-guarantees //! //! ## Disconnection //! @@ -374,6 +376,11 @@ impl Sender { /// If called on a zero-capacity channel, this method will wait for a receive /// operation to appear on the other side of the channel. /// + /// If called on an unbounded channel, this method will never block in order to wait for space to + /// become available. (See [`std::sync`] for precise guarantees on blocking.) + /// + /// [`std::sync`]: ../index.html#blocking-guarantees + /// /// # Examples /// /// ``` @@ -770,9 +777,11 @@ pub struct Iter<'a, T: 'a> { /// if the corresponding channel has hung up. /// /// This iterator will never block the caller in order to wait for data to -/// become available. Instead, it will return [`None`]. +/// become available. Instead, it will return [`None`]. (See [`std::sync`] for +/// precise guarantees on blocking.) /// /// [`try_iter`]: Receiver::try_iter +/// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples /// @@ -917,7 +926,8 @@ impl Receiver { /// /// This method will never block the caller in order to wait for data to /// become available. Instead, this will always return immediately with a - /// possible option of pending data on the channel. + /// possible option of pending data on the channel. (See [`std::sync`] for precise + /// guarantees on blocking.) /// /// If called on a zero-capacity channel, this method will receive a message only if there /// happens to be a send operation on the other side of the channel at the same time. @@ -929,6 +939,7 @@ impl Receiver { /// (one for disconnection, one for an empty buffer). /// /// [`recv`]: Self::recv + /// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples /// diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs index b74f84ff465c0..ad74ac2248878 100644 --- a/library/std/src/sync/mpsc.rs +++ b/library/std/src/sync/mpsc.rs @@ -15,8 +15,9 @@ //! //! 1. An asynchronous, infinitely buffered channel. The [`channel`] function //! will return a `(Sender, Receiver)` tuple where all sends will be -//! **asynchronous** (they never block). The channel conceptually has an -//! infinite buffer. +//! **asynchronous** (they never block for space to become available; see +//! [`std::sync`] for precise guarantees on blocking.) The channel +//! conceptually has an infinite buffer. //! //! 2. A synchronous, bounded channel. The [`sync_channel`] function will //! return a `(SyncSender, Receiver)` tuple where the storage for pending @@ -26,6 +27,7 @@ //! channel where each sender atomically hands off a message to a receiver. //! //! [`send`]: Sender::send +//! [`std::sync`]: ../index.html#blocking-guarantees //! //! ## Disconnection //! @@ -228,9 +230,11 @@ pub struct Iter<'a, T: 'a> { /// if the corresponding channel has hung up. /// /// This iterator will never block the caller in order to wait for data to -/// become available. Instead, it will return [`None`]. +/// become available. Instead, it will return [`None`]. (See [`std::sync`] for +/// precise guarantees on blocking.) /// /// [`try_iter`]: Receiver::try_iter +/// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples /// @@ -590,7 +594,10 @@ impl Sender { /// will be received. It is possible for the corresponding receiver to /// hang up immediately after this function returns [`Ok`]. /// - /// This method will never block the current thread. + /// This method will never block the caller in order to wait for space to + /// become available. (See [`std::sync`] for precise guarantees on blocking.) + /// + /// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples /// @@ -798,7 +805,8 @@ impl Receiver { /// /// This method will never block the caller in order to wait for data to /// become available. Instead, this will always return immediately with a - /// possible option of pending data on the channel. + /// possible option of pending data on the channel. (See [`std::sync`] for + /// precise guarantees on blocking.) /// /// This is useful for a flavor of "optimistic check" before deciding to /// block on a receiver. @@ -807,6 +815,7 @@ impl Receiver { /// (one for disconnection, one for an empty buffer). /// /// [`recv`]: Self::recv + /// [`std::sync`]: ../index.html#blocking-guarantees /// /// # Examples /// From 1b75a0a63ce1a50ce954cba812830e8b90704423 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 6 Jul 2026 12:54:09 -0700 Subject: [PATCH 16/16] Update mdbook to 0.5.4 Changelog: https://github.com/rust-lang/mdBook/blob/master/CHANGELOG.md#mdbook-054 --- src/tools/rustbook/Cargo.lock | 59 ++++++++++++++++++++--------------- src/tools/rustbook/Cargo.toml | 2 +- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index 36b3705027aa1..76f39ae18b763 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -78,9 +78,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "autocfg" @@ -149,7 +149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ "find-msvc-tools", - "shlex", + "shlex 1.3.0", ] [[package]] @@ -545,9 +545,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "6.4.1" +version = "6.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d43ccdfe15a81ab0a8af639e90254227c9a46afd9c5f5b6ec7efaa345c4b0f00" +checksum = "f26569a2763497b7bd3fbd19374b774ea6038c5293678771259cd534d49740ff" dependencies = [ "derive_builder", "log", @@ -762,9 +762,9 @@ dependencies = [ [[package]] name = "mdbook-core" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fc1c4da7fd9e2e412f3891428f9468fab890ed159723ed0892bb85a049ac1c1" +checksum = "8725b7f8e94a5c40a00c907e4006301ba2fc06722de489a0cb19db1823fdf200" dependencies = [ "anyhow", "regex", @@ -776,9 +776,9 @@ dependencies = [ [[package]] name = "mdbook-driver" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2068566fc3c100cfd19f4a13e4e0eb4fdcd2250cfd0aa633ec25102b1c98d53e" +checksum = "485612ee2a91847760e742ce441673fa127306a43f44e666796f7d99d4592272" dependencies = [ "anyhow", "indexmap", @@ -791,7 +791,7 @@ dependencies = [ "regex", "serde", "serde_json", - "shlex", + "shlex 2.0.1", "tempfile", "toml 1.1.2+spec-1.1.0", "topological-sort", @@ -800,9 +800,9 @@ dependencies = [ [[package]] name = "mdbook-html" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85ed2140251689f928615f0a5615413eb072eb28e003d179257aa4f034c95513" +checksum = "8d25933e4d7cbaa342db9ab9f414c2a09b1c59becb63ad344520370d822ab28a" dependencies = [ "anyhow", "ego-tree", @@ -846,9 +846,9 @@ dependencies = [ [[package]] name = "mdbook-markdown" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb3ca9eadf02ce206118a0b9c264718723d669b110c01a720fa9a0786f30642" +checksum = "9ca553aa4330b15fa2c706aef373bc714cc719513d1da73c17be3dba208b9aab" dependencies = [ "pulldown-cmark 0.13.4", "regex", @@ -857,9 +857,9 @@ dependencies = [ [[package]] name = "mdbook-preprocessor" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eff7b4afaafd664a649a03b8891ad8199aef359a35b911ad6c31acab38ed209" +checksum = "f8e75b08763e31982701d5b2680124bd4bd9bed4a4e1b5a499381320ccae199f" dependencies = [ "anyhow", "mdbook-core", @@ -869,9 +869,9 @@ dependencies = [ [[package]] name = "mdbook-renderer" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e607259410d53aa5cdaf5b6c1c6b3fd61f2e0f0523ebf457d34cd4f0b71e2a88" +checksum = "75d378308f820f05c6c89e4ec552a3c64a0cc10ccab7dcc93a2baa3bc714ea1b" dependencies = [ "anyhow", "mdbook-core", @@ -900,9 +900,9 @@ dependencies = [ [[package]] name = "mdbook-summary" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae8a734e5e35b0bc145b46d01fd27e266ba647dcdb9b8c907cb6a29eca9122b" +checksum = "2453622fa7236139365a9acd20314ab859ff747d57ba36ff0d476b64adc75cf8" dependencies = [ "anyhow", "mdbook-core", @@ -930,9 +930,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "miniz_oxide" @@ -1230,9 +1230,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.3" +version = "1.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" dependencies = [ "aho-corasick", "memchr", @@ -1253,9 +1253,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "rustbook" @@ -1345,6 +1345,7 @@ version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ + "indexmap", "itoa", "memchr", "serde", @@ -1407,6 +1408,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + [[package]] name = "simd-adler32" version = "0.3.9" diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index f981d09fbbee1..1551a289549a3 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" [dependencies] clap = { version = "4.0.32", features = ["cargo"] } -mdbook-driver = { version = "0.5.3", features = ["search"] } +mdbook-driver = { version = "0.5.4", features = ["search"] } mdbook-i18n-helpers = "0.4.0" mdbook-spec = { path = "../../doc/reference/tools/mdbook-spec" } mdbook-trpl = { path = "../../doc/book/packages/mdbook-trpl" }