diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 88a7722c9ccf0..b089ae22d6d98 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -449,6 +449,7 @@ pub enum SelectionError<'tcx> { TraitNotObjectSafe(DefId), NotConstEvaluatable(NotConstEvaluatable), Overflow, + ErrorReporting, } /// When performing resolution, it is typically the case that there diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index e236c4712c883..87495a2d5b3ec 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -261,12 +261,18 @@ impl EvaluationResult { } } -/// Indicates that trait evaluation caused overflow. +/// Indicates that trait evaluation caused overflow and in which pass. #[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)] -pub struct OverflowError; +pub enum OverflowError { + Cannonical, + ErrorReporting, +} impl<'tcx> From for SelectionError<'tcx> { - fn from(OverflowError: OverflowError) -> SelectionError<'tcx> { - SelectionError::Overflow + fn from(overflow_error: OverflowError) -> SelectionError<'tcx> { + match overflow_error { + OverflowError::Cannonical => SelectionError::Overflow, + OverflowError::ErrorReporting => SelectionError::ErrorReporting, + } } } 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 6447e4cbf2bf6..d76a098a264c6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -842,6 +842,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { Overflow => { bug!("overflow should be handled before the `report_selection_error` path"); } + SelectionError::ErrorReporting => { + bug!("ErrorReporting Overflow should not reach `report_selection_err` call") + } }; self.note_obligation_cause(&mut err, &obligation); diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index 032d402fec045..31254a0534d76 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -83,17 +83,21 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { ) -> EvaluationResult { match self.evaluate_obligation(obligation) { Ok(result) => result, - Err(OverflowError) => { + Err(OverflowError::Cannonical) => { let mut selcx = SelectionContext::with_query_mode(&self, TraitQueryMode::Standard); - selcx.evaluate_root_obligation(obligation).unwrap_or_else(|r| { - span_bug!( - obligation.cause.span, - "Overflow should be caught earlier in standard query mode: {:?}, {:?}", - obligation, - r, - ) + selcx.evaluate_root_obligation(obligation).unwrap_or_else(|r| match r { + OverflowError::Cannonical => { + span_bug!( + obligation.cause.span, + "Overflow should be caught earlier in standard query mode: {:?}, {:?}", + obligation, + r, + ) + } + OverflowError::ErrorReporting => EvaluationResult::EvaluatedToErr, }) } + Err(OverflowError::ErrorReporting) => EvaluationResult::EvaluatedToErr, } } } 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 719412492f637..277617a5685d6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -13,7 +13,7 @@ use rustc_target::spec::abi::Abi; use crate::traits::coherence::Conflict; use crate::traits::{util, SelectionResult}; -use crate::traits::{Overflow, Unimplemented}; +use crate::traits::{ErrorReporting, Overflow, Unimplemented}; use super::BuiltinImplConditions; use super::IntercrateAmbiguityCause; @@ -156,7 +156,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval })) } Ok(_) => Ok(None), - Err(OverflowError) => Err(Overflow), + Err(OverflowError::Cannonical) => Err(Overflow), + Err(OverflowError::ErrorReporting) => Err(ErrorReporting), }) .flat_map(Result::transpose) .collect::, _>>()?; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e191654210a43..3818e75a1de04 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -20,8 +20,8 @@ use super::ObligationCauseCode; use super::Selection; use super::SelectionResult; use super::TraitQueryMode; +use super::{ErrorReporting, Overflow, SelectionError, Unimplemented}; use super::{ObligationCause, PredicateObligation, TraitObligation}; -use super::{Overflow, SelectionError, Unimplemented}; use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::traits::error_reporting::InferCtxtExt; @@ -900,7 +900,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.candidate_from_obligation(stack) { Ok(Some(c)) => self.evaluate_candidate(stack, &c), Ok(None) => Ok(EvaluatedToAmbig), - Err(Overflow) => Err(OverflowError), + Err(Overflow) => Err(OverflowError::Cannonical), + Err(ErrorReporting) => Err(OverflowError::ErrorReporting), Err(..) => Ok(EvaluatedToErr), } } @@ -1057,10 +1058,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if !self.infcx.tcx.recursion_limit().value_within_limit(depth) { match self.query_mode { TraitQueryMode::Standard => { + if self.infcx.is_tainted_by_errors() { + return Err(OverflowError::ErrorReporting); + } self.infcx.report_overflow_error(error_obligation, true); } TraitQueryMode::Canonical => { - return Err(OverflowError); + return Err(OverflowError::Cannonical); } } } diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 1a2931b9377ce..540365956a8fb 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -140,6 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Err(e) => e, }; + self.set_tainted_by_errors(); let expr = expr.peel_drop_temps(); let cause = self.misc(expr.span); let expr_ty = self.resolve_vars_with_obligations(checked_ty); diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 8135d4a2085dd..c2c1d369d6e8a 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -78,7 +78,8 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { ); match infcx.evaluate_obligation(&obligation) { Ok(eval_result) if eval_result.may_apply() => {} - Err(traits::OverflowError) => {} + Err(traits::OverflowError::Cannonical) => {} + Err(traits::OverflowError::ErrorReporting) => {} _ => { return false; } diff --git a/src/test/ui/typeck/issue-89275.rs b/src/test/ui/typeck/issue-89275.rs new file mode 100644 index 0000000000000..b91c001754872 --- /dev/null +++ b/src/test/ui/typeck/issue-89275.rs @@ -0,0 +1,29 @@ +#![recursion_limit = "5"] // To reduce noise + +//expect mutability error when ambiguous traits are in scope +//and not an overflow error on the span in the main function. + +struct Ratio(T); + +pub trait Pow { + fn pow(self) -> Self; +} + +impl<'a, T> Pow for &'a Ratio +where + &'a T: Pow, +{ + fn pow(self) -> Self { + self + } +} + +fn downcast<'a, W: ?Sized>() -> &'a W { + todo!() +} + +struct Other; + +fn main() { + let other: &mut Other = downcast();//~ERROR 28:29: 28:39: mismatched types [E0308] +} diff --git a/src/test/ui/typeck/issue-89275.stderr b/src/test/ui/typeck/issue-89275.stderr new file mode 100644 index 0000000000000..d73e647d21f6b --- /dev/null +++ b/src/test/ui/typeck/issue-89275.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-89275.rs:28:29 + | +LL | let other: &mut Other = downcast(); + | ---------- ^^^^^^^^^^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut Other` + found reference `&_` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`.