about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-05-24 17:11:40 +0000
committerMichael Goulet <michael@errs.io>2023-05-25 17:17:07 +0000
commit91525a43243e088abb34fca3d43fd8588b8667e0 (patch)
treec050a71b1d9b243a49bad1fe68920e2ef418e1c6
parentcade26637fe1c23965ce644299ed5200db7c92dd (diff)
downloadrust-91525a43243e088abb34fca3d43fd8588b8667e0.tar.gz
rust-91525a43243e088abb34fca3d43fd8588b8667e0.zip
Use ErrorGuaranteed more in MIR type ops
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs45
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs21
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs16
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs54
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs24
8 files changed, 104 insertions, 107 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 95dcc8d4b19..f527eee7bda 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -1,12 +1,12 @@
 use std::fmt;
 
+use rustc_errors::ErrorGuaranteed;
 use rustc_infer::infer::canonical::Canonical;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
 use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
-use rustc_trait_selection::traits::query::{Fallible, NoSolution};
 use rustc_trait_selection::traits::ObligationCause;
 
 use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
@@ -30,14 +30,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         locations: Locations,
         category: ConstraintCategory<'tcx>,
         op: Op,
-    ) -> Fallible<R>
+    ) -> Result<R, ErrorGuaranteed>
     where
         Op: type_op::TypeOp<'tcx, Output = R>,
         Op::ErrorInfo: ToUniverseInfo<'tcx>,
     {
         let old_universe = self.infcx.universe();
 
-        let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?;
+        let TypeOpOutput { output, constraints, error_info } =
+            op.fully_perform(self.infcx, locations.span(self.body))?;
 
         debug!(?output, ?constraints);
 
@@ -135,14 +136,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     ) {
         let param_env = self.param_env;
         let predicate = predicate.to_predicate(self.tcx());
-        self.fully_perform_op(
+        let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             locations,
             category,
             param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)),
-        )
-        .unwrap_or_else(|NoSolution| {
-            span_mirbug!(self, NoSolution, "could not prove {:?}", predicate);
-        })
+        );
     }
 
     pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
@@ -163,15 +161,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
     {
         let param_env = self.param_env;
-        self.fully_perform_op(
+        let result: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             location.to_locations(),
             category,
             param_env.and(type_op::normalize::Normalize::new(value)),
-        )
-        .unwrap_or_else(|NoSolution| {
-            span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value);
-            value
-        })
+        );
+        result.unwrap_or(value)
     }
 
     #[instrument(skip(self), level = "debug")]
@@ -181,18 +176,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         user_ty: ty::UserType<'tcx>,
         span: Span,
     ) {
-        self.fully_perform_op(
+        let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             Locations::All(span),
             ConstraintCategory::Boring,
             self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(mir_ty, user_ty)),
-        )
-        .unwrap_or_else(|err| {
-            span_mirbug!(
-                self,
-                span,
-                "ascribe_user_type `{mir_ty:?}=={user_ty:?}` failed with `{err:?}`",
-            );
-        });
+        );
     }
 
     /// *Incorrectly* skips the WF checks we normally do in `ascribe_user_type`.
@@ -219,7 +207,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
         let cause = ObligationCause::dummy_with_span(span);
         let param_env = self.param_env;
-        self.fully_perform_op(
+        let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
             Locations::All(span),
             ConstraintCategory::Boring,
             type_op::custom::CustomTypeOp::new(
@@ -230,13 +218,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 },
                 "ascribe_user_type_skip_wf",
             ),
-        )
-        .unwrap_or_else(|err| {
-            span_mirbug!(
-                self,
-                span,
-                "ascribe_user_type_skip_wf `{mir_ty:?}=={user_ty:?}` failed with `{err:?}`",
-            );
-        });
+        );
     }
 }
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index bd01c0b504c..c8ec1257d37 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -8,7 +8,7 @@ use rustc_infer::infer::InferCtxt;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::traits::query::OutlivesBound;
 use rustc_middle::ty::{self, RegionVid, Ty};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
 use std::rc::Rc;
 use type_op::TypeOpOutput;
@@ -243,18 +243,11 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
             let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
                 .param_env
                 .and(type_op::normalize::Normalize::new(ty))
-                .fully_perform(self.infcx)
-                .unwrap_or_else(|_| {
-                    let guar = self
-                        .infcx
-                        .tcx
-                        .sess
-                        .delay_span_bug(span, format!("failed to normalize {:?}", ty));
-                    TypeOpOutput {
-                        output: self.infcx.tcx.ty_error(guar),
-                        constraints: None,
-                        error_info: None,
-                    }
+                .fully_perform(self.infcx, span)
+                .unwrap_or_else(|guar| TypeOpOutput {
+                    output: self.infcx.tcx.ty_error(guar),
+                    constraints: None,
+                    error_info: None,
                 });
             if let Some(c) = constraints_normalize {
                 constraints.push(c)
@@ -324,7 +317,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
         let TypeOpOutput { output: bounds, constraints, .. } = self
             .param_env
             .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
-            .fully_perform(self.infcx)
+            .fully_perform(self.infcx, DUMMY_SP)
             .unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty));
         debug!(?bounds, ?constraints);
         self.add_outlives_bounds(bounds);
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 9731b10aa99..fd94ac86d7d 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -4,6 +4,7 @@ use rustc_index::interval::IntervalSet;
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
 use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
+use rustc_span::DUMMY_SP;
 use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult;
 use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
 use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
@@ -568,10 +569,15 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
     ) -> DropData<'tcx> {
         debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
 
-        let param_env = typeck.param_env;
-        let TypeOpOutput { output, constraints, .. } =
-            param_env.and(DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx).unwrap();
-
-        DropData { dropck_result: output, region_constraint_data: constraints }
+        match typeck
+            .param_env
+            .and(DropckOutlives::new(dropped_ty))
+            .fully_perform(typeck.infcx, DUMMY_SP)
+        {
+            Ok(TypeOpOutput { output, constraints, .. }) => {
+                DropData { dropck_result: output, region_constraint_data: constraints }
+            }
+            Err(_) => DropData { dropck_result: Default::default(), region_constraint_data: None },
+        }
     }
 }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index cf204cff6b3..b2693e60546 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -10,6 +10,7 @@ use either::Either;
 use hir::OpaqueTyOrigin;
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
+use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
@@ -216,24 +217,22 @@ pub(crate) fn type_check<'mir, 'tcx>(
     let opaque_type_values = opaque_type_values
         .into_iter()
         .map(|(opaque_type_key, decl)| {
-            checker
-                .fully_perform_op(
-                    Locations::All(body.span),
-                    ConstraintCategory::OpaqueType,
-                    CustomTypeOp::new(
-                        |ocx| {
-                            ocx.infcx.register_member_constraints(
-                                param_env,
-                                opaque_type_key,
-                                decl.hidden_type.ty,
-                                decl.hidden_type.span,
-                            );
-                            Ok(())
-                        },
-                        "opaque_type_map",
-                    ),
-                )
-                .unwrap();
+            let _: Result<_, ErrorGuaranteed> = checker.fully_perform_op(
+                Locations::All(body.span),
+                ConstraintCategory::OpaqueType,
+                CustomTypeOp::new(
+                    |ocx| {
+                        ocx.infcx.register_member_constraints(
+                            param_env,
+                            opaque_type_key,
+                            decl.hidden_type.ty,
+                            decl.hidden_type.span,
+                        );
+                        Ok(())
+                    },
+                    "opaque_type_map",
+                ),
+            );
             let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
             trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
             if hidden_type.has_non_region_infer() {
@@ -2755,11 +2754,20 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
     /// constraints in our `InferCtxt`
     type ErrorInfo = InstantiateOpaqueType<'tcx>;
 
-    fn fully_perform(mut self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
-        let (mut output, region_constraints) = scrape_region_constraints(infcx, |ocx| {
-            ocx.register_obligations(self.obligations.clone());
-            Ok(())
-        })?;
+    fn fully_perform(
+        mut self,
+        infcx: &InferCtxt<'tcx>,
+        span: Span,
+    ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
+        let (mut output, region_constraints) = scrape_region_constraints(
+            infcx,
+            |ocx| {
+                ocx.register_obligations(self.obligations.clone());
+                Ok(())
+            },
+            "InstantiateOpaqueType",
+            span,
+        )?;
         self.region_constraints = Some(region_constraints);
         output.error_info = Some(self);
         Ok(output)
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index dd1f89e5b91..6f3451d5657 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,3 +1,4 @@
+use rustc_errors::ErrorGuaranteed;
 use rustc_infer::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_infer::traits::PredicateObligations;
@@ -185,7 +186,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
     }
 
     fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
-        match self.type_checker.fully_perform_op(
+        let _: Result<_, ErrorGuaranteed> = self.type_checker.fully_perform_op(
             self.locations,
             self.category,
             InstantiateOpaqueType {
@@ -194,16 +195,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
                 base_universe: None,
                 region_constraints: None,
             },
-        ) {
-            Ok(()) => {}
-            Err(_) => {
-                // It's a bit redundant to delay a bug here, but I'd rather
-                // delay more bugs than accidentally not delay a bug at all.
-                self.type_checker.tcx().sess.delay_span_bug(
-                    self.locations.span(self.type_checker.body),
-                    "errors selecting obligation during MIR typeck",
-                );
-            }
-        };
+        );
     }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index 0db80232891..0e797a1cb60 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -1,8 +1,8 @@
 use crate::infer::InferCtxt;
 use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput};
-use crate::traits::query::NoSolution;
 use crate::traits::{ObligationCause, ObligationCtxt};
 use rustc_data_structures::fx::FxIndexSet;
+use rustc_errors::ErrorGuaranteed;
 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
 use rustc_middle::ty::{self, ParamEnv, Ty, TypeFolder, TypeVisitableExt};
 use rustc_span::def_id::LocalDefId;
@@ -69,16 +69,12 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
         }
 
         let span = self.tcx.def_span(body_id);
-        let result = param_env
+        let result: Result<_, ErrorGuaranteed> = param_env
             .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
-            .fully_perform(self);
+            .fully_perform(self, span);
         let result = match result {
             Ok(r) => r,
-            Err(NoSolution) => {
-                self.tcx.sess.delay_span_bug(
-                    span,
-                    "implied_outlives_bounds failed to solve all obligations",
-                );
+            Err(_) => {
                 return vec![];
             }
         };
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
index 3d6c1d9e2b0..94464895f3b 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
@@ -3,9 +3,10 @@ use crate::infer::InferCtxt;
 use crate::traits::query::type_op::TypeOpOutput;
 use crate::traits::query::Fallible;
 use crate::traits::ObligationCtxt;
+use rustc_errors::ErrorGuaranteed;
 use rustc_infer::infer::region_constraints::RegionConstraintData;
-use rustc_middle::traits::query::NoSolution;
 use rustc_span::source_map::DUMMY_SP;
+use rustc_span::Span;
 
 use std::fmt;
 
@@ -35,12 +36,16 @@ where
     /// Processes the operation and all resulting obligations,
     /// returning the final result along with any region constraints
     /// (they will be given over to the NLL region solver).
-    fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
+    fn fully_perform(
+        self,
+        infcx: &InferCtxt<'tcx>,
+        span: Span,
+    ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
         if cfg!(debug_assertions) {
             info!("fully_perform({:?})", self);
         }
 
-        Ok(scrape_region_constraints(infcx, self.closure)?.0)
+        Ok(scrape_region_constraints(infcx, self.closure, self.description, span)?.0)
     }
 }
 
@@ -55,7 +60,9 @@ impl<F> fmt::Debug for CustomTypeOp<F> {
 pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
     infcx: &InferCtxt<'tcx>,
     op: impl FnOnce(&ObligationCtxt<'_, 'tcx>) -> Fallible<R>,
-) -> Fallible<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>)> {
+    name: &'static str,
+    span: Span,
+) -> Result<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>), ErrorGuaranteed> {
     // During NLL, we expect that nobody will register region
     // obligations **except** as part of a custom type op (and, at the
     // end of each custom type op, we scrape out the region
@@ -70,16 +77,17 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
 
     let value = infcx.commit_if_ok(|_| {
         let ocx = ObligationCtxt::new_in_snapshot(infcx);
-        let value = op(&ocx)?;
+        let value = op(&ocx).map_err(|_| {
+            infcx.tcx.sess.delay_span_bug(span, format!("error performing operation: {name}"))
+        })?;
         let errors = ocx.select_all_or_error();
         if errors.is_empty() {
             Ok(value)
         } else {
-            infcx.tcx.sess.delay_span_bug(
+            Err(infcx.tcx.sess.delay_span_bug(
                 DUMMY_SP,
                 format!("errors selecting obligation during MIR typeck: {:?}", errors),
-            );
-            Err(NoSolution)
+            ))
         }
     })?;
 
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index 9e8bc8bce9a..a34ea3fb3dd 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -4,11 +4,12 @@ use crate::infer::canonical::{
 use crate::infer::{InferCtxt, InferOk};
 use crate::traits::query::Fallible;
 use crate::traits::ObligationCause;
+use rustc_errors::ErrorGuaranteed;
 use rustc_infer::infer::canonical::Certainty;
-use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::PredicateObligations;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
+use rustc_span::Span;
 use std::fmt;
 
 pub mod ascribe_user_type;
@@ -32,7 +33,11 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug {
     /// Processes the operation and all resulting obligations,
     /// returning the final result along with any region constraints
     /// (they will be given over to the NLL region solver).
-    fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>>;
+    fn fully_perform(
+        self,
+        infcx: &InferCtxt<'tcx>,
+        span: Span,
+    ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed>;
 }
 
 /// The output from performing a type op
@@ -120,10 +125,16 @@ where
     type Output = Q::QueryResponse;
     type ErrorInfo = Canonical<'tcx, ParamEnvAnd<'tcx, Q>>;
 
-    fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
+    fn fully_perform(
+        self,
+        infcx: &InferCtxt<'tcx>,
+        span: Span,
+    ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
         let mut region_constraints = QueryRegionConstraints::default();
         let (output, error_info, mut obligations, _) =
-            Q::fully_perform_into(self, infcx, &mut region_constraints)?;
+            Q::fully_perform_into(self, infcx, &mut region_constraints).map_err(|_| {
+                infcx.tcx.sess.delay_span_bug(span, format!("error performing {self:?}"))
+            })?;
 
         // Typically, instantiating NLL query results does not
         // create obligations. However, in some cases there
@@ -151,7 +162,10 @@ where
                 }
             }
             if !progress {
-                return Err(NoSolution);
+                return Err(infcx.tcx.sess.delay_span_bug(
+                    span,
+                    format!("ambiguity processing {obligations:?} from {self:?}"),
+                ));
             }
         }