about summary refs log tree commit diff
path: root/compiler/rustc_traits
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-09-13 17:33:40 +0000
committerMichael Goulet <michael@errs.io>2023-09-13 17:35:44 +0000
commit8fbd78ccea0e462be3d3745923d5aed8a451dc62 (patch)
tree8e144eda2c26f936a98a044189b66e6d46ad5a9e /compiler/rustc_traits
parente5fedceabf4e0564231db592b6d1f35e1ca27908 (diff)
downloadrust-8fbd78ccea0e462be3d3745923d5aed8a451dc62.tar.gz
rust-8fbd78ccea0e462be3d3745923d5aed8a451dc62.zip
Detect cycle errors hidden by opaques during monomorphization
Diffstat (limited to 'compiler/rustc_traits')
-rw-r--r--compiler/rustc_traits/src/normalize_projection_ty.rs26
1 files changed, 25 insertions, 1 deletions
diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs
index 0dbac56b47d..01bb1ca70eb 100644
--- a/compiler/rustc_traits/src/normalize_projection_ty.rs
+++ b/compiler/rustc_traits/src/normalize_projection_ty.rs
@@ -3,10 +3,13 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::query::{
     normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution,
 };
-use rustc_trait_selection::traits::{self, ObligationCause, SelectionContext};
+use rustc_trait_selection::traits::{
+    self, FulfillmentErrorCode, ObligationCause, SelectionContext,
+};
 use std::sync::atomic::Ordering;
 
 pub(crate) fn provide(p: &mut Providers) {
@@ -40,6 +43,27 @@ fn normalize_projection_ty<'tcx>(
                 &mut obligations,
             );
             ocx.register_obligations(obligations);
+            // #112047: With projections and opaques, we are able to create opaques that
+            // are recursive (given some substitution of the opaque's type variables).
+            // In that case, we may only realize a cycle error when calling
+            // `normalize_erasing_regions` in mono.
+            if !ocx.infcx.next_trait_solver() {
+                let errors = ocx.select_where_possible();
+                if !errors.is_empty() {
+                    // Rustdoc may attempt to normalize type alias types which are not
+                    // well-formed. Rustdoc also normalizes types that are just not
+                    // well-formed, since we don't do as much HIR analysis (checking
+                    // that impl vars are constrained by the signature, for example).
+                    if !tcx.sess.opts.actually_rustdoc {
+                        for error in &errors {
+                            if let FulfillmentErrorCode::CodeCycle(cycle) = &error.code {
+                                ocx.infcx.err_ctxt().report_overflow_obligation_cycle(cycle);
+                            }
+                        }
+                    }
+                    return Err(NoSolution);
+                }
+            }
             // FIXME(associated_const_equality): All users of normalize_projection_ty expected
             // a type, but there is the possibility it could've been a const now. Maybe change
             // it to a Term later?