about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2020-01-11 14:12:39 +0000
committerMatthew Jasper <mjjasper1@gmail.com>2020-02-14 22:40:03 +0000
commit2bd16f3c81af80718403e2e202fd0d59e8f94c60 (patch)
tree687aa391c14a967b63e33029fbf0264881b284ce
parent5cfa7d1dfb8a83c24ba3220d6740388546c664b9 (diff)
downloadrust-2bd16f3c81af80718403e2e202fd0d59e8f94c60.tar.gz
rust-2bd16f3c81af80718403e2e202fd0d59e8f94c60.zip
Improve opaque type lifetime errors
* Use better span for member constraint errors
* Avoid a bad suggestion
* Don't report member constraint errors if we have other universal
  region errors.
-rw-r--r--src/librustc/infer/error_reporting/mod.rs6
-rw-r--r--src/librustc/infer/lexical_region_resolve/mod.rs11
-rw-r--r--src/librustc/infer/opaque_types/mod.rs5
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_errors.rs23
-rw-r--r--src/librustc_mir/borrow_check/region_infer/mod.rs6
-rw-r--r--src/librustc_mir/borrow_check/region_infer/opaque_types.rs21
6 files changed, 41 insertions, 31 deletions
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 01390f2c719..327e1da64c4 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -405,17 +405,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     }
 
                     RegionResolutionError::MemberConstraintFailure {
-                        opaque_type_def_id,
                         hidden_ty,
                         member_region,
-                        span: _,
-                        choice_regions: _,
+                        span,
                     } => {
                         let hidden_ty = self.resolve_vars_if_possible(&hidden_ty);
                         opaque_types::unexpected_hidden_region_diagnostic(
                             self.tcx,
                             Some(region_scope_tree),
-                            opaque_type_def_id,
+                            span,
                             hidden_ty,
                             member_region,
                         )
diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs
index e0a8c3b4e65..1b204e5ba6c 100644
--- a/src/librustc/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc/infer/lexical_region_resolve/mod.rs
@@ -18,7 +18,6 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::implementation::{
     Direction, Graph, NodeIndex, INCOMING, OUTGOING,
 };
-use rustc_hir::def_id::DefId;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_span::Span;
 use std::fmt;
@@ -95,13 +94,7 @@ pub enum RegionResolutionError<'tcx> {
     /// Indicates a failure of a `MemberConstraint`. These arise during
     /// impl trait processing explicitly -- basically, the impl trait's hidden type
     /// included some region that it was not supposed to.
-    MemberConstraintFailure {
-        span: Span,
-        opaque_type_def_id: DefId,
-        hidden_ty: Ty<'tcx>,
-        member_region: Region<'tcx>,
-        choice_regions: Vec<Region<'tcx>>,
-    },
+    MemberConstraintFailure { span: Span, hidden_ty: Ty<'tcx>, member_region: Region<'tcx> },
 }
 
 struct RegionAndOrigin<'tcx> {
@@ -656,10 +649,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                 let span = self.tcx().def_span(member_constraint.opaque_type_def_id);
                 errors.push(RegionResolutionError::MemberConstraintFailure {
                     span,
-                    opaque_type_def_id: member_constraint.opaque_type_def_id,
                     hidden_ty: member_constraint.hidden_ty,
                     member_region,
-                    choice_regions: choice_regions.collect(),
                 });
             }
         }
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
index 4abc3ef437e..4edacd4731c 100644
--- a/src/librustc/infer/opaque_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -595,11 +595,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 pub fn unexpected_hidden_region_diagnostic(
     tcx: TyCtxt<'tcx>,
     region_scope_tree: Option<&region::ScopeTree>,
-    opaque_type_def_id: DefId,
+    span: Span,
     hidden_ty: Ty<'tcx>,
     hidden_region: ty::Region<'tcx>,
 ) -> DiagnosticBuilder<'tcx> {
-    let span = tcx.def_span(opaque_type_def_id);
     let mut err = struct_span_err!(
         tcx.sess,
         span,
@@ -851,7 +850,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
                     unexpected_hidden_region_diagnostic(
                         self.tcx,
                         None,
-                        self.opaque_type_def_id,
+                        self.tcx.def_span(self.opaque_type_def_id),
                         hidden_ty,
                         r,
                     )
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index 0e040ec7827..b393d4bc2a5 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -6,7 +6,6 @@ use rustc::infer::{
 use rustc::mir::ConstraintCategory;
 use rustc::ty::{self, RegionVid, Ty};
 use rustc_errors::{Applicability, DiagnosticBuilder};
-use rustc_hir::def_id::DefId;
 use rustc_span::symbol::kw;
 use rustc_span::Span;
 
@@ -58,8 +57,8 @@ crate enum RegionErrorKind<'tcx> {
 
     /// An unexpected hidden region for an opaque type.
     UnexpectedHiddenRegion {
-        /// The def id of the opaque type.
-        opaque_type_def_id: DefId,
+        /// The span for the member constraint.
+        span: Span,
         /// The hidden type.
         hidden_ty: Ty<'tcx>,
         /// The unexpected region.
@@ -194,18 +193,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     }
                 }
 
-                RegionErrorKind::UnexpectedHiddenRegion {
-                    opaque_type_def_id,
-                    hidden_ty,
-                    member_region,
-                } => {
+                RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, member_region } => {
                     let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
+                    let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
+                    let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
                     opaque_types::unexpected_hidden_region_diagnostic(
                         self.infcx.tcx,
                         Some(region_scope_tree),
-                        opaque_type_def_id,
-                        hidden_ty,
-                        member_region,
+                        span,
+                        named_ty,
+                        named_region,
                     )
                     .buffer(&mut self.errors_buffer);
                 }
@@ -588,6 +585,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                             {
                                 found = true;
                                 break;
+                            } else {
+                                // If there's already a lifetime bound, don't
+                                // suggest anything.
+                                return;
                             }
                         }
                     }
diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs
index 4a2f398c6d5..8435e6bc885 100644
--- a/src/librustc_mir/borrow_check/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/region_infer/mod.rs
@@ -511,7 +511,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             self.check_universal_regions(body, outlives_requirements.as_mut(), &mut errors_buffer);
         }
 
-        self.check_member_constraints(infcx, &mut errors_buffer);
+        if errors_buffer.is_empty() {
+            self.check_member_constraints(infcx, &mut errors_buffer);
+        }
 
         let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
 
@@ -1604,7 +1606,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             // If not, report an error.
             let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid));
             errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion {
-                opaque_type_def_id: m_c.opaque_type_def_id,
+                span: m_c.definition_span,
                 hidden_ty: m_c.hidden_ty,
                 member_region,
             });
diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
index f3f392683f6..71702eb84e7 100644
--- a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
+++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
@@ -1,5 +1,5 @@
 use rustc::infer::InferCtxt;
-use rustc::ty;
+use rustc::ty::{self, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
 use rustc_span::Span;
@@ -119,4 +119,23 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             })
             .collect()
     }
+
+    /// Map the regions in the type to named regions. This is similar to what
+    /// `infer_opaque_types` does, but can infer any universal region, not only
+    /// ones from the substs for the opaque type. It also doesn't double check
+    /// that the regions produced are in fact equal to the named region they are
+    /// replaced with. This is fine because this function is only to improve the
+    /// region names in error messages.
+    pub(in crate::borrow_check) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        tcx.fold_regions(&ty, &mut false, |region, _| match *region {
+            ty::ReVar(vid) => {
+                let upper_bound = self.universal_upper_bound(vid);
+                self.definitions[upper_bound].external_name.unwrap_or(region)
+            }
+            _ => region,
+        })
+    }
 }