From e940f845be13ff37d4ba28df5f40d74e5b0895a0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Dec 2022 00:00:01 +0000 Subject: [PATCH 1/2] drive-by: Default param for ToPredicate --- .../rustc_borrowck/src/type_check/canonical.rs | 6 ++---- compiler/rustc_middle/src/ty/mod.rs | 18 +++++++++--------- .../rustc_trait_selection/src/traits/mod.rs | 2 +- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 1aad6738bba7a..3617bf58be9dd 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -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 + std::fmt::Debug>, locations: Locations, category: ConstraintCategory<'tcx>, ) { @@ -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>, ) { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index dd4ab3e8d30bf..81847e2e4cab6 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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 { @@ -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); @@ -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) } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index c6818a4e57d42..d3cfd61e1956d 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -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(); From d2a80c157145d0c1e6fd6669862358de6cd89185 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Dec 2022 00:19:42 +0000 Subject: [PATCH 2/2] Avoid noting cause code (which is usually misc, b/c codegen) for opaque type reveal overflow --- .../src/traits/codegen.rs | 2 +- .../src/traits/error_reporting/mod.rs | 84 ++++++++++++++----- .../src/traits/error_reporting/suggestions.rs | 4 +- .../src/traits/project.rs | 12 ++- .../src/traits/query/normalize.rs | 14 ++-- .../src/traits/select/mod.rs | 13 +-- 6 files changed, 80 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index 61743d78e9e80..0102d268b42e1 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -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); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 56dea916b305f..80870d871d163 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -99,26 +99,36 @@ pub trait InferCtxtExt<'tcx> { } pub trait TypeErrCtxtExt<'tcx> { + fn report_overflow_error( + &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>>, + >>::Error: std::fmt::Debug; + fn report_fulfillment_errors( &self, errors: &[FulfillmentError<'tcx>], body_id: Option, ) -> ErrorGuaranteed; - fn report_overflow_error( + fn report_overflow_obligation( &self, obligation: &Obligation<'tcx, T>, suggest_increasing_limit: bool, ) -> ! where - T: fmt::Display - + TypeFoldable<'tcx> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = 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, @@ -458,8 +468,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { /// occurrences in any case. fn report_overflow_error( &self, - obligation: &Obligation<'tcx, T>, + predicate: &T, + span: Span, suggest_increasing_limit: bool, + mutate: impl FnOnce(&mut Diagnostic), ) -> ! where T: fmt::Display @@ -467,8 +479,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = 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. @@ -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, @@ -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( + &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), @@ -521,11 +560,11 @@ 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()); @@ -533,7 +572,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // 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( @@ -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); } } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 1740128727a5a..6ea54b625bbc0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -298,7 +298,7 @@ pub trait TypeErrCtxtExt<'tcx> { obligated_types: &mut Vec>, seen_requirements: &mut FxHashSet, ) 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( @@ -2353,7 +2353,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { obligated_types: &mut Vec>, seen_requirements: &mut FxHashSet, ) where - T: fmt::Display, + T: fmt::Display + ToPredicate<'tcx>, { let tcx = self.tcx; match *cause_code { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 051660be9c474..1790ef5b4814e 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -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); diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index f899321fc01e1..7ad532d8a3464 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -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; @@ -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); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 8835f2cc1b97a..035deb6163981 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -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}; @@ -1313,10 +1312,7 @@ 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>>, - >>::Error: std::fmt::Debug, + T: ToPredicate<'tcx> + Clone, { if !self.infcx.tcx.recursion_limit().value_within_limit(depth) { match self.query_mode { @@ -1324,7 +1320,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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); @@ -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>>, - >>::Error: std::fmt::Debug, + V: ToPredicate<'tcx> + Clone, { self.check_recursion_depth(obligation.recursion_depth, error_obligation) }