From cfa655ad24dbe4cd823f699ef9b52b5e95a0db43 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Wed, 30 Sep 2026 13:22:11 -0400 Subject: [PATCH 01/12] tests: accept noundef in a couple more places LLVM 24 got smarter and is able to mark some more things noundef, which showed up in some of our test checks. --- tests/codegen-llvm/sparc-struct-abi.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/codegen-llvm/sparc-struct-abi.rs b/tests/codegen-llvm/sparc-struct-abi.rs index 6a31fe0d37f15..f79814e4bb4f1 100644 --- a/tests/codegen-llvm/sparc-struct-abi.rs +++ b/tests/codegen-llvm/sparc-struct-abi.rs @@ -29,7 +29,7 @@ pub struct BoolFloat { f: f32, } -// CHECK: define inreg { i32, float } @structboolfloat() +// CHECK: define inreg{{( noundef)?}} { i32, float } @structboolfloat() // CHECK-NEXT: start: // CHECK-NEXT: ret { i32, float } { i32 16777216, float {{0x40091EB860000000|3.140000e\+00}} } #[no_mangle] @@ -48,7 +48,7 @@ pub struct ShortDouble { d: f64, } -// CHECK: define { i64, double } @structshortdouble() +// CHECK: define{{( noundef)?}} { i64, double } @structshortdouble() // CHECK-NEXT: start: // CHECK-NEXT: ret { i64, double } { i64 34621422135410688, double 3.140000e+00 } #[no_mangle] @@ -88,7 +88,7 @@ pub struct NestedStructs { b: FloatFloat, } -// CHECK: define inreg { float, float, float, float } @structnestestructs() +// CHECK: define inreg{{( noundef)?}} { float, float, float, float } @structnestestructs() // CHECK-NEXT: start: // CHECK-NEXT: ret { float, float, float, float } { float {{0x3FB99999A0000000|1.000000e-01}}, float {{0x3FF19999A0000000|1.100000e\+00}}, float {{0x40019999A0000000|2.200000e\+00}}, float {{0x400A666660000000|3.300000e\+00}} } #[no_mangle] From e75273b0247664eded2f7bd482c76dc0adaaf149 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Fri, 2 Oct 2026 08:44:29 +0200 Subject: [PATCH 02/12] core: io: clean `unused_variables` lint under `no_io_statics` When building `core` with `--cfg no_io_statics`, the compiler warns: error: unused variable: `f` --> .../library/core/src/io/error/os_functions.rs:9:36 | 9 | pub(super) unsafe fn set_functions(f: &'static OsFunctions) { | ^ help: if this is intentional, prefix it with an underscore: `_f` | = note: `-D unused-variables` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(unused_variables)]` Thus clean it up. Signed-off-by: Miguel Ojeda --- library/core/src/io/error/os_functions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/io/error/os_functions.rs b/library/core/src/io/error/os_functions.rs index b34b7c7dc7926..fcc549f0fb643 100644 --- a/library/core/src/io/error/os_functions.rs +++ b/library/core/src/io/error/os_functions.rs @@ -6,7 +6,7 @@ use crate::fmt; /// The provided reference must point to data that is entirely constant; it must /// not be created during runtime. #[inline] -pub(super) unsafe fn set_functions(f: &'static OsFunctions) { +pub(super) unsafe fn set_functions(_f: &'static OsFunctions) { // FIXME: externally implementable items may allow for weak linkage, allowing // these methods to be overridden even when atomic pointers are not supported. } From c52c1942446fd4f1b513dbf8689aa028c0a79607 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Fri, 21 Aug 2026 15:25:42 -0700 Subject: [PATCH 03/12] always use next-solver in coherence --- .../src/coherence/orphan.rs | 2 +- .../src/traits/coherence.rs | 215 +++++------------- 2 files changed, 54 insertions(+), 163 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 496994096d69b..d2c3a08eb714f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -321,7 +321,7 @@ fn orphan_check<'tcx>( // (1) Instantiate all generic params with fresh inference vars. let infcx = tcx .infer_ctxt() - .with_next_trait_solver(tcx.next_trait_solver_in_coherence()) + .with_next_trait_solver(true) .enable_next_solver_overflow_fcw(false) .build(TypingMode::Coherence); let cause = traits::ObligationCause::dummy(); diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index d3c118b33e8ce..df21f682d7380 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -33,8 +33,7 @@ use crate::solve::{SolverDelegate, deeply_normalize_for_diagnostics, inspect}; use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{ - FulfillmentErrorCode, NormalizeExt, Obligation, ObligationCause, PredicateObligation, - SelectionContext, SkipLeakCheck, util, + FulfillmentErrorCode, Obligation, ObligationCause, PredicateObligation, SkipLeakCheck, util, }; /// The "header" of an impl is everything outside the body: a Self type, a trait @@ -79,21 +78,6 @@ pub(crate) fn suggest_increasing_recursion_limit<'tcx>( suggest_new_overflow_limit(tcx, err); } -#[derive(Debug, Clone, Copy)] -enum TrackAmbiguityCauses { - Yes, - No, -} - -impl TrackAmbiguityCauses { - fn is_yes(self) -> bool { - match self { - TrackAmbiguityCauses::Yes => true, - TrackAmbiguityCauses::No => false, - } - } -} - /// If there are types that satisfy both impls, returns `Some` /// with a suitably-freshened `ImplHeader` with those types /// instantiated. Otherwise, returns `None`. @@ -157,42 +141,7 @@ fn overlapping_impls( overlap_mode: OverlapMode, is_of_trait: bool, ) -> Option> { - if tcx.next_trait_solver_in_coherence() { - overlap( - tcx, - TrackAmbiguityCauses::Yes, - skip_leak_check, - impl1_def_id, - impl2_def_id, - overlap_mode, - is_of_trait, - ) - } else { - let _overlap_with_bad_diagnostics = overlap( - tcx, - TrackAmbiguityCauses::No, - skip_leak_check, - impl1_def_id, - impl2_def_id, - overlap_mode, - is_of_trait, - )?; - - // In the case where we detect an error, run the check again, but - // this time tracking intercrate ambiguity causes for better - // diagnostics. (These take time and can lead to false errors.) - let overlap = overlap( - tcx, - TrackAmbiguityCauses::Yes, - skip_leak_check, - impl1_def_id, - impl2_def_id, - overlap_mode, - is_of_trait, - ) - .unwrap(); - Some(overlap) - } + overlap(tcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode, is_of_trait) } fn fresh_impl_header<'tcx>( @@ -217,27 +166,11 @@ fn fresh_impl_header<'tcx>( } } -fn fresh_impl_header_normalized<'tcx>( - infcx: &InferCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - impl_def_id: DefId, - is_of_trait: bool, -) -> ImplHeader<'tcx> { - let header = fresh_impl_header(infcx, impl_def_id, is_of_trait); - - let InferOk { value: mut header, obligations } = - infcx.at(&ObligationCause::dummy(), param_env).normalize(Unnormalized::new_wip(header)); - - header.predicates.extend(obligations.into_iter().map(|o| o.predicate)); - header -} - /// Can both impl `a` and impl `b` be satisfied by a common type (including /// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls. #[instrument(level = "debug", skip(tcx))] fn overlap<'tcx>( tcx: TyCtxt<'tcx>, - track_ambiguity_causes: TrackAmbiguityCauses, skip_leak_check: SkipLeakCheck, impl1_def_id: DefId, impl2_def_id: DefId, @@ -260,13 +193,9 @@ fn overlap<'tcx>( let infcx = tcx .infer_ctxt() .skip_leak_check(skip_leak_check.is_yes()) - .with_next_trait_solver(tcx.next_trait_solver_in_coherence()) + .with_next_trait_solver(true) .enable_next_solver_overflow_fcw(false) .build(TypingMode::Coherence); - let selcx = &mut SelectionContext::new(&infcx); - if track_ambiguity_causes.is_yes() { - selcx.enable_tracking_intercrate_ambiguity_causes(); - } // For the purposes of this check, we don't bring any placeholder // types into scope; instead, we replace the generic types with @@ -274,21 +203,12 @@ fn overlap<'tcx>( // empty environment. let param_env = ty::ParamEnv::empty(); - let impl1_header = if tcx.next_trait_solver_in_coherence() { - fresh_impl_header(selcx.infcx, impl1_def_id, is_of_trait) - } else { - fresh_impl_header_normalized(selcx.infcx, param_env, impl1_def_id, is_of_trait) - }; - let impl2_header = if tcx.next_trait_solver_in_coherence() { - fresh_impl_header(selcx.infcx, impl2_def_id, is_of_trait) - } else { - fresh_impl_header_normalized(selcx.infcx, param_env, impl2_def_id, is_of_trait) - }; + let impl1_header = fresh_impl_header(&infcx, impl1_def_id, is_of_trait); + let impl2_header = fresh_impl_header(&infcx, impl2_def_id, is_of_trait); // Equate the headers to find their intersection (the general type, with infer vars, // that may apply both impls). - let mut obligations = - equate_impl_headers(selcx.infcx, param_env, &impl1_header, &impl2_header)?; + let mut obligations = equate_impl_headers(&infcx, param_env, &impl1_header, &impl2_header)?; debug!("overlap: unification check succeeded"); obligations.extend( @@ -299,7 +219,7 @@ fn overlap<'tcx>( let mut overflowing_predicates = Vec::new(); if overlap_mode.use_implicit_negative() { - match impl_intersection_has_impossible_obligation(selcx, &obligations) { + match impl_intersection_has_impossible_obligation(&infcx, &obligations) { IntersectionHasImpossibleObligations::Yes => return None, IntersectionHasImpossibleObligations::No { overflowing_predicates: p } => { overflowing_predicates = p @@ -316,10 +236,8 @@ fn overlap<'tcx>( let intercrate_ambiguity_causes = if !overlap_mode.use_implicit_negative() { Default::default() - } else if infcx.next_trait_solver() { - compute_intercrate_ambiguity_causes(&infcx, &obligations) } else { - selcx.take_intercrate_ambiguity_causes() + compute_intercrate_ambiguity_causes(&infcx, &obligations) }; debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); @@ -335,9 +253,7 @@ fn overlap<'tcx>( let mut impl_header = infcx.deeply_resolve_ignoring_regions(impl1_header); // Deeply normalize the impl header for diagnostics, ignoring any errors if this fails. - if infcx.next_trait_solver() { - impl_header = deeply_normalize_for_diagnostics(&infcx, param_env, impl_header); - } + impl_header = deeply_normalize_for_diagnostics(&infcx, param_env, impl_header); Some(OverlapResult { impl_header, @@ -375,7 +291,7 @@ fn equate_impl_headers<'tcx>( enum IntersectionHasImpossibleObligations<'tcx> { Yes, No { - /// With `-Znext-solver=coherence`, some obligations may + /// With the next solver, some obligations may /// fail if only the user increased the recursion limit. /// /// We return those obligations here and mention them in the @@ -402,78 +318,53 @@ enum IntersectionHasImpossibleObligations<'tcx> { /// of the two impls above to be empty. /// /// Importantly, this works even if there isn't a `impl !Error for MyLocalType`. -#[instrument(level = "debug", skip(selcx), ret)] -fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, +#[instrument(level = "debug", skip(infcx), ret)] +fn impl_intersection_has_impossible_obligation<'a, 'tcx>( + infcx: &InferCtxt<'tcx>, obligations: &'a [PredicateObligation<'tcx>], ) -> IntersectionHasImpossibleObligations<'tcx> { - let infcx = selcx.infcx; - - if infcx.next_trait_solver() { - // A fast path optimization, try evaluating all goals with - // a very low recursion depth and bail if any of them don't - // hold. - if !obligations.iter().all(|o| { - <&SolverDelegate<'tcx>>::from(infcx) - .root_goal_may_hold_with_depth(8, Goal::new(infcx.tcx, o.param_env, o.predicate)) - }) { - return IntersectionHasImpossibleObligations::Yes; - } - - let ocx = ObligationCtxt::new(infcx); - ocx.register_obligations(obligations.iter().cloned()); - let hard_errors = ocx.try_evaluate_obligations(); - if let TraitErrors::HasErrors(hard_errors) = hard_errors { - assert!( - hard_errors.iter().all(|e| e.is_true_error()), - "should not have detected ambiguity during first pass" - ); - return IntersectionHasImpossibleObligations::Yes; - } + // A fast path optimization, try evaluating all goals with + // a very low recursion depth and bail if any of them don't + // hold. + if !obligations.iter().all(|o| { + <&SolverDelegate<'tcx>>::from(infcx) + .root_goal_may_hold_with_depth(8, Goal::new(infcx.tcx, o.param_env, o.predicate)) + }) { + return IntersectionHasImpossibleObligations::Yes; + } - // Make a new `ObligationCtxt` and re-prove the ambiguities with a richer - // `FulfillmentError`. This is so that we can detect overflowing obligations - // without needing to run the `BestObligation` visitor on true errors. - let ambiguities = ocx.into_pending_obligations(); - let ocx = ObligationCtxt::new_with_diagnostics(infcx); - ocx.register_obligations(ambiguities); - let errors_and_ambiguities = ocx.evaluate_obligations_error_on_ambiguity(); - // We only care about the obligations that are *definitely* true errors. - // Ambiguities do not prove the disjointness of two impls. - let (errors, ambiguities): (Vec<_>, Vec<_>) = - errors_and_ambiguities.into_iter().partition(|error| error.is_true_error()); - assert!(errors.is_empty(), "should not have ambiguities during second pass"); - - IntersectionHasImpossibleObligations::No { - overflowing_predicates: ambiguities - .into_iter() - .filter(|error| { - matches!(error.code, FulfillmentErrorCode::Ambiguity { overflow: Some(true) }) - }) - .map(|e| infcx.deeply_resolve_ignoring_regions(e.obligation.predicate)) - .collect(), - } - } else { - for obligation in obligations { - // We use `evaluate_root_obligation` to correctly track intercrate - // ambiguity clauses. - let evaluation_result = selcx.evaluate_root_obligation(obligation); - - match evaluation_result { - Ok(result) => { - if !result.may_apply() { - return IntersectionHasImpossibleObligations::Yes; - } - } - // If overflow occurs, we need to conservatively treat the goal as possibly holding, - // since there can be instantiations of this goal that don't overflow and result in - // success. While this isn't much of a problem in the old solver, since we treat overflow - // fatally, this still can be encountered: . - Err(_overflow) => {} - } - } + let ocx = ObligationCtxt::new(infcx); + ocx.register_obligations(obligations.iter().cloned()); + let hard_errors = ocx.try_evaluate_obligations(); + if let TraitErrors::HasErrors(hard_errors) = hard_errors { + assert!( + hard_errors.iter().all(|e| e.is_true_error()), + "should not have detected ambiguity during first pass" + ); + return IntersectionHasImpossibleObligations::Yes; + } - IntersectionHasImpossibleObligations::No { overflowing_predicates: Vec::new() } + // Make a new `ObligationCtxt` and re-prove the ambiguities with a richer + // `FulfillmentError`. This is so that we can detect overflowing obligations + // without needing to run the `BestObligation` visitor on true errors. + let ambiguities = ocx.into_pending_obligations(); + let ocx = ObligationCtxt::new_with_diagnostics(infcx); + ocx.register_obligations(ambiguities); + let errors_and_ambiguities = ocx.evaluate_obligations_error_on_ambiguity(); + // We only care about the obligations that are *definitely* true errors. + // Ambiguities do not prove the disjointness of two impls. + let (errors, ambiguities): (Vec<_>, Vec<_>) = + errors_and_ambiguities.into_iter().partition(|error| error.is_true_error()); + assert!(errors.is_empty(), "should not have ambiguities during second pass"); + + IntersectionHasImpossibleObligations::No { + overflowing_predicates: ambiguities + .into_iter() + .filter(|error| { + matches!(error.code, FulfillmentErrorCode::Ambiguity { overflow: Some(true) }) + }) + .map(|e| infcx.deeply_resolve_ignoring_regions(e.obligation.predicate)) + .collect(), } } From 52aa198e14414e7cf23d59aea71b6d9cb1f617c1 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Fri, 21 Aug 2026 15:26:21 -0700 Subject: [PATCH 04/12] make `coherence` and `globally` the only `NextSolverConfig` options --- compiler/rustc_ast_passes/src/feature_gate.rs | 5 ++-- compiler/rustc_interface/src/tests.rs | 16 ++-------- compiler/rustc_middle/src/ty/context.rs | 8 ++--- compiler/rustc_session/src/config.rs | 29 ++++++++++--------- compiler/rustc_session/src/options.rs | 9 +++--- 5 files changed, 28 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 45fa1863e715f..1176d6e1398f0 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -5,6 +5,7 @@ use rustc_attr_parsing::AttributeParser; use rustc_errors::msg; use rustc_feature::{DependentFeature, Features}; use rustc_session::Session; +use rustc_session::config::NextSolverConfig; use rustc_session::diagnostics::{feature_err, feature_warn}; use rustc_span::{Span, Spanned, sym}; @@ -698,7 +699,7 @@ fn check_dependent_features(sess: &Session, features: &Features) { } fn warn_next_solver_and_gce(sess: &Session, features: &Features) { - if !sess.opts.unstable_opts.next_solver.globally { + if sess.opts.unstable_opts.next_solver != NextSolverConfig::Globally { return; } @@ -716,7 +717,7 @@ fn warn_next_solver_and_gce(sess: &Session, features: &Features) { } fn check_features_requiring_new_solver(sess: &Session, features: &Features) { - if sess.opts.unstable_opts.next_solver.globally { + if sess.opts.unstable_opts.next_solver == NextSolverConfig::Globally { return; } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 2f9489ac67ad4..8c241f51dfbfd 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -859,7 +859,7 @@ fn test_unstable_options_tracking_hash() { // tidy-alphabetical-end // FIXME(#160895): We don't test this when the next-solver is enabled by default. if option_env!("CFG_DEFAULT_NEXT_SOLVER_GLOBALLY").is_none() { - tracked!(next_solver, NextSolverConfig { coherence: true, globally: true }); + tracked!(next_solver, NextSolverConfig::Globally); } // tidy-alphabetical-start tracked!(no_generate_arange_section, true); @@ -948,7 +948,7 @@ fn test_edition_parsing() { #[test] fn test_assumptions_on_binders_enables_next_solver_globally() { - let globally = NextSolverConfig { coherence: true, globally: true }; + let globally = NextSolverConfig::Globally; let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); // `-Zassumptions-on-binders` alone enables the next solver globally. @@ -957,18 +957,6 @@ fn test_assumptions_on_binders_enables_next_solver_globally() { assert!(opts.unstable_opts.assumptions_on_binders); assert_eq!(opts.unstable_opts.next_solver, globally); - // Flag order must not matter when both `-Zassumptions-on-binders` and `-Znext-solver` - // are present. - for args in [ - ["-Zassumptions-on-binders".to_string(), "-Znext-solver=coherence".to_string()], - ["-Znext-solver=coherence".to_string(), "-Zassumptions-on-binders".to_string()], - ] { - let matches = optgroups().parse(&args).unwrap(); - let opts = build_session_options(&mut early_dcx, &matches); - assert!(opts.unstable_opts.assumptions_on_binders); - assert_eq!(opts.unstable_opts.next_solver, globally); - } - // `-Zassumptions-on-binders` overrides `-Znext-solver=no` regardless of order, since // the assumptions implementation requires the next solver. This also emits an early // warning (covered by the UI test `next-solver-no-overridden`). diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index be4679320e9c7..03a8664ab0a02 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -40,6 +40,7 @@ use rustc_index::IndexVec; use rustc_lint_defs::Lint; use rustc_lint_defs::builtin::UNUSED_FEATURES; use rustc_macros::Diagnostic; +use rustc_session::config::NextSolverConfig; use rustc_session::{IncrCompSession, Session}; use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, bug, kw, sym}; @@ -2823,11 +2824,8 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn next_trait_solver_globally(self) -> bool { - self.sess.opts.unstable_opts.next_solver.globally && !self.features().generic_const_exprs() - } - - pub fn next_trait_solver_in_coherence(self) -> bool { - self.sess.opts.unstable_opts.next_solver.coherence + self.sess.opts.unstable_opts.next_solver == NextSolverConfig::Globally + && !self.features().generic_const_exprs() } pub fn disable_trait_solver_fast_paths(self) -> bool { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 798dcaf969965..8c9cfd76e08fb 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1037,13 +1037,11 @@ impl ExternEntry { } } +/// Where the new trait solver should be enabled only in coherence or everywhere. #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct NextSolverConfig { - /// Whether the new trait solver should be enabled in coherence. - pub coherence: bool = true, - /// Whether the new trait solver should be enabled everywhere. - /// This is only `true` if `coherence` is also enabled. - pub globally: bool = false, +pub enum NextSolverConfig { + Coherence, + Globally, } // FIXME(#160895): Using -Znext-solver as default on nightly @@ -1051,9 +1049,9 @@ pub struct NextSolverConfig { impl Default for NextSolverConfig { fn default() -> Self { if option_env!("CFG_DEFAULT_NEXT_SOLVER_GLOBALLY").is_some() { - Self { coherence: true, globally: true } + Self::Globally } else { - Self { coherence: true, globally: false } + Self::Coherence } } } @@ -2715,17 +2713,22 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M // `-Zassumptions-on-binders` requires the next trait solver globally. Normalize after // parsing so the effective config is independent of flag order and so consumers that - // read `next_solver.globally` directly (e.g. feature-gate checks) see the right value. + // read `next_solver` directly (e.g. feature-gate checks) see the right value. if unstable_opts.assumptions_on_binders { - // `NextSolverConfig::default()` has `coherence: true`; the only way `coherence` is - // false here is an explicit `-Znext-solver=no`. - if !unstable_opts.next_solver.coherence { + // Only warn when the last `-Znext-solver` given has a value that doesn't enable + // the solver globally, so a later `-Znext-solver=globally` overrides an earlier one. + let no_next_solver = matches + .opt_strs("Z") + .iter() + .rfind(|arg| arg.starts_with("next-solver")) + .is_some_and(|arg| *arg == "next-solver=no" || *arg == "next-solver=coherence"); + if no_next_solver { early_dcx.early_warn( "-Zassumptions-on-binders unconditionally enables the next trait solver; \ `-Znext-solver=no` is ignored", ); } - unstable_opts.next_solver = NextSolverConfig { coherence: true, globally: true }; + unstable_opts.next_solver = NextSolverConfig::Globally; } if unstable_opts.staticlib_hide_internal_symbols && !crate_types.contains(&CrateType::StaticLib) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 4c153cbb8c031..9a3e74c28348d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -877,7 +877,7 @@ mod desc { pub(crate) const parse_unpretty: &str = "`string` or `string=string`"; pub(crate) const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; pub(crate) const parse_next_solver_config: &str = - "either `globally` (when used without an argument), `coherence` (default) or `no`"; + "either `globally` (when used without an argument), or `coherence` (default)"; pub(crate) const parse_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted"; pub(crate) const parse_linker_plugin_lto: &str = @@ -1795,13 +1795,12 @@ pub mod parse { pub(crate) fn parse_next_solver_config(slot: &mut NextSolverConfig, v: Option<&str>) -> bool { if let Some(config) = v { *slot = match config { - "no" => NextSolverConfig { coherence: false, globally: false }, - "coherence" => NextSolverConfig { coherence: true, globally: false }, - "globally" => NextSolverConfig { coherence: true, globally: true }, + "no" | "coherence" => NextSolverConfig::Coherence, + "globally" => NextSolverConfig::Globally, _ => return false, }; } else { - *slot = NextSolverConfig { coherence: true, globally: true }; + *slot = NextSolverConfig::Globally; } true From 71e0361cd9bb8a9c47a06612f96e009eb6f4dbc5 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Fri, 21 Aug 2026 15:27:01 -0700 Subject: [PATCH 05/12] remove intercrate ambiguity cause tracking from the old solver --- compiler/rustc_trait_selection/src/lib.rs | 1 - .../src/traits/select/mod.rs | 91 ------------------- 2 files changed, 92 deletions(-) diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 9a3948f0ac440..9364d65968dd0 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -11,7 +11,6 @@ //! This API is completely unstable and subject to change. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(associated_type_defaults)] #![feature(default_field_values)] #![feature(deref_patterns)] diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 4846d75339cd6..f92d0b3720b12 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -35,7 +35,6 @@ use tracing::{debug, instrument, trace}; use self::EvaluationResult::*; use self::SelectionCandidate::*; -use super::coherence::{self, Conflict}; use super::project::ProjectionTermObligation; use super::util::closure_trait_ref_and_return_type; use super::{ @@ -106,14 +105,6 @@ pub struct SelectionContext<'cx, 'tcx> { /// require themselves. freshener: TypeFreshener<'cx, 'tcx>, - /// If `intercrate` is set, we remember predicates which were - /// considered ambiguous because of impls potentially added in other crates. - /// This is used in coherence to give improved diagnostics. - /// We don't do his until we detect a coherence error because it can - /// lead to false overflow results (#47139) and because always - /// computing it may negatively impact performance. - intercrate_ambiguity_causes: Option>>, - /// The mode that trait queries run in, which informs our error handling /// policy. In essence, canonicalized queries need their errors propagated /// rather than immediately reported because we do not have accurate spans. @@ -191,7 +182,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { SelectionContext { infcx, freshener: TypeFreshener::new(infcx), - intercrate_ambiguity_causes: None, query_mode: TraitQueryMode::Standard, } } @@ -208,27 +198,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { SelectionContext { query_mode, ..SelectionContext::new(infcx) } } - /// Enables tracking of intercrate ambiguity causes. See - /// the documentation of [`Self::intercrate_ambiguity_causes`] for more. - pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) { - assert!(self.typing_mode().is_coherence()); - assert!(self.intercrate_ambiguity_causes.is_none()); - - self.intercrate_ambiguity_causes = Some(FxIndexSet::default()); - debug!("selcx: enable_tracking_intercrate_ambiguity_causes"); - } - - /// Gets the intercrate ambiguity causes collected since tracking - /// was enabled and disables tracking at the same time. If - /// tracking is not enabled, just returns an empty vector. - pub fn take_intercrate_ambiguity_causes( - &mut self, - ) -> FxIndexSet> { - assert!(self.typing_mode().is_coherence()); - - self.intercrate_ambiguity_causes.take().unwrap_or_default() - } - pub fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -363,42 +332,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, stack: &TraitObligationStack<'o, 'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { - if let Err(conflict) = self.is_knowable(stack) { - debug!("coherence stage: not knowable"); - if self.intercrate_ambiguity_causes.is_some() { - debug!("evaluate_stack: intercrate_ambiguity_causes is some"); - // Heuristics: show the diagnostics when there are no candidates in crate. - if let Ok(candidate_set) = self.assemble_candidates(stack) { - let mut no_candidates_apply = true; - - for c in candidate_set.vec.iter() { - if self.evaluate_candidate(stack, c)?.may_apply() { - no_candidates_apply = false; - break; - } - } - - if !candidate_set.ambiguous && no_candidates_apply { - let trait_ref = self.infcx.deeply_resolve_ignoring_regions( - stack.obligation.predicate.skip_binder().trait_ref, - ); - if !trait_ref.references_error() { - let self_ty = trait_ref.self_ty(); - let self_ty = self_ty.has_concrete_skeleton().then(|| self_ty); - let cause = if let Conflict::Upstream = conflict { - IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_ref, self_ty } - } else { - IntercrateAmbiguityCause::DownstreamCrate { trait_ref, self_ty } - }; - debug!(?cause, "evaluate_stack: pushing cause"); - self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause); - } - } - } - } - return Ok(None); - } - let candidate_set = self.assemble_candidates(stack)?; if candidate_set.ambiguous { @@ -1432,30 +1365,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates } - fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> { - let obligation = &stack.obligation; - match self.typing_mode() { - TypingMode::Coherence => {} - TypingMode::Typeck { .. } - | TypingMode::PostTypeckUntilBorrowck { .. } - | TypingMode::Reflection - | TypingMode::PostBorrowck { .. } - | TypingMode::PostAnalysis - | TypingMode::Codegen => return Ok(()), - } - - debug!("is_knowable()"); - - let predicate = self.infcx.deeply_resolve_ignoring_regions(obligation.predicate); - - // Okay to skip binder because of the nature of the - // trait-ref-is-knowable check, which does not care about - // bound regions. - let trait_ref = predicate.skip_binder().trait_ref; - - coherence::trait_ref_is_knowable(self.infcx, trait_ref, |ty| Ok::<_, !>(ty)).into_ok() - } - /// Returns `true` if the global caches can be used. fn can_use_global_caches( &self, From 097e1f3733f8bc1ddba633b56221754796057e69 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Fri, 21 Aug 2026 15:27:33 -0700 Subject: [PATCH 06/12] mark TypingMode::Coherence arms in the old solver as unreachable --- .../src/traits/fulfill.rs | 13 ++++++--- .../src/traits/normalize.rs | 12 ++++++--- .../src/traits/project.rs | 6 +++-- .../src/traits/query/normalize.rs | 6 +++-- .../src/traits/select/candidate_assembly.rs | 6 ++--- .../src/traits/select/mod.rs | 27 ++++++++++--------- 6 files changed, 41 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index aae323ae1671f..83f1fcd756981 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -176,12 +176,14 @@ where TypingMode::Typeck { defining_opaque_types_and_generators } => { defining_opaque_types_and_generators } - TypingMode::Coherence - | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } + TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } | TypingMode::PostBorrowck { defined_opaque_types: _ } | TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => return Default::default(), + TypingMode::Coherence => { + unreachable!("old solver coherence") + } }; if stalled_coroutines.is_empty() { @@ -872,8 +874,9 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { trait_obligation: PolyTraitObligation<'tcx>, stalled_on: &mut Vec, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { + debug_assert!(!self.selcx.typing_mode().is_coherence(), "old solver coherence"); let infcx = self.selcx.infcx; - if obligation.predicate.is_global() && !self.selcx.typing_mode().is_coherence() { + if obligation.predicate.is_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. if infcx.predicate_must_hold_considering_regions(obligation) { @@ -925,9 +928,11 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { project_obligation: PolyProjectionObligation<'tcx>, stalled_on: &mut Vec, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { + debug_assert!(!self.selcx.typing_mode().is_coherence(), "old solver coherence"); + let tcx = self.selcx.tcx(); let infcx = self.selcx.infcx; - if obligation.predicate.is_global() && !self.selcx.typing_mode().is_coherence() { + if obligation.predicate.is_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. if infcx.predicate_must_hold_considering_regions(obligation) { diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 5a66fafd57361..63f7c6dfc94fc 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -139,11 +139,13 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable>>( // so we can ignore those. match infcx.typing_mode_raw().assert_not_erased() { // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis - TypingMode::Coherence - | TypingMode::Typeck { .. } + TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE), TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => {} + TypingMode::Coherence => { + unreachable!("old solver coherence") + } } value.has_type_flags(flags) @@ -426,8 +428,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.selcx.typing_mode() { // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis - TypingMode::Coherence - | TypingMode::Typeck { .. } + TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } => ty.super_fold_with(self), TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => { @@ -449,6 +450,9 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx self.depth -= 1; folded_ty } + TypingMode::Coherence => { + unreachable!("old solver coherence") + } } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 6f7c46089632f..6cea4a9300824 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1034,8 +1034,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // transmute checking and polymorphic MIR optimizations could // get a result which isn't correct for all monomorphizations. match selcx.typing_mode() { - TypingMode::Coherence - | TypingMode::Typeck { .. } + TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::Reflection | TypingMode::PostBorrowck { .. } => { @@ -1053,6 +1052,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( selcx.infcx.deeply_resolve_ignoring_regions(trait_ref); !poly_trait_ref.still_further_specializable() } + TypingMode::Coherence => { + unreachable!("old solver coherence") + } } } } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 782697782f94c..b4dffab26d1e4 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -231,8 +231,7 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { ty::Opaque { def_id } => { // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.infcx.typing_mode_raw().assert_not_erased() { - TypingMode::Coherence - | TypingMode::Typeck { .. } + TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } => ty.try_super_fold_with(self)?, @@ -268,6 +267,9 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { self.anon_depth -= 1; folded_ty? } + TypingMode::Coherence => { + unreachable!("old solver coherence") + } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 9ebfb4d5ecda0..7228c55b404b4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -845,6 +845,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) => { + debug_assert!(!self.typing_mode().is_coherence(), "old solver coherence"); + if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate { .. })) { // We do not generate an auto impl candidate for `impl Trait`s which already // reference our auto trait. @@ -855,10 +857,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // // Note that this is only sound as projection candidates of opaque types // are always applicable for auto traits. - } else if self.typing_mode().is_coherence() { - // We do not emit auto trait candidates for opaque types in coherence. - // Doing so can result in weird dependency cycles. - candidates.ambiguous = true; } else if self.infcx.can_define_opaque_ty(def_id) { // We do not emit auto trait candidates for opaque types in their defining scope, as // we need to know the hidden type first, which we can't reliably know within the defining diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index f92d0b3720b12..05b4ba6a7180c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -933,8 +933,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { previous_stack: TraitObligationStackList<'o, 'tcx>, mut obligation: PolyTraitObligation<'tcx>, ) -> Result { - if !self.typing_mode().is_coherence() - && obligation.is_global() + debug_assert!(!self.typing_mode().is_coherence(), "old solver coherence"); + + if obligation.is_global() && obligation.param_env.caller_bounds().all(|bound| bound.has_param()) { // If a param env has no global bounds, global obligations do not @@ -1379,13 +1380,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } match self.typing_mode() { - // Avoid using the global cache during coherence and just rely - // on the local cache. It is really just a simplification to - // avoid us having to fear that coherence results "pollute" - // the master cache. Since coherence executes pretty quickly, - // it's not worth going to more trouble to increase the - // hit-rate, I don't think. - TypingMode::Coherence => false, // Avoid using the global cache when we're defining opaque types // as their hidden type may impact the result of candidate selection. // @@ -1411,6 +1405,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // FIXME(#132279): This is still incorrect as we treat opaque types // and default associated items differently between these two modes. TypingMode::PostAnalysis | TypingMode::Codegen => true, + TypingMode::Coherence => { + unreachable!("old solver coherence") + } } } @@ -2437,14 +2434,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> { return Err(()); } - TypingMode::Coherence - | TypingMode::Typeck { .. } + TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } | TypingMode::Codegen | TypingMode::ErasedNotCoherence(_) | TypingMode::Reflection | TypingMode::PostAnalysis => {} + TypingMode::Coherence => { + unreachable!("old solver coherence") + } } Ok(Normalized { value: impl_args, obligations: nested_obligations }) @@ -2785,12 +2784,14 @@ impl<'tcx> SelectionContext<'_, 'tcx> { TypingMode::Typeck { defining_opaque_types_and_generators: stalled_generators } => { def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id)) } - TypingMode::Coherence - | TypingMode::PostAnalysis + TypingMode::PostAnalysis | TypingMode::Reflection | TypingMode::Codegen | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } | TypingMode::PostBorrowck { defined_opaque_types: _ } => false, + TypingMode::Coherence => { + unreachable!("old solver coherence") + } } } } From d850b33c37707c3001d956998839dcf6d3186718 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Fri, 21 Aug 2026 15:28:41 -0700 Subject: [PATCH 07/12] bless tests --- .../assumptions_on_binders/alias_outlives.rs | 2 +- ...higher_ranked_alias_outlives_assumption.rs | 2 +- .../nested-gat-outlives-issue-161067.rs | 2 +- .../placeholder-assumptions-issue-157840.rs | 2 +- .../reflexive-outlives-in-root.rs | 2 +- .../resolved-region-var-max-universe.rs | 2 +- .../same-universe-placeholder-outlives.rs | 2 +- .../test-infra-fails-properly.rs | 2 +- .../test-infra-works.rs | 2 +- .../type-outlives-assumptions.rs | 2 +- .../type_relation_binders_inside_solver-1.rs | 2 +- .../type_relation_binders_inside_solver-2.rs | 2 +- .../type_relation_binders_inside_solver-3.rs | 2 +- .../generic_const_exprs/error_in_ty.rs | 2 -- .../generic_const_exprs/error_in_ty.stderr | 16 +++++----- tests/ui/error-codes/E0476.old.stderr | 31 ------------------- tests/ui/error-codes/E0476.rs | 2 -- .../{E0476.next.stderr => E0476.stderr} | 8 ++--- ...-124857-combine-effect-const-infer-vars.rs | 2 -- ...857-combine-effect-const-infer-vars.stderr | 2 +- .../traits/issue-90662-projection-caching.rs | 2 -- .../ambiguity-causes-canonical-state-ice-1.rs | 1 - .../ambiguity-causes-canonical-state-ice-2.rs | 2 -- ...iguity-causes-canonical-state-ice-2.stderr | 2 +- .../ambiguity-causes-visitor-hang.rs | 2 -- .../ambiguity-causes-visitor-hang.stderr | 2 +- .../coherence/coherence-fulfill-overflow.rs | 2 -- .../coherence-fulfill-overflow.stderr | 2 +- ...e-unknowable-does-not-eagerly-normalize.rs | 1 - .../dont-ice-on-assoc-projection.rs | 2 -- .../dont-ice-on-assoc-projection.stderr | 4 +-- .../normalize/indirectly-constrained-term.rs | 3 -- .../coherence-alias-hang-with-region.rs | 1 - ...cursion-limit-normalizes-to-constraints.rs | 1 - 34 files changed, 31 insertions(+), 85 deletions(-) delete mode 100644 tests/ui/error-codes/E0476.old.stderr rename tests/ui/error-codes/{E0476.next.stderr => E0476.stderr} (92%) diff --git a/tests/ui/assumptions_on_binders/alias_outlives.rs b/tests/ui/assumptions_on_binders/alias_outlives.rs index 0c2ed6585cf45..7dd14da4fd773 100644 --- a/tests/ui/assumptions_on_binders/alias_outlives.rs +++ b/tests/ui/assumptions_on_binders/alias_outlives.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally // test that a `::Assoc: '!a_u1` constraint is considered to be satisfied // if there's a `T::Assoc: 'static` assumption in the root universe and if not that it is diff --git a/tests/ui/assumptions_on_binders/implied_higher_ranked_alias_outlives_assumption.rs b/tests/ui/assumptions_on_binders/implied_higher_ranked_alias_outlives_assumption.rs index 2f0f2ca8aab85..1d889b8c64362 100644 --- a/tests/ui/assumptions_on_binders/implied_higher_ranked_alias_outlives_assumption.rs +++ b/tests/ui/assumptions_on_binders/implied_higher_ranked_alias_outlives_assumption.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally //@ check-pass #![feature(generic_const_items)] diff --git a/tests/ui/assumptions_on_binders/nested-gat-outlives-issue-161067.rs b/tests/ui/assumptions_on_binders/nested-gat-outlives-issue-161067.rs index 937b17e5ec872..4e72f328f73e7 100644 --- a/tests/ui/assumptions_on_binders/nested-gat-outlives-issue-161067.rs +++ b/tests/ui/assumptions_on_binders/nested-gat-outlives-issue-161067.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally //@ needs-rustc-debug-assertions // Regression test for #161067. A nested non-rigid alias must be normalized diff --git a/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs b/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs index 8b0b92b8a7842..b3bc4d6fae25f 100644 --- a/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs +++ b/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally trait Trait {} diff --git a/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs index 641ac3951d76a..fcd436c7df3ed 100644 --- a/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs +++ b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally #![feature(test_binder_constraints, non_lifetime_binders)] #![expect(incomplete_features)] diff --git a/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs b/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs index ef1a5ca74c546..4c35de2be8759 100644 --- a/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs +++ b/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally // Regression test for an ICE in the `MaxUniverse` region visitor. When computing // the max universe of a region constraint, a `ReVar` term could already have been diff --git a/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs index 6d292416cd4cf..b748dffe34981 100644 --- a/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs +++ b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally #![feature(test_binder_constraints, non_lifetime_binders)] #![expect(incomplete_features)] diff --git a/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs b/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs index 97629627ad556..042deefcbb6e5 100644 --- a/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs +++ b/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally #![feature(test_binder_constraints)] #![expect(incomplete_features)] diff --git a/tests/ui/assumptions_on_binders/test-infra-works.rs b/tests/ui/assumptions_on_binders/test-infra-works.rs index d8d64d1aac255..b36e16a545bb3 100644 --- a/tests/ui/assumptions_on_binders/test-infra-works.rs +++ b/tests/ui/assumptions_on_binders/test-infra-works.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally #![feature(test_binder_constraints, non_lifetime_binders)] #![expect(incomplete_features)] diff --git a/tests/ui/assumptions_on_binders/type-outlives-assumptions.rs b/tests/ui/assumptions_on_binders/type-outlives-assumptions.rs index bc3b3a7f2c250..c78231d8ca103 100644 --- a/tests/ui/assumptions_on_binders/type-outlives-assumptions.rs +++ b/tests/ui/assumptions_on_binders/type-outlives-assumptions.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally // Regression test for rust-lang/project-assumptions-on-binders#19, based on the `syn` failure. // The receiver gives us an implied `I: 'b` bound and `'b: 'a` lets that satisfy the object diff --git a/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-1.rs b/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-1.rs index fe5753c3c9970..212446a179f00 100644 --- a/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-1.rs +++ b/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-1.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally #![crate_type = "lib"] diff --git a/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-2.rs b/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-2.rs index 78769282a3f4e..0a484d17da542 100644 --- a/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-2.rs +++ b/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-2.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally #![crate_type = "lib"] diff --git a/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-3.rs b/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-3.rs index c1d4d0ed1c79f..6cc175fbce36d 100644 --- a/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-3.rs +++ b/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-3.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally #![crate_type = "lib"] diff --git a/tests/ui/const-generics/generic_const_exprs/error_in_ty.rs b/tests/ui/const-generics/generic_const_exprs/error_in_ty.rs index 29ad935c0149c..9449153060db5 100644 --- a/tests/ui/const-generics/generic_const_exprs/error_in_ty.rs +++ b/tests/ui/const-generics/generic_const_exprs/error_in_ty.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence - #![feature(generic_const_exprs)] #![allow(incomplete_features)] diff --git a/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr b/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr index dea81894463b3..21ca0f6e04d97 100644 --- a/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr +++ b/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr @@ -1,11 +1,11 @@ error[E0425]: cannot find value `x` in this scope - --> $DIR/error_in_ty.rs:6:31 + --> $DIR/error_in_ty.rs:4:31 | LL | pub struct A {} | ^ not found in this scope | note: similarly named const parameter `z` defined here - --> $DIR/error_in_ty.rs:6:20 + --> $DIR/error_in_ty.rs:4:20 | LL | pub struct A {} | ^ @@ -16,7 +16,7 @@ LL + pub struct A {} | error: `[usize; x]` is forbidden as the type of a const generic parameter - --> $DIR/error_in_ty.rs:6:23 + --> $DIR/error_in_ty.rs:4:23 | LL | pub struct A {} | ^^^^^^^^^^ @@ -28,31 +28,31 @@ LL + #![feature(min_adt_const_params)] | error[E0308]: mismatched types - --> $DIR/error_in_ty.rs:10:8 + --> $DIR/error_in_ty.rs:8:8 | LL | impl A<2> { | ^ expected `[usize; x]`, found integer | note: expected because of the type of the const parameter - --> $DIR/error_in_ty.rs:6:14 + --> $DIR/error_in_ty.rs:4:14 | LL | pub struct A {} | ^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/error_in_ty.rs:16:8 + --> $DIR/error_in_ty.rs:14:8 | LL | impl A<2> { | ^ expected `[usize; x]`, found integer | note: expected because of the type of the const parameter - --> $DIR/error_in_ty.rs:6:14 + --> $DIR/error_in_ty.rs:4:14 | LL | pub struct A {} | ^^^^^^^^^^^^^^^^^^^ error[E0592]: duplicate definitions with name `B` - --> $DIR/error_in_ty.rs:12:5 + --> $DIR/error_in_ty.rs:10:5 | LL | pub const fn B() {} | ^^^^^^^^^^^^^^^^ duplicate definitions for `B` diff --git a/tests/ui/error-codes/E0476.old.stderr b/tests/ui/error-codes/E0476.old.stderr deleted file mode 100644 index 454dbecc7d01f..0000000000000 --- a/tests/ui/error-codes/E0476.old.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0119]: conflicting implementations of trait `CoerceUnsized<&Wrapper<_>>` for type `&Wrapper<_>` - --> $DIR/E0476.rs:11:1 - | -LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: conflicting implementation in crate `core`: - - impl<'a, 'b, T, U> CoerceUnsized<&'a U> for &'b T - where 'b: 'a, T: Unsize, T: ?Sized, U: ?Sized; - -error[E0476]: lifetime of the source pointer does not outlive lifetime bound of the object type - --> $DIR/E0476.rs:11:1 - | -LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: object type is valid for the lifetime `'a` as defined here - --> $DIR/E0476.rs:11:6 - | -LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} - | ^^ -note: source pointer is only valid for the lifetime `'b` as defined here - --> $DIR/E0476.rs:11:10 - | -LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} - | ^^ - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0119, E0476. -For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/error-codes/E0476.rs b/tests/ui/error-codes/E0476.rs index 03656d28b2b99..d5e4b8d237274 100644 --- a/tests/ui/error-codes/E0476.rs +++ b/tests/ui/error-codes/E0476.rs @@ -1,5 +1,3 @@ -//@ revisions: old next -//@[next] compile-flags: -Znext-solver=coherence #![feature(coerce_unsized)] #![feature(unsize)] diff --git a/tests/ui/error-codes/E0476.next.stderr b/tests/ui/error-codes/E0476.stderr similarity index 92% rename from tests/ui/error-codes/E0476.next.stderr rename to tests/ui/error-codes/E0476.stderr index 454dbecc7d01f..0378ac6e8ec91 100644 --- a/tests/ui/error-codes/E0476.next.stderr +++ b/tests/ui/error-codes/E0476.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `CoerceUnsized<&Wrapper<_>>` for type `&Wrapper<_>` - --> $DIR/E0476.rs:11:1 + --> $DIR/E0476.rs:9:1 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,18 +9,18 @@ LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S where 'b: 'a, T: Unsize, T: ?Sized, U: ?Sized; error[E0476]: lifetime of the source pointer does not outlive lifetime bound of the object type - --> $DIR/E0476.rs:11:1 + --> $DIR/E0476.rs:9:1 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: object type is valid for the lifetime `'a` as defined here - --> $DIR/E0476.rs:11:6 + --> $DIR/E0476.rs:9:6 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^ note: source pointer is only valid for the lifetime `'b` as defined here - --> $DIR/E0476.rs:11:10 + --> $DIR/E0476.rs:9:10 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^ diff --git a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs index ba503be2aaff7..39d1840caf41e 100644 --- a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs +++ b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence - #![feature(const_trait_impl)] const trait Foo {} diff --git a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr index 97fdb4b287e8f..76520d1f4d89a 100644 --- a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr +++ b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Foo` for type `i32` - --> $DIR/ice-124857-combine-effect-const-infer-vars.rs:9:1 + --> $DIR/ice-124857-combine-effect-const-infer-vars.rs:7:1 | LL | const impl Foo for i32 {} | ---------------------- first implementation here diff --git a/tests/ui/traits/issue-90662-projection-caching.rs b/tests/ui/traits/issue-90662-projection-caching.rs index 247cc78979a91..ba3b6e4e43b98 100644 --- a/tests/ui/traits/issue-90662-projection-caching.rs +++ b/tests/ui/traits/issue-90662-projection-caching.rs @@ -1,5 +1,3 @@ -//@ revisions: old next -//@[next] compile-flags: -Znext-solver=coherence //@ check-pass // Regression test for issue #90662 diff --git a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-1.rs b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-1.rs index 151c3b226c114..48b1a442bf41d 100644 --- a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-1.rs +++ b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-1.rs @@ -1,4 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence //@ check-pass // A regression test for #124791. Computing ambiguity causes diff --git a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.rs b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.rs index b472499cb0bf7..28df3a39ddddf 100644 --- a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.rs +++ b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence - // A regression test for #124791. Computing ambiguity causes // for the overlap of the `ToString` impls caused an ICE. #![crate_type = "lib"] diff --git a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.stderr b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.stderr index 469f7a909b141..6200046baa65d 100644 --- a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.stderr +++ b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Overlap` for type `str` - --> $DIR/ambiguity-causes-canonical-state-ice-2.rs:18:1 + --> $DIR/ambiguity-causes-canonical-state-ice-2.rs:16:1 | LL | impl + ?Sized> Overlap for T {} | --------------------------------------------------- first implementation here diff --git a/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.rs b/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.rs index 54854b1b8a522..190531bc9201d 100644 --- a/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.rs +++ b/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.rs @@ -4,8 +4,6 @@ // takes multiple minutes when doing so and less than a second // otherwise. -//@ compile-flags: -Znext-solver=coherence - trait RecursiveSuper: Super< A0 = Self::Assoc, diff --git a/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.stderr b/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.stderr index 3731dc5b74ec0..467981efe2c99 100644 --- a/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.stderr +++ b/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Overlap` for type `Box<_>` - --> $DIR/ambiguity-causes-visitor-hang.rs:53:1 + --> $DIR/ambiguity-causes-visitor-hang.rs:51:1 | LL | impl Overlap for T {} | ------------------------------------- first implementation here diff --git a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.rs b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.rs index 3fd22c7dbf0c1..551fe619329ff 100644 --- a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.rs +++ b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence - #![feature(rustc_attrs)] #![rustc_no_implicit_bounds] #![recursion_limit = "10"] diff --git a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr index a93fbc2404dad..8e293950f0adb 100644 --- a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr +++ b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `W>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/coherence-fulfill-overflow.rs:14:1 + --> $DIR/coherence-fulfill-overflow.rs:12:1 | LL | impl Trait for W {} | ---------------------------- first implementation here diff --git a/tests/ui/traits/next-solver/coherence/coherence-unknowable-does-not-eagerly-normalize.rs b/tests/ui/traits/next-solver/coherence/coherence-unknowable-does-not-eagerly-normalize.rs index 13cdcc7d93e58..95916365a73f2 100644 --- a/tests/ui/traits/next-solver/coherence/coherence-unknowable-does-not-eagerly-normalize.rs +++ b/tests/ui/traits/next-solver/coherence/coherence-unknowable-does-not-eagerly-normalize.rs @@ -1,4 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence //@ check-pass //@ aux-build:coherence-unknowable-does-not-eagerly-normalize-dep.rs // diff --git a/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.rs b/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.rs index cbe489a0430a8..6ad7893e32f1e 100644 --- a/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.rs +++ b/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence - // Makes sure we don't ICE on associated const projection when the feature gate // is not enabled, since we should avoid encountering ICEs on stable if possible. diff --git a/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr b/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr index e8c1f597e0cd8..4d75a2ef0af99 100644 --- a/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr +++ b/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr @@ -1,5 +1,5 @@ error[E0658]: associated const equality is incomplete - --> $DIR/dont-ice-on-assoc-projection.rs:15:32 + --> $DIR/dont-ice-on-assoc-projection.rs:13:32 | LL | impl Foo for T where T: Bar {} | ^^^^^^^^^ @@ -9,7 +9,7 @@ LL | impl Foo for T where T: Bar {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0119]: conflicting implementations of trait `Foo` for type `()` - --> $DIR/dont-ice-on-assoc-projection.rs:15:1 + --> $DIR/dont-ice-on-assoc-projection.rs:13:1 | LL | impl Foo for () {} | --------------- first implementation here diff --git a/tests/ui/traits/next-solver/normalize/indirectly-constrained-term.rs b/tests/ui/traits/next-solver/normalize/indirectly-constrained-term.rs index 696d567db86d9..7a555b40bf6dd 100644 --- a/tests/ui/traits/next-solver/normalize/indirectly-constrained-term.rs +++ b/tests/ui/traits/next-solver/normalize/indirectly-constrained-term.rs @@ -1,6 +1,3 @@ -//@ revisions: current next -//@[next] compile-flags: -Znext-solver=coherence -//@ ignore-compare-mode-next-solver (explicit revisions) //@ check-pass // A regression test for `paperclip-core`. This previously failed to compile diff --git a/tests/ui/traits/next-solver/overflow/coherence-alias-hang-with-region.rs b/tests/ui/traits/next-solver/overflow/coherence-alias-hang-with-region.rs index 1df895d732a40..0ccb6f22cf965 100644 --- a/tests/ui/traits/next-solver/overflow/coherence-alias-hang-with-region.rs +++ b/tests/ui/traits/next-solver/overflow/coherence-alias-hang-with-region.rs @@ -1,6 +1,5 @@ //@ check-pass //@ revisions: ai ia ii -//@ compile-flags: -Znext-solver=coherence // Regression test for nalgebra hang . diff --git a/tests/ui/traits/next-solver/overflow/recursion-limit-normalizes-to-constraints.rs b/tests/ui/traits/next-solver/overflow/recursion-limit-normalizes-to-constraints.rs index e5a57a44d4980..f084027acfe68 100644 --- a/tests/ui/traits/next-solver/overflow/recursion-limit-normalizes-to-constraints.rs +++ b/tests/ui/traits/next-solver/overflow/recursion-limit-normalizes-to-constraints.rs @@ -1,4 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence //@ check-pass #![feature(rustc_attrs)] #![rustc_no_implicit_bounds] From f3f9adf7082e27e0b77b05ec3e2fdaee1badd056 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Fri, 2 Oct 2026 14:48:46 +0200 Subject: [PATCH 08/12] tests: add test for warning-free builds of `core` under `no_io_statics` Similar to the existing tests for other `cfg`s like `no_fp_fmt_parse`, add one for `no_io_statics`. This should prevent issues like the one in the parent commit. Signed-off-by: Miguel Ojeda --- tests/run-make/core-no-io-statics/rmake.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/run-make/core-no-io-statics/rmake.rs diff --git a/tests/run-make/core-no-io-statics/rmake.rs b/tests/run-make/core-no-io-statics/rmake.rs new file mode 100644 index 0000000000000..0e75dfa8c273c --- /dev/null +++ b/tests/run-make/core-no-io-statics/rmake.rs @@ -0,0 +1,14 @@ +// This test checks that the core library of Rust can be compiled when enabling +// `--cfg no_io_statics`. + +use run_make_support::{rustc, source_root}; + +fn main() { + rustc() + .edition("2024") + .arg("-Dwarnings") + .crate_type("rlib") + .input(source_root().join("library/core/src/lib.rs")) + .cfg("no_io_statics") + .run(); +} From da0baa24c41da903b35aa146503e4261ffe26aaa Mon Sep 17 00:00:00 2001 From: Yara Date: Fri, 2 Oct 2026 15:38:20 +0200 Subject: [PATCH 09/12] reflection: fix ICE when TypeId::info called on ADT We are refactoring from a large enum where the fields of the variants contain all the reflection info to a flat enum containing only the type kind (struct/bool/array etc). While we removed the fields of Struct, Enum and Union we forgot to take out the const eval code writing into those fields. That gave an ICE. This fixes that. --- .../src/const_eval/type_info.rs | 4 +- .../src/const_eval/type_info/adt.rs | 178 +----------------- 2 files changed, 7 insertions(+), 175 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index 0bece36c64ed0..0df2e9b5fd0ae 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -91,9 +91,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { self.project_downcast_named(&field_dest, sym::Slice)?; variant } - ty::Adt(adt_def, generics) => { - self.write_adt_type_info(&field_dest, (ty, *adt_def), generics)? - } + ty::Adt(adt_def, _) => self.write_adt_type_info(&field_dest, *adt_def)?, ty::Bool => { let (variant, _variant_place) = self.project_downcast_named(&field_dest, sym::Bool)?; diff --git a/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs b/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs index 281d7b0a921ba..4ff1b37e953d4 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs @@ -1,13 +1,12 @@ use rustc_abi::{FieldIdx, VariantIdx}; -use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{ - AdtDef, AdtKind, Const, ConstKind, GenericArgKind, GenericArgs, Region, Ty, VariantDef, + AdtDef, AdtKind, Const, ConstKind, GenericArgKind, GenericArgs, Region, Ty, }; use rustc_span::{bug, span_bug, sym}; use crate::const_eval::CompileTimeMachine; use crate::interpret::{ - CtfeProvenance, InterpCx, InterpResult, MPlaceTy, Projectable, Scalar, Writeable, interp_ok, + CtfeProvenance, InterpCx, InterpResult, MPlaceTy, Projectable, Writeable, interp_ok, }; impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { @@ -15,190 +14,25 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { pub(crate) fn write_adt_type_info( &mut self, place: &impl Writeable<'tcx, CtfeProvenance>, - adt: (Ty<'tcx>, AdtDef<'tcx>), - generics: &'tcx GenericArgs<'tcx>, + adt_def: AdtDef<'tcx>, ) -> InterpResult<'tcx, VariantIdx> { - let (adt_ty, adt_def) = adt; let variant_idx = match adt_def.adt_kind() { AdtKind::Struct => { - let (variant, variant_place) = self.project_downcast_named(place, sym::Struct)?; - let place = self.project_field(&variant_place, FieldIdx::ZERO)?; - self.write_struct_type_info( - place, - (adt_ty, adt_def.variant(VariantIdx::ZERO)), - generics, - )?; + let (variant, _) = self.project_downcast_named(place, sym::Struct)?; variant } AdtKind::Union => { - let (variant, variant_place) = self.project_downcast_named(place, sym::Union)?; - let place = self.project_field(&variant_place, FieldIdx::ZERO)?; - self.write_union_type_info( - place, - (adt_ty, adt_def.variant(VariantIdx::ZERO)), - generics, - )?; + let (variant, _) = self.project_downcast_named(place, sym::Union)?; variant } AdtKind::Enum => { - let (variant, variant_place) = self.project_downcast_named(place, sym::Enum)?; - let place = self.project_field(&variant_place, FieldIdx::ZERO)?; - self.write_enum_type_info(place, adt, generics)?; + let (variant, _) = self.project_downcast_named(place, sym::Enum)?; variant } }; interp_ok(variant_idx) } - pub(crate) fn write_struct_type_info( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - struct_: (Ty<'tcx>, &'tcx VariantDef), - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - let (struct_ty, struct_def) = struct_; - let struct_layout = self.layout_of(struct_ty)?; - - for (field_idx, field) in - place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() - { - let field_place = self.project_field(&place, field_idx)?; - - match field.name { - sym::generics => self.write_generics(&field_place, generics)?, - sym::fields => { - self.write_variant_fields(field_place, struct_def, struct_layout, generics)? - } - sym::non_exhaustive => { - let is_non_exhaustive = struct_def.is_field_list_non_exhaustive(); - self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? - } - other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), - } - } - - interp_ok(()) - } - - pub(crate) fn write_union_type_info( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - union_: (Ty<'tcx>, &'tcx VariantDef), - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - let (union_ty, union_def) = union_; - let union_layout = self.layout_of(union_ty)?; - - for (field_idx, field) in - place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() - { - let field_place = self.project_field(&place, field_idx)?; - - match field.name { - sym::generics => self.write_generics(&field_place, generics)?, - sym::fields => { - self.write_variant_fields(field_place, union_def, union_layout, generics)? - } - sym::non_exhaustive => { - let is_non_exhaustive = union_def.is_field_list_non_exhaustive(); - self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? - } - other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), - } - } - - interp_ok(()) - } - - pub(crate) fn write_enum_type_info( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - enum_: (Ty<'tcx>, AdtDef<'tcx>), - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - let (enum_ty, enum_def) = enum_; - let enum_layout = self.layout_of(enum_ty)?; - - for (field_idx, field) in - place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() - { - let field_place = self.project_field(&place, field_idx)?; - - match field.name { - sym::generics => self.write_generics(&field_place, generics)?, - sym::type_id_variants => { - self.allocate_fill_and_write_slice_ptr( - &field_place, - enum_def.variants().len() as u64, - |this, i, place| { - let variant_idx = VariantIdx::from_usize(i as usize); - let variant_def = &enum_def.variants()[variant_idx]; - let variant_layout = enum_layout.for_variant(this, variant_idx); - this.write_enum_variant(place, (variant_layout, &variant_def), generics) - }, - )?; - } - sym::non_exhaustive => { - let is_non_exhaustive = enum_def.is_variant_list_non_exhaustive(); - self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? - } - other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), - } - } - - interp_ok(()) - } - - fn write_enum_variant( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - variant: (TyAndLayout<'tcx>, &'tcx VariantDef), - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - let (variant_layout, variant_def) = variant; - - for (field_idx, field_def) in - place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() - { - let field_place = self.project_field(&place, field_idx)?; - match field_def.name { - sym::name => { - let name_place = self.allocate_str_dedup(variant_def.name.as_str())?; - let ptr = self.mplace_to_imm_ptr(&name_place, None)?; - self.write_immediate(*ptr, &field_place)? - } - sym::fields => { - self.write_variant_fields(field_place, &variant_def, variant_layout, generics)? - } - sym::non_exhaustive => { - let is_non_exhaustive = variant_def.is_field_list_non_exhaustive(); - self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? - } - other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"), - } - } - interp_ok(()) - } - - // Write fields for struct, enum variants - fn write_variant_fields( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - variant_def: &'tcx VariantDef, - variant_layout: TyAndLayout<'tcx>, - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - self.allocate_fill_and_write_slice_ptr( - &place, - variant_def.fields.len() as u64, - |this, i, place| { - let field_def = &variant_def.fields[FieldIdx::from_usize(i as usize)]; - let field_ty = field_def.ty(*this.tcx, generics).skip_norm_wip(); - this.write_field(field_ty, place, variant_layout, Some(field_def.name), i) - }, - ) - } - pub(super) fn write_generics( &mut self, place: &impl Writeable<'tcx, CtfeProvenance>, From 6065c5ae5206289fa17f13049c8bfad88fbfa3af Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 2 Oct 2026 16:42:27 -0400 Subject: [PATCH 10/12] Make the tracking issue template better suited for experiments --- .github/ISSUE_TEMPLATE/tracking_issue.md | 32 +++++++++++++++--------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/tracking_issue.md b/.github/ISSUE_TEMPLATE/tracking_issue.md index 0e0fdc5ca864e..e4bdcd212f381 100644 --- a/.github/ISSUE_TEMPLATE/tracking_issue.md +++ b/.github/ISSUE_TEMPLATE/tracking_issue.md @@ -1,6 +1,6 @@ --- name: Tracking Issue -about: A tracking issue for an accepted feature or RFC in Rust. +about: A tracking issue for an unstable feature in Rust. title: Tracking Issue for XXX labels: C-tracking-issue --- @@ -8,19 +8,27 @@ labels: C-tracking-issue NOTE: For library features, please use the "Library Tracking Issue" template instead. Thank you for creating a tracking issue! 📜 Tracking issues are for tracking a -feature from implementation to stabilisation. Make sure to include the relevant -RFC for the feature if it has one. Otherwise provide a short summary of the -feature and link any relevant PRs or issues, and remove any sections that are -not relevant to the feature. +feature from implementation to stabilisation. Remember to add team labels to the tracking issue. -For a language team feature, this would e.g., be `T-lang`. +For a language team feature, this would e.g., be `T-lang`: + +> @rustbot label T-lang + Such a feature should also be labeled with e.g., `F-my_feature`. This label is used to associate issues (e.g., bugs and design questions) to the feature. --> -This is a tracking issue for the RFC "XXX" (rust-lang/rfcs#NNN). -The feature gate for the issue is `#![feature(FFF)]`. +This is a tracking issue for `#![feature(FFF)]`. +The RFC for this feature is rust-lang/rfcs#NNN. + + ### About tracking issues @@ -38,8 +46,8 @@ implementing a feature, followed by a PR that stabilises the feature. However for larger features an implementation could be broken up into multiple PRs. --> -- [ ] Implement the RFC (cc @rust-lang/XXX -- can anyone write up mentoring - instructions?) +- [ ] Create the feature gate +- [ ] Implement the feature - [ ] Adjust documentation ([see instructions on rustc-dev-guide][doc-guide]) - [ ] Style updates for any new syntax ([nightly-style-procedure]) - [ ] Style team decision on new formatting @@ -59,8 +67,8 @@ stabilised. It is useful to link related discussions and conculsions as they develop. --> -- [ ] list all the "unresolved questions" found in the RFC to ensure they are - not forgotten. +- [ ] List any unresolved questions, including those listed in the RFC if there is one, + to ensure they are not forgotten. ### Implementation history From 89f50a5d3a11eb03f983aca5158590e4771bfd16 Mon Sep 17 00:00:00 2001 From: panstromek Date: Sat, 3 Oct 2026 07:01:18 +0200 Subject: [PATCH 11/12] ref: Avoid long iterator chain in all_rust_features --- compiler/rustc_target/src/target_features.rs | 42 ++++++++++---------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 2ee7dea9f8af3..5272ed2df59b3 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -1062,26 +1062,28 @@ const XTENSA_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ /// /// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator! pub fn all_rust_features() -> impl Iterator { - std::iter::empty() - .chain(ARM_FEATURES) - .chain(AARCH64_FEATURES) - .chain(X86_FEATURES) - .chain(HEXAGON_FEATURES) - .chain(POWERPC_FEATURES) - .chain(MIPS_FEATURES) - .chain(NVPTX_FEATURES) - .chain(RISCV_FEATURES) - .chain(WASM_FEATURES) - .chain(BPF_FEATURES) - .chain(XTENSA_FEATURES) - .chain(CSKY_FEATURES) - .chain(LOONGARCH_FEATURES) - .chain(IBMZ_FEATURES) - .chain(SPARC_FEATURES) - .chain(M68K_FEATURES) - .chain(AVR_FEATURES) - .cloned() - .map(|(f, s, _)| (f, s)) + [ + ARM_FEATURES, + AARCH64_FEATURES, + X86_FEATURES, + HEXAGON_FEATURES, + POWERPC_FEATURES, + MIPS_FEATURES, + NVPTX_FEATURES, + RISCV_FEATURES, + WASM_FEATURES, + BPF_FEATURES, + XTENSA_FEATURES, + CSKY_FEATURES, + LOONGARCH_FEATURES, + IBMZ_FEATURES, + SPARC_FEATURES, + M68K_FEATURES, + AVR_FEATURES, + ] + .into_iter() + .flatten() + .map(|(f, s, _)| (*f, *s)) } /// Find which target architectures a feature belongs to. From 62cbb1801373d3e36a957780a9bb92830a6ebbaf Mon Sep 17 00:00:00 2001 From: Davlat Davydov Date: Fri, 2 Oct 2026 02:26:15 +0300 Subject: [PATCH 12/12] Add documentation for the and attributes Fix test-tidy review changes review changes review changes fix llvm build --- library/core/src/attribute_docs.rs | 98 ++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/library/core/src/attribute_docs.rs b/library/core/src/attribute_docs.rs index 584e1583c9bdb..989f1e154add6 100644 --- a/library/core/src/attribute_docs.rs +++ b/library/core/src/attribute_docs.rs @@ -406,6 +406,104 @@ const _: () = (); /// [the `no_std` attribute]: ../reference/names/preludes.html#the-no_std-attribute const _: () = (); +#[doc(attribute = "no_main")] +/// Prevents emitting the `main` entrypoint symbol. +/// +/// Written as an inner attribute at the top of the crate root, the `no_main` attribute prevents +/// the compiler from generating the program's standard Rust entrypoint, leaving that up to you. +/// This is useful when some other object being linked into the program defines the entrypoint, +/// or when you want to define the platform's `main` symbol yourself. +/// +/// If you define an entry point symbol that is suitable for your target, it must also be exported +/// under an unmangled name using the [`no_mangle` attribute]: +/// +/// ```standalone_crate +/// #![no_main] +/// +/// use std::ffi::{c_char, c_int}; +/// +/// #[unsafe(no_mangle)] +/// pub extern "C" fn main(_argc: c_int, _argv: *const *const c_char) -> c_int { +/// println!("Hello world!"); +/// 0 +/// } +/// ``` +/// +/// Unlike `no_std`, the `no_main` attribute does not prevent the compiler from generating +/// the startup routine or linking the standard library provided by the operating system's executable [ABI]. +/// +/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface +/// [`no_mangle` attribute]: ../reference/abi.html#the-no_mangle-attribute +const _: () = (); + +#[doc(attribute = "repr")] +/// Specifies the [representation] of a type. +/// +/// Written as an outer attribute on a `struct`, `enum` or `union`, `repr` controls how the +/// type is laid out in memory. This is needed when passing types across an [FFI] boundary +/// or whenever you rely on a specific layout. +/// +/// The available representations are: +/// +/// * [`Rust`] (the default): the layout is unspecified and may change between compilations. +/// * [`C`]: the layout follows the rules of the C language for the target platform. +/// * The [primitive representations] (`u8`, `i32`, `usize`, ...): set the discriminant +/// type of an enum. +/// * [`transparent`]: the type has the same layout and ABI as its only non-zero-sized field. +/// +/// The `align(N)` and `packed(N)` modifiers raise or lower the alignment of a type, respectively. +/// `N` must be a power of two no greater than 229. The two modifiers cannot be +/// applied to the same type, and references to fields of a `packed` type cannot be created, +/// since they may be unaligned. +/// +/// # Examples +/// +/// ``` +/// #[repr(C, align(16))] +/// struct Foo { +/// first: u32, +/// second: u32, +/// third: u32, +/// } +/// +/// assert_eq!(align_of::(), 16); +/// // 12 bytes of fields, rounded up to a multiple of the alignment. +/// assert_eq!(size_of::(), 16); +/// ``` +/// +/// ``` +/// #[repr(C, packed(2))] +/// struct Foo { +/// first: u32, +/// second: u32, +/// third: u32, +/// } +/// +/// assert_eq!(align_of::(), 2); +/// assert_eq!(size_of::(), 12); +/// ``` +/// +/// ``` +/// #[repr(C)] +/// struct Foo { +/// item: T, +/// } +/// ``` +/// +/// `Foo` is laid out according to the C rules and is guaranteed to be 16-byte aligned. +/// +/// The representation is a property of the type definition, so it does +/// parameters: below, `Foo` and `Foo` both use the `C` representation. Their actual +/// layouts still differ, because they depend on `T`. +/// +/// [representation]: ../reference/type-layout.html#representations +/// [`Rust`]: ../reference/type-layout.html#the-rust-representation +/// [`C`]: ../reference/type-layout.html#the-c-representation +/// [primitive representations]: ../reference/type-layout.html#primitive-representations +/// [`transparent`]: ../reference/type-layout.html#the-transparent-representation +/// [FFI]: https://en.wikipedia.org/wiki/Foreign_function_interface +const _: () = (); + #[doc(attribute = "inline")] // /// Suggest that the compiler inline a function at its call sites.