about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2020-02-15 12:11:59 +0000
committerMatthew Jasper <mjjasper1@gmail.com>2020-03-17 09:07:56 +0000
commit0a7f16e7d851f99816114cbc830c662d55376fbd (patch)
tree96c82e5e86c6658519be36698a6e33eb009da95a
parentcefd0305b1e67ad95f86c273e5cf76f189a7206e (diff)
downloadrust-0a7f16e7d851f99816114cbc830c662d55376fbd.tar.gz
rust-0a7f16e7d851f99816114cbc830c662d55376fbd.zip
Erase regions in writeback
Also skip duplicated region solving entirely with `-Zborrowck=mir`.
-rw-r--r--src/librustc_infer/infer/error_reporting/mod.rs13
-rw-r--r--src/librustc_infer/infer/lexical_region_resolve/mod.rs35
-rw-r--r--src/librustc_infer/infer/mod.rs62
-rw-r--r--src/librustc_trait_selection/traits/mod.rs4
-rw-r--r--src/librustc_typeck/check/dropck.rs4
-rw-r--r--src/librustc_typeck/check/regionck.rs12
-rw-r--r--src/librustc_typeck/check/writeback.rs27
-rw-r--r--src/librustc_typeck/coherence/builtin.rs6
-rw-r--r--src/librustc_typeck/impl_wf_check/min_specialization.rs4
9 files changed, 103 insertions, 64 deletions
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs
index a544381f33d..ebbfcb28db2 100644
--- a/src/librustc_infer/infer/error_reporting/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/mod.rs
@@ -49,7 +49,7 @@ use super::lexical_region_resolve::RegionResolutionError;
 use super::region_constraints::GenericKind;
 use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
 
-use crate::infer::{self, SuppressRegionErrors};
+use crate::infer;
 use crate::traits::error_reporting::report_object_safety_error;
 use crate::traits::{
     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
@@ -372,17 +372,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         &self,
         region_scope_tree: &region::ScopeTree,
         errors: &Vec<RegionResolutionError<'tcx>>,
-        suppress: SuppressRegionErrors,
     ) {
-        debug!(
-            "report_region_errors(): {} errors to start, suppress = {:?}",
-            errors.len(),
-            suppress
-        );
-
-        if suppress.suppressed() {
-            return;
-        }
+        debug!("report_region_errors(): {} errors to start", errors.len());
 
         // try to pre-process the errors, which will group some of them
         // together into a `ProcessedErrors` group:
diff --git a/src/librustc_infer/infer/lexical_region_resolve/mod.rs b/src/librustc_infer/infer/lexical_region_resolve/mod.rs
index b7278ecd5e4..3af10e850d5 100644
--- a/src/librustc_infer/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc_infer/infer/lexical_region_resolve/mod.rs
@@ -7,6 +7,7 @@ use crate::infer::region_constraints::RegionConstraintData;
 use crate::infer::region_constraints::VarInfos;
 use crate::infer::region_constraints::VerifyBound;
 use crate::infer::RegionVariableOrigin;
+use crate::infer::RegionckMode;
 use crate::infer::SubregionOrigin;
 use rustc::middle::free_region::RegionRelations;
 use rustc::ty::fold::TypeFoldable;
@@ -33,12 +34,29 @@ pub fn resolve<'tcx>(
     region_rels: &RegionRelations<'_, 'tcx>,
     var_infos: VarInfos,
     data: RegionConstraintData<'tcx>,
+    mode: RegionckMode,
 ) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) {
     debug!("RegionConstraintData: resolve_regions()");
     let mut errors = vec![];
     let mut resolver = LexicalResolver { region_rels, var_infos, data };
-    let values = resolver.infer_variable_values(&mut errors);
-    (values, errors)
+    match mode {
+        RegionckMode::Solve => {
+            let values = resolver.infer_variable_values(&mut errors);
+            (values, errors)
+        }
+        RegionckMode::Erase { suppress_errors: false } => {
+            // Do real inference to get errors, then erase the results.
+            let mut values = resolver.infer_variable_values(&mut errors);
+            let re_erased = region_rels.tcx.lifetimes.re_erased;
+
+            values.values.iter_mut().for_each(|v| *v = VarValue::Value(re_erased));
+            (values, errors)
+        }
+        RegionckMode::Erase { suppress_errors: true } => {
+            // Skip region inference entirely.
+            (resolver.erased_data(region_rels.tcx), Vec::new())
+        }
+    }
 }
 
 /// Contains the result of lexical region resolution. Offers methods
@@ -163,6 +181,19 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         }
     }
 
+    /// An erased version of the lexical region resolutions. Used when we're
+    /// erasing regions and suppressing errors: in item bodies with
+    /// `-Zborrowck=mir`.
+    fn erased_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> {
+        LexicalRegionResolutions {
+            error_region: tcx.lifetimes.re_static,
+            values: IndexVec::from_elem_n(
+                VarValue::Value(tcx.lifetimes.re_erased),
+                self.num_vars(),
+            ),
+        }
+    }
+
     fn dump_constraints(&self, free_regions: &RegionRelations<'_, 'tcx>) {
         debug!("----() Start constraint listing (context={:?}) ()----", free_regions.context);
         for (idx, (constraint, _)) in self.data.constraints.iter().enumerate() {
diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs
index 9ae131c568d..c5f06d53b8f 100644
--- a/src/librustc_infer/infer/mod.rs
+++ b/src/librustc_infer/infer/mod.rs
@@ -79,31 +79,50 @@ pub type Bound<T> = Option<T>;
 pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
 pub type FixupResult<'tcx, T> = Result<T, FixupError<'tcx>>; // "fixup result"
 
-/// A flag that is used to suppress region errors. This is normally
-/// false, but sometimes -- when we are doing region checks that the
-/// NLL borrow checker will also do -- it might be set to true.
-#[derive(Copy, Clone, Default, Debug)]
-pub struct SuppressRegionErrors {
-    suppressed: bool,
+/// How we should handle region solving.
+///
+/// This is used so that the region values inferred by HIR region solving are
+/// not exposed, and so that we can avoid doing work in HIR typeck that MIR
+/// typeck will also do.
+#[derive(Copy, Clone, Debug)]
+pub enum RegionckMode {
+    /// The default mode: report region errors, don't erase regions.
+    Solve,
+    /// Erase the results of region after solving.
+    Erase {
+        /// A flag that is used to suppress region errors, when we are doing
+        /// region checks that the NLL borrow checker will also do -- it might
+        /// be set to true.
+        suppress_errors: bool,
+    },
+}
+
+impl Default for RegionckMode {
+    fn default() -> Self {
+        RegionckMode::Solve
+    }
 }
 
-impl SuppressRegionErrors {
+impl RegionckMode {
     pub fn suppressed(self) -> bool {
-        self.suppressed
+        match self {
+            Self::Solve => false,
+            Self::Erase { suppress_errors } => suppress_errors,
+        }
     }
 
     /// Indicates that the MIR borrowck will repeat these region
     /// checks, so we should ignore errors if NLL is (unconditionally)
     /// enabled.
-    pub fn when_nll_is_enabled(tcx: TyCtxt<'_>) -> Self {
+    pub fn for_item_body(tcx: TyCtxt<'_>) -> Self {
         // FIXME(Centril): Once we actually remove `::Migrate` also make
         // this always `true` and then proceed to eliminate the dead code.
         match tcx.borrowck_mode() {
             // If we're on Migrate mode, report AST region errors
-            BorrowckMode::Migrate => SuppressRegionErrors { suppressed: false },
+            BorrowckMode::Migrate => RegionckMode::Erase { suppress_errors: false },
 
             // If we're on MIR, don't report AST region errors as they should be reported by NLL
-            BorrowckMode::Mir => SuppressRegionErrors { suppressed: true },
+            BorrowckMode::Mir => RegionckMode::Erase { suppress_errors: true },
         }
     }
 }
@@ -1207,20 +1226,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         region_context: DefId,
         region_map: &region::ScopeTree,
         outlives_env: &OutlivesEnvironment<'tcx>,
-        suppress: SuppressRegionErrors,
+        mode: RegionckMode,
     ) {
         assert!(
             self.is_tainted_by_errors() || self.inner.borrow().region_obligations.is_empty(),
             "region_obligations not empty: {:#?}",
             self.inner.borrow().region_obligations
         );
-
-        let region_rels = &RegionRelations::new(
-            self.tcx,
-            region_context,
-            region_map,
-            outlives_env.free_region_map(),
-        );
         let (var_infos, data) = self
             .inner
             .borrow_mut()
@@ -1228,8 +1240,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             .take()
             .expect("regions already resolved")
             .into_infos_and_data();
+
+        let region_rels = &RegionRelations::new(
+            self.tcx,
+            region_context,
+            region_map,
+            outlives_env.free_region_map(),
+        );
+
         let (lexical_region_resolutions, errors) =
-            lexical_region_resolve::resolve(region_rels, var_infos, data);
+            lexical_region_resolve::resolve(region_rels, var_infos, data, mode);
 
         let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
         assert!(old_value.is_none());
@@ -1240,7 +1260,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             // this infcx was in use.  This is totally hokey but
             // otherwise we have a hard time separating legit region
             // errors from silly ones.
-            self.report_region_errors(region_map, &errors, suppress);
+            self.report_region_errors(region_map, &errors);
         }
     }
 
diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs
index 7b93982db97..43a90c4a6c1 100644
--- a/src/librustc_trait_selection/traits/mod.rs
+++ b/src/librustc_trait_selection/traits/mod.rs
@@ -21,7 +21,7 @@ mod util;
 pub mod wf;
 
 use crate::infer::outlives::env::OutlivesEnvironment;
-use crate::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt};
+use crate::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
 use crate::traits::error_reporting::InferCtxtExt as _;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc::middle::region;
@@ -244,7 +244,7 @@ fn do_normalize_predicates<'tcx>(
             region_context,
             &region_scope_tree,
             &outlives_env,
-            SuppressRegionErrors::default(),
+            RegionckMode::default(),
         );
 
         let predicates = match infcx.fully_resolve(&predicates) {
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index dca4f9e7cbe..e48ebbbb235 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -9,7 +9,7 @@ use rustc::ty::subst::{Subst, SubstsRef};
 use rustc::ty::{self, Predicate, Ty, TyCtxt};
 use rustc_errors::struct_span_err;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{InferOk, SuppressRegionErrors, TyCtxtInferExt};
+use rustc_infer::infer::{InferOk, RegionckMode, TyCtxtInferExt};
 use rustc_infer::traits::TraitEngineExt as _;
 use rustc_span::Span;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
@@ -139,7 +139,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
             drop_impl_did,
             &region_scope_tree,
             &outlives_env,
-            SuppressRegionErrors::default(),
+            RegionckMode::default(),
         );
         Ok(())
     })
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index ecc9a423b91..b6d6d3a7a87 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -85,7 +85,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::PatKind;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{self, RegionObligation, SuppressRegionErrors};
+use rustc_infer::infer::{self, RegionObligation, RegionckMode};
 use rustc_span::Span;
 use rustc_trait_selection::infer::OutlivesEnvironmentExt;
 use rustc_trait_selection::opaque_types::InferCtxtExt;
@@ -124,7 +124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             rcx.visit_body(body);
             rcx.visit_region_obligations(id);
         }
-        rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx));
+        rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx));
     }
 
     /// Region checking during the WF phase for items. `wf_tys` are the
@@ -142,7 +142,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span);
         rcx.outlives_environment.save_implied_bounds(item_id);
         rcx.visit_region_obligations(item_id);
-        rcx.resolve_regions_and_report_errors(SuppressRegionErrors::default());
+        rcx.resolve_regions_and_report_errors(RegionckMode::default());
     }
 
     /// Region check a function body. Not invoked on closures, but
@@ -165,7 +165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             rcx.visit_fn_body(fn_id, body, self.tcx.hir().span(fn_id));
         }
 
-        rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx));
+        rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx));
     }
 }
 
@@ -346,7 +346,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
         self.select_all_obligations_or_error();
     }
 
-    fn resolve_regions_and_report_errors(&self, suppress: SuppressRegionErrors) {
+    fn resolve_regions_and_report_errors(&self, mode: RegionckMode) {
         self.infcx.process_registered_region_obligations(
             self.outlives_environment.region_bound_pairs_map(),
             self.implicit_region_bound,
@@ -357,7 +357,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
             self.subject_def_id,
             &self.region_scope_tree,
             &self.outlives_environment,
-            suppress,
+            mode,
         );
     }
 
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 21536503ef7..8ed6cc3a943 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -124,7 +124,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
     fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
         debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty);
-        assert!(!ty.needs_infer() && !ty.has_placeholders());
+        assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions());
         self.tables.node_types_mut().insert(hir_id, ty);
     }
 
@@ -326,9 +326,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             let new_upvar_capture = match *upvar_capture {
                 ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue,
                 ty::UpvarCapture::ByRef(ref upvar_borrow) => {
-                    let r = upvar_borrow.region;
-                    let r = self.resolve(&r, &upvar_id.var_path.hir_id);
-                    ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind: upvar_borrow.kind, region: r })
+                    ty::UpvarCapture::ByRef(ty::UpvarBorrow {
+                        kind: upvar_borrow.kind,
+                        region: self.tcx().lifetimes.re_erased,
+                    })
                 }
             };
             debug!("Upvar capture for {:?} resolved to {:?}", upvar_id, new_upvar_capture);
@@ -421,8 +422,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     fn visit_opaque_types(&mut self, span: Span) {
         for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() {
             let hir_id = self.tcx().hir().as_local_hir_id(def_id).unwrap();
-            let instantiated_ty =
-                self.tcx().erase_regions(&self.resolve(&opaque_defn.concrete_ty, &hir_id));
+            let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &hir_id);
 
             debug_assert!(!instantiated_ty.has_escaping_bound_vars());
 
@@ -611,10 +611,8 @@ impl Locatable for hir::HirId {
     }
 }
 
-///////////////////////////////////////////////////////////////////////////
-// The Resolver. This is the type folding engine that detects
-// unresolved types and so forth.
-
+/// The Resolver. This is the type folding engine that detects
+/// unresolved types and so forth.
 struct Resolver<'cx, 'tcx> {
     tcx: TyCtxt<'tcx>,
     infcx: &'cx InferCtxt<'cx, 'tcx>,
@@ -647,7 +645,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match self.infcx.fully_resolve(&t) {
-            Ok(t) => t,
+            Ok(t) => self.infcx.tcx.erase_regions(&t),
             Err(_) => {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
                 self.report_error(t);
@@ -656,15 +654,14 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
         }
     }
 
-    // FIXME This should be carefully checked
-    // We could use `self.report_error` but it doesn't accept a ty::Region, right now.
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        self.infcx.fully_resolve(&r).unwrap_or(self.tcx.lifetimes.re_static)
+        debug_assert!(!r.is_late_bound(), "Should not be resolving bound region.");
+        self.tcx.lifetimes.re_erased
     }
 
     fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         match self.infcx.fully_resolve(&ct) {
-            Ok(ct) => ct,
+            Ok(ct) => self.infcx.tcx.erase_regions(&ct),
             Err(_) => {
                 debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
                 // FIXME: we'd like to use `self.report_error`, but it doesn't yet
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index 2ea7601ae65..e24d9bebf65 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -12,7 +12,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::ItemKind;
 use rustc_infer::infer;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{SuppressRegionErrors, TyCtxtInferExt};
+use rustc_infer::infer::{RegionckMode, TyCtxtInferExt};
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
 use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError};
 use rustc_trait_selection::traits::predicate_for_trait_def;
@@ -307,7 +307,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) {
                             impl_did,
                             &region_scope_tree,
                             &outlives_env,
-                            SuppressRegionErrors::default(),
+                            RegionckMode::default(),
                         );
                     }
                 }
@@ -568,7 +568,7 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
             impl_did,
             &region_scope_tree,
             &outlives_env,
-            SuppressRegionErrors::default(),
+            RegionckMode::default(),
         );
 
         CoerceUnsizedInfo { custom_kind: kind }
diff --git a/src/librustc_typeck/impl_wf_check/min_specialization.rs b/src/librustc_typeck/impl_wf_check/min_specialization.rs
index e96a8c454b8..cae88376118 100644
--- a/src/librustc_typeck/impl_wf_check/min_specialization.rs
+++ b/src/librustc_typeck/impl_wf_check/min_specialization.rs
@@ -75,7 +75,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt};
+use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
 use rustc_infer::traits::specialization_graph::Node;
 use rustc_span::Span;
 use rustc_trait_selection::traits::{self, translate_substs, wf};
@@ -162,7 +162,7 @@ fn get_impl_substs<'tcx>(
         impl1_def_id,
         &ScopeTree::default(),
         &outlives_env,
-        SuppressRegionErrors::default(),
+        RegionckMode::default(),
     );
     let impl2_substs = match infcx.fully_resolve(&impl2_substs) {
         Ok(s) => s,