Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make note_obligation_cause_code take a impl ToPredicate for predicate #105342

Merged
Merged
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
6 changes: 2 additions & 4 deletions compiler/rustc_borrowck/src/type_check/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {

pub(super) fn prove_predicates(
&mut self,
predicates: impl IntoIterator<
Item = impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug,
>,
predicates: impl IntoIterator<Item = impl ToPredicate<'tcx> + std::fmt::Debug>,
locations: Locations,
category: ConstraintCategory<'tcx>,
) {
Expand All @@ -135,7 +133,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
pub(super) fn prove_predicate(
&mut self,
predicate: impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug,
predicate: impl ToPredicate<'tcx> + std::fmt::Debug,
locations: Locations,
category: ConstraintCategory<'tcx>,
) {
Expand Down
18 changes: 9 additions & 9 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1150,8 +1150,8 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> {
}
}

pub trait ToPredicate<'tcx, Predicate> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate;
pub trait ToPredicate<'tcx, P = Predicate<'tcx>> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P;
}

impl<'tcx, T> ToPredicate<'tcx, T> for T {
Expand All @@ -1160,21 +1160,21 @@ impl<'tcx, T> ToPredicate<'tcx, T> for T {
}
}

impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Binder<'tcx, PredicateKind<'tcx>> {
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
tcx.mk_predicate(self)
}
}

impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Clause<'tcx> {
impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self)))
}
}

impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
Expand All @@ -1193,25 +1193,25 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef
}
}

impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyTraitPredicate<'tcx> {
impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(|p| PredicateKind::Clause(Clause::Trait(p))).to_predicate(tcx)
}
}

impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyRegionOutlivesPredicate<'tcx> {
impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx)
}
}

impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyTypeOutlivesPredicate<'tcx> {
impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(|p| PredicateKind::Clause(Clause::TypeOutlives(p))).to_predicate(tcx)
}
}

impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyProjectionPredicate<'tcx> {
impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx)
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub fn codegen_select_candidate<'tcx>(
// `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization.
for err in errors {
if let FulfillmentErrorCode::CodeCycle(cycle) = err.code {
infcx.err_ctxt().report_overflow_error_cycle(&cycle);
infcx.err_ctxt().report_overflow_obligation_cycle(&cycle);
}
}
return Err(CodegenObligationError::FulfillmentError);
Expand Down
84 changes: 63 additions & 21 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,26 +99,36 @@ pub trait InferCtxtExt<'tcx> {
}

pub trait TypeErrCtxtExt<'tcx> {
fn report_overflow_error<T>(
&self,
predicate: &T,
span: Span,
suggest_increasing_limit: bool,
mutate: impl FnOnce(&mut Diagnostic),
) -> !
where
T: fmt::Display
+ TypeFoldable<'tcx>
+ Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
<T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;

fn report_fulfillment_errors(
&self,
errors: &[FulfillmentError<'tcx>],
body_id: Option<hir::BodyId>,
) -> ErrorGuaranteed;

fn report_overflow_error<T>(
fn report_overflow_obligation<T>(
&self,
obligation: &Obligation<'tcx, T>,
suggest_increasing_limit: bool,
) -> !
where
T: fmt::Display
+ TypeFoldable<'tcx>
+ Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
<T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
T: ToPredicate<'tcx> + Clone;

fn suggest_new_overflow_limit(&self, err: &mut Diagnostic);

fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;

/// The `root_obligation` parameter should be the `root_obligation` field
/// from a `FulfillmentError`. If no `FulfillmentError` is available,
Expand Down Expand Up @@ -458,17 +468,20 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
/// occurrences in any case.
fn report_overflow_error<T>(
&self,
obligation: &Obligation<'tcx, T>,
predicate: &T,
span: Span,
suggest_increasing_limit: bool,
mutate: impl FnOnce(&mut Diagnostic),
) -> !
where
T: fmt::Display
+ TypeFoldable<'tcx>
+ Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
<T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
{
let predicate = self.resolve_vars_if_possible(obligation.predicate.clone());
let predicate = self.resolve_vars_if_possible(predicate.clone());
let mut pred_str = predicate.to_string();

if pred_str.len() > 50 {
// We don't need to save the type to a file, we will be talking about this type already
// in a separate note when we explain the obligation, so it will be available that way.
Expand All @@ -483,7 +496,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
let mut err = struct_span_err!(
self.tcx.sess,
obligation.cause.span,
span,
E0275,
"overflow evaluating the requirement `{}`",
pred_str,
Expand All @@ -493,20 +506,46 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.suggest_new_overflow_limit(&mut err);
}

self.note_obligation_cause_code(
&mut err,
&obligation.predicate,
obligation.param_env,
obligation.cause.code(),
&mut vec![],
&mut Default::default(),
);
mutate(&mut err);

err.emit();
self.tcx.sess.abort_if_errors();
bug!();
}

/// Reports that an overflow has occurred and halts compilation. We
/// halt compilation unconditionally because it is important that
/// overflows never be masked -- they basically represent computations
/// whose result could not be truly determined and thus we can't say
/// if the program type checks or not -- and they are unusual
/// occurrences in any case.
fn report_overflow_obligation<T>(
&self,
obligation: &Obligation<'tcx, T>,
suggest_increasing_limit: bool,
) -> !
where
T: ToPredicate<'tcx> + Clone,
{
let predicate = obligation.predicate.clone().to_predicate(self.tcx);
let predicate = self.resolve_vars_if_possible(predicate);
self.report_overflow_error(
&predicate,
obligation.cause.span,
suggest_increasing_limit,
|err| {
self.note_obligation_cause_code(
err,
&predicate,
obligation.param_env,
obligation.cause.code(),
&mut vec![],
&mut Default::default(),
);
},
);
}

fn suggest_new_overflow_limit(&self, err: &mut Diagnostic) {
let suggested_limit = match self.tcx.recursion_limit() {
Limit(0) => Limit(2),
Expand All @@ -521,19 +560,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}

/// Reports that a cycle was detected which led to overflow and halts
/// compilation. This is equivalent to `report_overflow_error` except
/// compilation. This is equivalent to `report_overflow_obligation` except
/// that we can give a more helpful error message (and, in particular,
/// we do not suggest increasing the overflow limit, which is not
/// going to help).
fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
let cycle = self.resolve_vars_if_possible(cycle.to_owned());
assert!(!cycle.is_empty());

debug!(?cycle, "report_overflow_error_cycle");

// The 'deepest' obligation is most likely to have a useful
// cause 'backtrace'
self.report_overflow_error(cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(), false);
self.report_overflow_obligation(
cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(),
false,
);
}

fn report_selection_error(
Expand Down Expand Up @@ -1554,7 +1596,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
diag.emit();
}
FulfillmentErrorCode::CodeCycle(ref cycle) => {
self.report_overflow_error_cycle(cycle);
self.report_overflow_obligation_cycle(cycle);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ pub trait TypeErrCtxtExt<'tcx> {
obligated_types: &mut Vec<Ty<'tcx>>,
seen_requirements: &mut FxHashSet<DefId>,
) where
T: fmt::Display + ToPredicate<'tcx, T>;
T: fmt::Display + ToPredicate<'tcx>;

/// Suggest to await before try: future? => future.await?
fn suggest_await_before_try(
Expand Down Expand Up @@ -2353,7 +2353,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
obligated_types: &mut Vec<Ty<'tcx>>,
seen_requirements: &mut FxHashSet<DefId>,
) where
T: fmt::Display,
T: fmt::Display + ToPredicate<'tcx>,
{
let tcx = self.tcx;
match *cause_code {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
fn pred_known_to_hold_modulo_regions<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
pred: impl ToPredicate<'tcx, ty::Predicate<'tcx>> + TypeVisitable<'tcx>,
pred: impl ToPredicate<'tcx> + TypeVisitable<'tcx>,
span: Span,
) -> bool {
let has_non_region_infer = pred.has_non_region_infer();
Expand Down
12 changes: 5 additions & 7 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,14 +504,12 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
Reveal::All => {
let recursion_limit = self.tcx().recursion_limit();
if !recursion_limit.value_within_limit(self.depth) {
let obligation = Obligation::with_depth(
self.tcx(),
self.cause.clone(),
recursion_limit.0,
self.param_env,
ty,
self.selcx.infcx.err_ctxt().report_overflow_error(
&ty,
self.cause.span,
true,
|_| {},
);
self.selcx.infcx.err_ctxt().report_overflow_error(&obligation, true);
}

let substs = substs.fold_with(self);
Expand Down
14 changes: 6 additions & 8 deletions compiler/rustc_trait_selection/src/traits/query/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::infer::canonical::OriginalQueryValues;
use crate::infer::{InferCtxt, InferOk};
use crate::traits::error_reporting::TypeErrCtxtExt;
use crate::traits::project::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
use crate::traits::{ObligationCause, PredicateObligation, Reveal};
use rustc_data_structures::sso::SsoHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_infer::traits::Normalized;
Expand Down Expand Up @@ -214,14 +214,12 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
let substs = substs.try_fold_with(self)?;
let recursion_limit = self.tcx().recursion_limit();
if !recursion_limit.value_within_limit(self.anon_depth) {
let obligation = Obligation::with_depth(
self.tcx(),
self.cause.clone(),
recursion_limit.0,
self.param_env,
ty,
self.infcx.err_ctxt().report_overflow_error(
&ty,
self.cause.span,
true,
|_| {},
);
self.infcx.err_ctxt().report_overflow_error(&obligation, true);
}

let generic_ty = self.tcx().bound_type_of(def_id);
Expand Down
13 changes: 3 additions & 10 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::print::{FmtPrinter, Print};
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::SubstsRef;
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
Expand Down Expand Up @@ -1313,18 +1312,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
error_obligation: &Obligation<'tcx, T>,
) -> Result<(), OverflowError>
where
T: fmt::Display
+ TypeFoldable<'tcx>
+ Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
<T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
T: ToPredicate<'tcx> + Clone,
{
if !self.infcx.tcx.recursion_limit().value_within_limit(depth) {
match self.query_mode {
TraitQueryMode::Standard => {
if let Some(e) = self.infcx.tainted_by_errors() {
return Err(OverflowError::Error(e));
}
self.infcx.err_ctxt().report_overflow_error(error_obligation, true);
self.infcx.err_ctxt().report_overflow_obligation(error_obligation, true);
}
TraitQueryMode::Canonical => {
return Err(OverflowError::Canonical);
Expand All @@ -1345,10 +1341,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
error_obligation: &Obligation<'tcx, V>,
) -> Result<(), OverflowError>
where
V: fmt::Display
+ TypeFoldable<'tcx>
+ Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
<V as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
V: ToPredicate<'tcx> + Clone,
{
self.check_recursion_depth(obligation.recursion_depth, error_obligation)
}
Expand Down