about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs1
-rw-r--r--compiler/rustc_middle/src/traits/select.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs10
-rw-r--r--compiler/rustc_typeck/src/check/demand.rs1
-rw-r--r--src/librustdoc/clean/blanket_impl.rs3
-rw-r--r--src/test/ui/typeck/issue-89275.rs29
-rw-r--r--src/test/ui/typeck/issue-89275.stderr14
10 files changed, 82 insertions, 18 deletions
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 88a7722c9cc..b089ae22d6d 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 e236c4712c8..87495a2d5b3 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<OverflowError> 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 6447e4cbf2b..d76a098a264 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 032d402fec0..31254a0534d 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 719412492f6..277617a5685 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::<Result<Vec<_>, _>>()?;
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index e191654210a..3818e75a1de 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 1a2931b9377..540365956a8 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 8135d4a2085..c2c1d369d6e 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 00000000000..b91c0017548
--- /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>(T);
+
+pub trait Pow {
+    fn pow(self) -> Self;
+}
+
+impl<'a, T> Pow for &'a Ratio<T>
+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 00000000000..d73e647d21f
--- /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`.