Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use std::num::NonZero;
use std::ops::DerefMut;
use std::path::{Path, PathBuf};
use std::thread::ThreadId;
use std::{assert_matches, fmt, panic};
use std::{assert_matches, fmt, mem, panic};

use Level::*;
// Used by external projects such as `rust-gpu`.
Expand Down Expand Up @@ -339,6 +339,15 @@ struct DiagCtxtInner {
/// twice.
emitted_diagnostics: FxHashSet<Hash128>,

/// We only want to emit `recursion_depth_exceeding_limit` once per
/// crate. Otherwise crates like `calimero-store` emit more than

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of referencing calimero-store which is "fixed" by the new version of generic-array, we quickly explain why we would have tons of warnings?

/// a thousand warnings.
///
/// We only check this in `TRACK_DIAGNOSTIC` meaning that the diagnostics
/// still get tracked by the query system, even if they don't get emitted
/// to users.
emitted_recursion_depth_exceeding_limit: bool,

/// Stashed diagnostics emitted in one stage of the compiler that may be
/// stolen and emitted/cancelled by other stages (e.g. to improve them and
/// add more information). All stashed diagnostics must be emitted with
Expand Down Expand Up @@ -530,6 +539,7 @@ impl DiagCtxt {
taught_diagnostics,
emitted_diagnostic_codes,
emitted_diagnostics,
emitted_recursion_depth_exceeding_limit,
stashed_diagnostics,
future_breakage_diagnostics,
fulfilled_expectations,
Expand All @@ -550,6 +560,7 @@ impl DiagCtxt {
*taught_diagnostics = Default::default();
*emitted_diagnostic_codes = Default::default();
*emitted_diagnostics = Default::default();
*emitted_recursion_depth_exceeding_limit = false;
*stashed_diagnostics = Default::default();
*future_breakage_diagnostics = Default::default();
*fulfilled_expectations = Default::default();
Expand Down Expand Up @@ -882,7 +893,7 @@ impl<'a> DiagCtxtHandle<'a> {

pub fn emit_future_breakage_report(&self) {
let inner = &mut *self.inner.borrow_mut();
let diags = std::mem::take(&mut inner.future_breakage_diagnostics);
let diags = mem::take(&mut inner.future_breakage_diagnostics);
if !diags.is_empty() {
inner.emitter.emit_future_breakage_report(diags);
}
Expand Down Expand Up @@ -922,7 +933,7 @@ impl<'a> DiagCtxtHandle<'a> {
/// [`DiagCtxtInner`] and indicate that the linked expectation has been fulfilled.
#[must_use]
pub fn steal_fulfilled_expectation_ids(&self) -> FxIndexSet<LintExpectationId> {
std::mem::take(&mut self.inner.borrow_mut().fulfilled_expectations)
mem::take(&mut self.inner.borrow_mut().fulfilled_expectations)
}

/// Trigger an ICE if there are any delayed bugs and no hard errors.
Expand Down Expand Up @@ -1198,6 +1209,7 @@ impl DiagCtxtInner {
taught_diagnostics: Default::default(),
emitted_diagnostic_codes: Default::default(),
emitted_diagnostics: Default::default(),
emitted_recursion_depth_exceeding_limit: false,
stashed_diagnostics: Default::default(),
future_breakage_diagnostics: Vec::new(),
fulfilled_expectations: Default::default(),
Expand All @@ -1210,7 +1222,7 @@ impl DiagCtxtInner {
fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
let mut guar = None;
let has_errors = !self.err_guars.is_empty();
for (_, stashed_diagnostics) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
for (_, stashed_diagnostics) in mem::take(&mut self.stashed_diagnostics).into_iter() {
for (_, (diag, _guar, _thread)) in stashed_diagnostics {
if !diag.is_error() {
// Unless they're forced, don't flush stashed warnings when
Expand Down Expand Up @@ -1337,10 +1349,19 @@ impl DiagCtxtInner {

let is_error = diagnostic.is_error();
let is_lint = diagnostic.is_lint.is_some();
// We only emit the first occurance of `recursion_depth_exceeding_limit`.
let silence_recursion_depth_exceeded_limit =
diagnostic.is_lint.as_ref().is_some_and(|lint| {
lint.name.eq_ignore_ascii_case(
rustc_lint_defs::builtin::RECURSION_DEPTH_EXCEEDING_LIMIT.name,
) && mem::replace(&mut self.emitted_recursion_depth_exceeding_limit, true)
});

// Only emit the diagnostic if we've been asked to deduplicate or
// haven't already emitted an equivalent diagnostic.
if !(self.flags.deduplicate_diagnostics && already_emitted) {
if !silence_recursion_depth_exceeded_limit
&& !(self.flags.deduplicate_diagnostics && already_emitted)
{
debug!(?diagnostic);
debug!(?self.emitted_diagnostics);

Expand Down Expand Up @@ -1463,8 +1484,7 @@ impl DiagCtxtInner {
return;
}

let bugs: Vec<_> =
std::mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect();
let bugs: Vec<_> = mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect();

let backtrace = std::env::var_os("RUST_BACKTRACE").as_deref() != Some(OsStr::new("0"));
let decorate = backtrace || self.ice_file.is_none();
Expand Down
43 changes: 3 additions & 40 deletions compiler/rustc_middle/src/ty/context/impl_interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
use std::ops::ControlFlow;
use std::{debug_assert_matches, fmt};

use rustc_data_structures::Limit;
use rustc_data_structures::intern::Interned;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Namespace};
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::{CRATE_HIR_ID, LangItem};
use rustc_hir::LangItem;
use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_span::{DUMMY_SP, Span, Symbol};
use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverProjectionLangItem, SolverTraitLangItem};
use rustc_type_ir::{
Expand All @@ -23,7 +22,6 @@ use crate::traits::cache::WithDepNode;
use crate::traits::solve::{
self, CanonicalInput, ExternalConstraints, ExternalConstraintsData, QueryResult, inspect,
};
use crate::ty::print::{FmtPrinter, Print};
use crate::ty::{
self, BoundRegion, Clause, Const, List, ParamTy, Pattern, PolyExistentialPredicate, Predicate,
Region, RegionKind, Ty, TyCtxt,
Expand Down Expand Up @@ -682,41 +680,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
self.evaluate_root_goal_for_proof_tree_raw((canonical_goal, root_depth))
}

fn emit_next_solver_overflow_fcw(self, predicate: ty::Predicate<'tcx>, span: Span) {
self.emit_node_span_lint(
rustc_session::lint::builtin::RECURSION_DEPTH_EXCEEDING_LIMIT,
CRATE_HIR_ID,
span,
rustc_errors::DiagDecorator(|diag| {
// FIXME: share this with overflow error in fulfillment instead of duplicating.
let pred_str = {
let s = predicate.to_string();
if s.len() > 50 {
let mut p: FmtPrinter<'_, '_> =
FmtPrinter::new_with_limit(self, Namespace::TypeNS, Limit(6));
predicate.print(&mut p).unwrap();
p.into_buffer()
} else {
s
}
};
diag.primary_message(format!(
"overflow evaluating the requirement `{pred_str}`",
));
diag.help(format!(
"consider increasing the recursion limit by adding a \
`#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
self.recursion_limit() * 2,
self.crate_name(LOCAL_CRATE),
));
diag.help(
"or consider adding a manual `impl` of auto traits like `Send` for intermediate types, if auto traits are involved",
);
diag.note("this lint is attached to the whole crate and can't be disabled on a per-function basis");
}),
)
}

fn item_name(self, id: DefId) -> Symbol {
self.opt_item_name(id).unwrap_or_else(|| {
bug!("item_name: no name for {:?}", self.def_path(id));
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_next_trait_solver/src/delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,10 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
dst: <Self::Interner as Interner>::Ty,
assume: <Self::Interner as Interner>::Const,
) -> Result<Certainty, NoSolution>;

fn emit_next_solver_overflow_fcw(
&self,
predicate: <Self::Interner as Interner>::Predicate,
span: <Self::Interner as Interner>::Span,
);
}
20 changes: 10 additions & 10 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +315,9 @@ where
}

/// The old solver doesn't check depth requirement when looking up cache while the next solver
/// does so. Thus the next solver is more prone to overflow.
/// To mitigate breakages, we re-evaluate the overflowed goal with doubled recursion limit
/// and emit a FCW if it succeeds.
/// does so. Thus the next solver is more prone to overflow. To mitigate breakages, we re-evaluate
/// the overflowed goal with doubled recursion limit and emit a FCW if doing so prevents overflow.
///
/// See the doc comment on `RECURSION_DEPTH_EXCEEDING_LIMIT` and #159228 for more details.
fn maybe_evaluate_root_goal_with_higher_recursion_limit<D, I>(
delegate: &D,
Expand All @@ -344,23 +344,23 @@ fn maybe_evaluate_root_goal_with_higher_recursion_limit<D, I>(
ecx.evaluate_goal_no_fast_paths(GoalSource::Misc, goal)
});
if let Ok(goal_evaluation) = &rerun_result
&& goal_evaluation.certainty.is_yes()
&& !goal_evaluation.certainty.is_overflow()
{
Ok(rerun_result)
} else {
Err(())
}
});
if let Ok(rerun_result) = rerun_result {
delegate.cx().emit_next_solver_overflow_fcw(predicate, span);
delegate.emit_next_solver_overflow_fcw(predicate, span);
*initial_result = rerun_result;
}
}

/// The old solver doesn't check depth requirement when looking up cache while the next solver
/// does so. Thus the next solver is more prone to overflow.
/// To mitigate breakages, we re-evaluate the overflowed goal with doubled recursion limit
/// and emit a FCW if it succeeds.
/// does so. Thus the next solver is more prone to overflow. To mitigate breakages, we re-evaluate
/// the overflowed goal with doubled recursion limit and emit a FCW if doing so prevents overflow.
///
/// See the doc comment on `RECURSION_DEPTH_EXCEEDING_LIMIT` and #159228 for more details.
fn maybe_evaluate_root_goal_for_proof_tree_with_higher_recursion_limit<D, I>(
delegate: &D,
Expand Down Expand Up @@ -393,7 +393,7 @@ fn maybe_evaluate_root_goal_for_proof_tree_with_higher_recursion_limit<D, I>(
delegate.cx().recursion_limit() * 2,
);
if let Ok(response) = &new_goal_evaluation.result
&& response.value.certainty.is_yes()
&& !response.value.certainty.is_overflow()
{
Ok((new_result, new_goal_evaluation))
} else {
Expand All @@ -402,7 +402,7 @@ fn maybe_evaluate_root_goal_for_proof_tree_with_higher_recursion_limit<D, I>(
});
if let Ok(rerun_result) = rerun_result {
let predicate: I::Predicate = goal_evaluation.uncanonicalized_goal.predicate;
delegate.cx().emit_next_solver_overflow_fcw(predicate, span);
delegate.emit_next_solver_overflow_fcw(predicate, span);
*initial_result = rerun_result;
}
}
Expand Down
44 changes: 42 additions & 2 deletions compiler/rustc_trait_selection/src/solve/delegate.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use std::collections::hash_map::Entry;
use std::ops::Deref;

use rustc_data_structures::Limit;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::LangItem;
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
use rustc_hir::def::Namespace;
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE};
use rustc_hir::{CRATE_HIR_ID, LangItem};
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
use rustc_infer::infer::canonical::{
Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarKind, CanonicalVarValues,
Expand All @@ -15,6 +17,7 @@ use rustc_infer::traits::solve::{
};
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::Certainty;
use rustc_middle::ty::print::{FmtPrinter, Print};
use rustc_middle::ty::{
self, MayBeErased, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeSuperVisitable, TypeVisitable,
TypeVisitableExt, TypeVisitor, TypingMode,
Expand Down Expand Up @@ -472,4 +475,41 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
rustc_transmute::Answer::No(_) | rustc_transmute::Answer::If(_) => Err(NoSolution),
}
}

fn emit_next_solver_overflow_fcw(&self, predicate: ty::Predicate<'tcx>, span: Span) {
let tcx = self.tcx;
let predicate = self.resolve_vars_if_possible(predicate);
tcx.emit_node_span_lint(
rustc_session::lint::builtin::RECURSION_DEPTH_EXCEEDING_LIMIT,
CRATE_HIR_ID,
span,
rustc_errors::DiagDecorator(|diag| {
// FIXME: share this with overflow error in fulfillment instead of duplicating.
let pred_str = {
let s = predicate.to_string();
if s.len() > 50 {
let mut p: FmtPrinter<'_, '_> =
FmtPrinter::new_with_limit(tcx, Namespace::TypeNS, Limit(6));
predicate.print(&mut p).unwrap();
p.into_buffer()
} else {
s
}
};
diag.primary_message(format!(
"overflow evaluating the requirement `{pred_str}`",
));
diag.help(format!(
"consider increasing the recursion limit by adding a \
`#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
tcx.recursion_limit() * 2,
tcx.crate_name(LOCAL_CRATE),
));
diag.help(
"or consider adding a manual `impl` of auto traits like `Send` for intermediate types, if auto traits are involved",
);
diag.note("this lint is attached to the whole crate and can't be disabled on a per-function basis");
}),
)
}
}
2 changes: 0 additions & 2 deletions compiler/rustc_type_ir/src/interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,8 +470,6 @@ pub trait Interner:
root_depth: usize,
) -> (QueryResult<Self>, Self::Probe);

fn emit_next_solver_overflow_fcw(self, predicate: Self::Predicate, span: Self::Span);

fn item_name(self, item_index: Self::DefId) -> Self::Symbol;

fn get_anon_re_bounds_lifetime(self, idx: usize, var_idx: usize) -> Option<Region<Self>>;
Expand Down
4 changes: 1 addition & 3 deletions tests/ui/traits/next-solver/overflow-discards-constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@ fn foo<T>()

fn main() {
foo(); // register a `(): Trait<?t>` obligation
//~^ WARN: overflow evaluating the requirement `(): Trait<_>` [recursion_depth_exceeding_limit]
//~| WARN: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
//~| WARN: overflow evaluating the requirement `(): Trait<i32>` [recursion_depth_exceeding_limit]
//~^ WARN: overflow evaluating the requirement `(): Trait<i32>` [recursion_depth_exceeding_limit]
//~| WARN: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

}
16 changes: 2 additions & 14 deletions tests/ui/traits/next-solver/overflow-discards-constraints.stderr
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
warning: overflow evaluating the requirement `(): Trait<_>`
--> $DIR/overflow-discards-constraints.rs:69:5
|
LL | foo(); // register a `(): Trait<?t>` obligation
| ^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "12"]` attribute to your crate (`overflow_discards_constraints`)
= help: or consider adding a manual `impl` of auto traits like `Send` for intermediate types, if auto traits are involved
= note: this lint is attached to the whole crate and can't be disabled on a per-function basis
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #159228 <https://github.com/rust-lang/rust/issues/159228>
= note: `#[warn(recursion_depth_exceeding_limit)]` (part of `#[warn(future_incompatible)]`) on by default

warning: overflow evaluating the requirement `(): Trait<i32>`
--> $DIR/overflow-discards-constraints.rs:69:5
|
Expand All @@ -22,6 +9,7 @@ LL | foo(); // register a `(): Trait<?t>` obligation
= note: this lint is attached to the whole crate and can't be disabled on a per-function basis
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #159228 <https://github.com/rust-lang/rust/issues/159228>
= note: `#[warn(recursion_depth_exceeding_limit)]` (part of `#[warn(future_incompatible)]`) on by default

warning: 2 warnings emitted
warning: 1 warning emitted

Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,5 @@ LL | require_sync::<Foo<Foo<Foo<Foo<Foo<Foo<()>>>>>>>();
= note: for more information, see issue #159228 <https://github.com/rust-lang/rust/issues/159228>
= note: `#[warn(recursion_depth_exceeding_limit)]` (part of `#[warn(future_incompatible)]`) on by default

warning: overflow evaluating the requirement `Foo<Foo<Foo<Foo<Foo<Foo<()>>>>>>: Sync`
--> $DIR/fcw-on-auto-trait.rs:22:5
|
LL | require_sync::<Foo<Foo<Foo<Foo<Foo<Foo<()>>>>>>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "16"]` attribute to your crate (`fcw_on_auto_trait`)
= help: or consider adding a manual `impl` of auto traits like `Send` for intermediate types, if auto traits are involved
= note: this lint is attached to the whole crate and can't be disabled on a per-function basis
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #159228 <https://github.com/rust-lang/rust/issues/159228>
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

warning: 2 warnings emitted
warning: 1 warning emitted

2 changes: 0 additions & 2 deletions tests/ui/traits/next-solver/overflow/fcw-on-auto-trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,4 @@ fn main() {
require_sync::<Foo<Foo<Foo<Foo<Foo<Foo<()>>>>>>>();
//[next]~^ WARN: overflow evaluating the requirement `Foo<Foo<Foo<Foo<Foo<Foo<()>>>>>>: Sync` [recursion_depth_exceeding_limit]
//[next]~| WARN: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
//[next]~| WARN: overflow evaluating the requirement `Foo<Foo<Foo<Foo<Foo<Foo<()>>>>>>: Sync` [recursion_depth_exceeding_limit]
//[next]~| WARN: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
}
Loading