]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / compiler / rustc_borrowck / src / diagnostics / bound_region_errors.rs
index 2a906e41b8cd5cc2640e99d7c0912affbc7b5066..8601fbe27f3fa27c0f0e08b181585829a22bc888 100644 (file)
@@ -1,10 +1,14 @@
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
 use rustc_infer::infer::canonical::Canonical;
 use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
 use rustc_infer::infer::region_constraints::Constraint;
+use rustc_infer::infer::region_constraints::RegionConstraintData;
+use rustc_infer::infer::RegionVariableOrigin;
 use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _};
 use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt};
 use rustc_middle::ty::error::TypeError;
+use rustc_middle::ty::RegionVid;
+use rustc_middle::ty::UniverseIndex;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_span::Span;
 use rustc_trait_selection::traits::query::type_op;
@@ -76,6 +80,15 @@ crate trait ToUniverseInfo<'tcx> {
     fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx>;
 }
 
+impl<'tcx> ToUniverseInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
+    fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
+        UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(crate::type_check::InstantiateOpaqueType {
+            base_universe: Some(base_universe),
+            ..self
+        })))
+    }
+}
+
 impl<'tcx> ToUniverseInfo<'tcx>
     for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>
 {
@@ -116,21 +129,31 @@ impl<'tcx, F, G> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::Custo
     }
 }
 
+impl<'tcx> ToUniverseInfo<'tcx> for ! {
+    fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
+        self
+    }
+}
+
 #[allow(unused_lifetimes)]
 trait TypeOpInfo<'tcx> {
     /// Returns an error to be reported if rerunning the type op fails to
     /// recover the error's cause.
-    fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx>;
+    fn fallback_error(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        span: Span,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
 
     fn base_universe(&self) -> ty::UniverseIndex;
 
     fn nice_error(
         &self,
-        tcx: TyCtxt<'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
         cause: ObligationCause<'tcx>,
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
-    ) -> Option<DiagnosticBuilder<'tcx>>;
+    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>;
 
     fn report_error(
         &self,
@@ -171,7 +194,7 @@ trait TypeOpInfo<'tcx> {
         debug!(?placeholder_region);
 
         let span = cause.span;
-        let nice_error = self.nice_error(tcx, cause, placeholder_region, error_region);
+        let nice_error = self.nice_error(mbcx, cause, placeholder_region, error_region);
 
         if let Some(nice_error) = nice_error {
             mbcx.buffer_error(nice_error);
@@ -188,7 +211,11 @@ struct PredicateQuery<'tcx> {
 }
 
 impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
-    fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
+    fn fallback_error(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        span: Span,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error");
         err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate));
         err
@@ -200,16 +227,16 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
 
     fn nice_error(
         &self,
-        tcx: TyCtxt<'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
         cause: ObligationCause<'tcx>,
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
-    ) -> Option<DiagnosticBuilder<'tcx>> {
-        tcx.infer_ctxt().enter_with_canonical(
+    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
+        mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
             cause.span,
             &self.canonical_query,
             |ref infcx, key, _| {
-                let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
+                let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
                 type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause);
                 try_extract_error_from_fulfill_cx(
                     fulfill_cx,
@@ -231,7 +258,11 @@ impl<'tcx, T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T>
 where
     T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx,
 {
-    fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
+    fn fallback_error(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        span: Span,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error");
         err.note(&format!("could not normalize `{}`", self.canonical_query.value.value.value));
         err
@@ -243,16 +274,16 @@ where
 
     fn nice_error(
         &self,
-        tcx: TyCtxt<'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
         cause: ObligationCause<'tcx>,
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
-    ) -> Option<DiagnosticBuilder<'tcx>> {
-        tcx.infer_ctxt().enter_with_canonical(
+    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
+        mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
             cause.span,
             &self.canonical_query,
             |ref infcx, key, _| {
-                let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
+                let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
 
                 let mut selcx = SelectionContext::new(infcx);
 
@@ -288,7 +319,11 @@ struct AscribeUserTypeQuery<'tcx> {
 }
 
 impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
-    fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
+    fn fallback_error(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        span: Span,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
         // and is only the fallback when the nice error fails. Consider improving this some more.
         tcx.sess.struct_span_err(span, "higher-ranked lifetime error")
@@ -300,16 +335,16 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
 
     fn nice_error(
         &self,
-        tcx: TyCtxt<'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
         cause: ObligationCause<'tcx>,
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
-    ) -> Option<DiagnosticBuilder<'tcx>> {
-        tcx.infer_ctxt().enter_with_canonical(
+    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
+        mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
             cause.span,
             &self.canonical_query,
             |ref infcx, key, _| {
-                let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
+                let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
                 type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span))
                     .ok()?;
                 try_extract_error_from_fulfill_cx(
@@ -323,22 +358,74 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
     }
 }
 
+impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
+    fn fallback_error(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        span: Span,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
+        // and is only the fallback when the nice error fails. Consider improving this some more.
+        tcx.sess.struct_span_err(span, "higher-ranked lifetime error for opaque type!")
+    }
+
+    fn base_universe(&self) -> ty::UniverseIndex {
+        self.base_universe.unwrap()
+    }
+
+    fn nice_error(
+        &self,
+        mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
+        _cause: ObligationCause<'tcx>,
+        placeholder_region: ty::Region<'tcx>,
+        error_region: Option<ty::Region<'tcx>>,
+    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
+        try_extract_error_from_region_constraints(
+            mbcx.infcx,
+            placeholder_region,
+            error_region,
+            self.region_constraints.as_ref().unwrap(),
+            // We're using the original `InferCtxt` that we
+            // started MIR borrowchecking with, so the region
+            // constraints have already been taken. Use the data from
+            // our `mbcx` instead.
+            |vid| mbcx.regioncx.var_infos[vid].origin,
+            |vid| mbcx.regioncx.var_infos[vid].universe,
+        )
+    }
+}
+
 #[instrument(skip(fulfill_cx, infcx), level = "debug")]
 fn try_extract_error_from_fulfill_cx<'tcx>(
     mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>,
     infcx: &InferCtxt<'_, 'tcx>,
     placeholder_region: ty::Region<'tcx>,
     error_region: Option<ty::Region<'tcx>>,
-) -> Option<DiagnosticBuilder<'tcx>> {
-    let tcx = infcx.tcx;
-
+) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
     // We generally shouldn't have errors here because the query was
     // already run, but there's no point using `delay_span_bug`
     // when we're going to emit an error here anyway.
     let _errors = fulfill_cx.select_all_or_error(infcx);
+    let region_constraints = infcx.with_region_constraints(|r| r.clone());
+    try_extract_error_from_region_constraints(
+        infcx,
+        placeholder_region,
+        error_region,
+        &region_constraints,
+        |vid| infcx.region_var_origin(vid),
+        |vid| infcx.universe_of_region(infcx.tcx.mk_region(ty::ReVar(vid))),
+    )
+}
 
-    let (sub_region, cause) = infcx.with_region_constraints(|region_constraints| {
-        debug!("{:#?}", region_constraints);
+fn try_extract_error_from_region_constraints<'tcx>(
+    infcx: &InferCtxt<'_, 'tcx>,
+    placeholder_region: ty::Region<'tcx>,
+    error_region: Option<ty::Region<'tcx>>,
+    region_constraints: &RegionConstraintData<'tcx>,
+    mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin,
+    mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex,
+) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
+    let (sub_region, cause) =
         region_constraints.constraints.iter().find_map(|(constraint, cause)| {
             match *constraint {
                 Constraint::RegSubReg(sub, sup) if sup == placeholder_region && sup != sub => {
@@ -346,12 +433,11 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
                 }
                 // FIXME: Should this check the universe of the var?
                 Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
-                    Some((tcx.mk_region(ty::ReVar(vid)), cause.clone()))
+                    Some((infcx.tcx.mk_region(ty::ReVar(vid)), cause.clone()))
                 }
                 _ => None,
             }
-        })
-    })?;
+        })?;
 
     debug!(?sub_region, "cause = {:#?}", cause);
     let nice_error = match (error_region, *sub_region) {
@@ -359,7 +445,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
             infcx,
             RegionResolutionError::SubSupConflict(
                 vid,
-                infcx.region_var_origin(vid),
+                region_var_origin(vid),
                 cause.clone(),
                 error_region,
                 cause.clone(),
@@ -376,8 +462,8 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
             infcx,
             RegionResolutionError::UpperBoundUniverseConflict(
                 vid,
-                infcx.region_var_origin(vid),
-                infcx.universe_of_region(sub_region),
+                region_var_origin(vid),
+                universe_of_region(vid),
                 cause.clone(),
                 placeholder_region,
             ),