Skip to content

Commit 54f7202

Browse files
committed
Erase regions in writeback
Also skip duplicated region solving entirely with `-Zborrowck=mir`.
1 parent b5a44ff commit 54f7202

File tree

8 files changed

+101
-63
lines changed

8 files changed

+101
-63
lines changed

src/librustc_infer/infer/error_reporting/mod.rs

+2-12
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ use super::lexical_region_resolve::RegionResolutionError;
4949
use super::region_constraints::GenericKind;
5050
use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
5151

52-
use crate::infer::opaque_types;
53-
use crate::infer::{self, SuppressRegionErrors};
52+
use crate::infer::{self, opaque_types};
5453
use crate::traits::error_reporting::report_object_safety_error;
5554
use crate::traits::{
5655
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
@@ -293,17 +292,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
293292
&self,
294293
region_scope_tree: &region::ScopeTree,
295294
errors: &Vec<RegionResolutionError<'tcx>>,
296-
suppress: SuppressRegionErrors,
297295
) {
298-
debug!(
299-
"report_region_errors(): {} errors to start, suppress = {:?}",
300-
errors.len(),
301-
suppress
302-
);
303-
304-
if suppress.suppressed() {
305-
return;
306-
}
296+
debug!("report_region_errors(): {} errors to start", errors.len());
307297

308298
// try to pre-process the errors, which will group some of them
309299
// together into a `ProcessedErrors` group:

src/librustc_infer/infer/lexical_region_resolve/mod.rs

+33-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::infer::region_constraints::RegionConstraintData;
77
use crate::infer::region_constraints::VarInfos;
88
use crate::infer::region_constraints::VerifyBound;
99
use crate::infer::RegionVariableOrigin;
10+
use crate::infer::RegionckMode;
1011
use crate::infer::SubregionOrigin;
1112
use rustc::middle::free_region::RegionRelations;
1213
use rustc::ty::fold::TypeFoldable;
@@ -33,12 +34,29 @@ pub fn resolve<'tcx>(
3334
region_rels: &RegionRelations<'_, 'tcx>,
3435
var_infos: VarInfos,
3536
data: RegionConstraintData<'tcx>,
37+
mode: RegionckMode,
3638
) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) {
3739
debug!("RegionConstraintData: resolve_regions()");
3840
let mut errors = vec![];
3941
let mut resolver = LexicalResolver { region_rels, var_infos, data };
40-
let values = resolver.infer_variable_values(&mut errors);
41-
(values, errors)
42+
match mode {
43+
RegionckMode::Solve => {
44+
let values = resolver.infer_variable_values(&mut errors);
45+
(values, errors)
46+
}
47+
RegionckMode::Erase { suppress_errors: false } => {
48+
// Do real inference to get errors, then erase the results.
49+
let mut values = resolver.infer_variable_values(&mut errors);
50+
let re_erased = region_rels.tcx.lifetimes.re_erased;
51+
52+
values.values.iter_mut().for_each(|v| *v = VarValue::Value(re_erased));
53+
(values, errors)
54+
}
55+
RegionckMode::Erase { suppress_errors: true } => {
56+
// Skip region inference entirely.
57+
(resolver.erased_data(region_rels.tcx), Vec::new())
58+
}
59+
}
4260
}
4361

4462
/// Contains the result of lexical region resolution. Offers methods
@@ -163,6 +181,19 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
163181
}
164182
}
165183

184+
/// An erased version of the lexical region resolutions. Used when we're
185+
/// erasing regions and suppressing errors: in item bodies with
186+
/// `-Zborrowck=mir`.
187+
fn erased_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> {
188+
LexicalRegionResolutions {
189+
error_region: tcx.lifetimes.re_static,
190+
values: IndexVec::from_elem_n(
191+
VarValue::Value(tcx.lifetimes.re_erased),
192+
self.num_vars(),
193+
),
194+
}
195+
}
196+
166197
fn dump_constraints(&self, free_regions: &RegionRelations<'_, 'tcx>) {
167198
debug!("----() Start constraint listing (context={:?}) ()----", free_regions.context);
168199
for (idx, (constraint, _)) in self.data.constraints.iter().enumerate() {

src/librustc_infer/infer/mod.rs

+41-21
Original file line numberDiff line numberDiff line change
@@ -80,31 +80,50 @@ pub type Bound<T> = Option<T>;
8080
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
8181
pub type FixupResult<'tcx, T> = Result<T, FixupError<'tcx>>; // "fixup result"
8282

83-
/// A flag that is used to suppress region errors. This is normally
84-
/// false, but sometimes -- when we are doing region checks that the
85-
/// NLL borrow checker will also do -- it might be set to true.
86-
#[derive(Copy, Clone, Default, Debug)]
87-
pub struct SuppressRegionErrors {
88-
suppressed: bool,
83+
/// How we should handle region solving.
84+
///
85+
/// This is used so that the region values inferred by HIR region solving are
86+
/// not exposed, and so that we can avoid doing work in HIR typeck that MIR
87+
/// typeck will also do.
88+
#[derive(Copy, Clone, Debug)]
89+
pub enum RegionckMode {
90+
/// The default mode: report region errors, don't erase regions.
91+
Solve,
92+
/// Erase the results of region after solving.
93+
Erase {
94+
/// A flag that is used to suppress region errors, when we are doing
95+
/// region checks that the NLL borrow checker will also do -- it might
96+
/// be set to true.
97+
suppress_errors: bool,
98+
},
99+
}
100+
101+
impl Default for RegionckMode {
102+
fn default() -> Self {
103+
RegionckMode::Solve
104+
}
89105
}
90106

91-
impl SuppressRegionErrors {
107+
impl RegionckMode {
92108
pub fn suppressed(self) -> bool {
93-
self.suppressed
109+
match self {
110+
Self::Solve => false,
111+
Self::Erase { suppress_errors } => suppress_errors,
112+
}
94113
}
95114

96115
/// Indicates that the MIR borrowck will repeat these region
97116
/// checks, so we should ignore errors if NLL is (unconditionally)
98117
/// enabled.
99-
pub fn when_nll_is_enabled(tcx: TyCtxt<'_>) -> Self {
118+
pub fn for_item_body(tcx: TyCtxt<'_>) -> Self {
100119
// FIXME(Centril): Once we actually remove `::Migrate` also make
101120
// this always `true` and then proceed to eliminate the dead code.
102121
match tcx.borrowck_mode() {
103122
// If we're on Migrate mode, report AST region errors
104-
BorrowckMode::Migrate => SuppressRegionErrors { suppressed: false },
123+
BorrowckMode::Migrate => RegionckMode::Erase { suppress_errors: false },
105124

106125
// If we're on MIR, don't report AST region errors as they should be reported by NLL
107-
BorrowckMode::Mir => SuppressRegionErrors { suppressed: true },
126+
BorrowckMode::Mir => RegionckMode::Erase { suppress_errors: true },
108127
}
109128
}
110129
}
@@ -1208,29 +1227,30 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
12081227
region_context: DefId,
12091228
region_map: &region::ScopeTree,
12101229
outlives_env: &OutlivesEnvironment<'tcx>,
1211-
suppress: SuppressRegionErrors,
1230+
mode: RegionckMode,
12121231
) {
12131232
assert!(
12141233
self.is_tainted_by_errors() || self.inner.borrow().region_obligations.is_empty(),
12151234
"region_obligations not empty: {:#?}",
12161235
self.inner.borrow().region_obligations
12171236
);
1218-
1219-
let region_rels = &RegionRelations::new(
1220-
self.tcx,
1221-
region_context,
1222-
region_map,
1223-
outlives_env.free_region_map(),
1224-
);
12251237
let (var_infos, data) = self
12261238
.inner
12271239
.borrow_mut()
12281240
.region_constraints
12291241
.take()
12301242
.expect("regions already resolved")
12311243
.into_infos_and_data();
1244+
1245+
let region_rels = &RegionRelations::new(
1246+
self.tcx,
1247+
region_context,
1248+
region_map,
1249+
outlives_env.free_region_map(),
1250+
);
1251+
12321252
let (lexical_region_resolutions, errors) =
1233-
lexical_region_resolve::resolve(region_rels, var_infos, data);
1253+
lexical_region_resolve::resolve(region_rels, var_infos, data, mode);
12341254

12351255
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
12361256
assert!(old_value.is_none());
@@ -1241,7 +1261,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
12411261
// this infcx was in use. This is totally hokey but
12421262
// otherwise we have a hard time separating legit region
12431263
// errors from silly ones.
1244-
self.report_region_errors(region_map, &errors, suppress);
1264+
self.report_region_errors(region_map, &errors);
12451265
}
12461266
}
12471267

src/librustc_infer/traits/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ mod util;
2222
pub mod wf;
2323

2424
use crate::infer::outlives::env::OutlivesEnvironment;
25-
use crate::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt};
25+
use crate::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
2626
use rustc::middle::region;
2727
use rustc::ty::error::{ExpectedFound, TypeError};
2828
use rustc::ty::fold::TypeFoldable;
@@ -301,7 +301,7 @@ fn do_normalize_predicates<'tcx>(
301301
region_context,
302302
&region_scope_tree,
303303
&outlives_env,
304-
SuppressRegionErrors::default(),
304+
RegionckMode::default(),
305305
);
306306

307307
let predicates = match infcx.fully_resolve(&predicates) {

src/librustc_typeck/check/dropck.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc::ty::subst::{Subst, SubstsRef};
99
use rustc::ty::{self, Predicate, Ty, TyCtxt};
1010
use rustc_errors::struct_span_err;
1111
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
12-
use rustc_infer::infer::{InferOk, SuppressRegionErrors, TyCtxtInferExt};
12+
use rustc_infer::infer::{InferOk, RegionckMode, TyCtxtInferExt};
1313
use rustc_infer::traits::{ObligationCause, TraitEngine, TraitEngineExt};
1414
use rustc_span::Span;
1515

@@ -136,7 +136,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
136136
drop_impl_did,
137137
&region_scope_tree,
138138
&outlives_env,
139-
SuppressRegionErrors::default(),
139+
RegionckMode::default(),
140140
);
141141
Ok(())
142142
})

src/librustc_typeck/check/regionck.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ use rustc_hir::def_id::DefId;
8585
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
8686
use rustc_hir::PatKind;
8787
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
88-
use rustc_infer::infer::{self, RegionObligation, SuppressRegionErrors};
88+
use rustc_infer::infer::{self, RegionObligation, RegionckMode};
8989
use rustc_span::Span;
9090
use std::mem;
9191
use std::ops::Deref;
@@ -122,7 +122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
122122
rcx.visit_body(body);
123123
rcx.visit_region_obligations(id);
124124
}
125-
rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx));
125+
rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx));
126126
}
127127

128128
/// Region checking during the WF phase for items. `wf_tys` are the
@@ -140,7 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
140140
rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span);
141141
rcx.outlives_environment.save_implied_bounds(item_id);
142142
rcx.visit_region_obligations(item_id);
143-
rcx.resolve_regions_and_report_errors(SuppressRegionErrors::default());
143+
rcx.resolve_regions_and_report_errors(RegionckMode::default());
144144
}
145145

146146
/// Region check a function body. Not invoked on closures, but
@@ -163,7 +163,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
163163
rcx.visit_fn_body(fn_id, body, self.tcx.hir().span(fn_id));
164164
}
165165

166-
rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx));
166+
rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx));
167167
}
168168
}
169169

@@ -344,7 +344,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
344344
self.select_all_obligations_or_error();
345345
}
346346

347-
fn resolve_regions_and_report_errors(&self, suppress: SuppressRegionErrors) {
347+
fn resolve_regions_and_report_errors(&self, mode: RegionckMode) {
348348
self.infcx.process_registered_region_obligations(
349349
self.outlives_environment.region_bound_pairs_map(),
350350
self.implicit_region_bound,
@@ -355,7 +355,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
355355
self.subject_def_id,
356356
&self.region_scope_tree,
357357
&self.outlives_environment,
358-
suppress,
358+
mode,
359359
);
360360
}
361361

src/librustc_typeck/check/writeback.rs

+12-15
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
123123

124124
fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
125125
debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty);
126-
assert!(!ty.needs_infer() && !ty.has_placeholders());
126+
assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions());
127127
self.tables.node_types_mut().insert(hir_id, ty);
128128
}
129129

@@ -325,9 +325,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
325325
let new_upvar_capture = match *upvar_capture {
326326
ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue,
327327
ty::UpvarCapture::ByRef(ref upvar_borrow) => {
328-
let r = upvar_borrow.region;
329-
let r = self.resolve(&r, &upvar_id.var_path.hir_id);
330-
ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind: upvar_borrow.kind, region: r })
328+
ty::UpvarCapture::ByRef(ty::UpvarBorrow {
329+
kind: upvar_borrow.kind,
330+
region: self.tcx().lifetimes.re_erased,
331+
})
331332
}
332333
};
333334
debug!("Upvar capture for {:?} resolved to {:?}", upvar_id, new_upvar_capture);
@@ -420,8 +421,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
420421
fn visit_opaque_types(&mut self, span: Span) {
421422
for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() {
422423
let hir_id = self.tcx().hir().as_local_hir_id(def_id).unwrap();
423-
let instantiated_ty =
424-
self.tcx().erase_regions(&self.resolve(&opaque_defn.concrete_ty, &hir_id));
424+
let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &hir_id);
425425

426426
debug_assert!(!instantiated_ty.has_escaping_bound_vars());
427427

@@ -610,10 +610,8 @@ impl Locatable for hir::HirId {
610610
}
611611
}
612612

613-
///////////////////////////////////////////////////////////////////////////
614-
// The Resolver. This is the type folding engine that detects
615-
// unresolved types and so forth.
616-
613+
/// The Resolver. This is the type folding engine that detects
614+
/// unresolved types and so forth.
617615
struct Resolver<'cx, 'tcx> {
618616
tcx: TyCtxt<'tcx>,
619617
infcx: &'cx InferCtxt<'cx, 'tcx>,
@@ -646,7 +644,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
646644

647645
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
648646
match self.infcx.fully_resolve(&t) {
649-
Ok(t) => t,
647+
Ok(t) => self.infcx.tcx.erase_regions(&t),
650648
Err(_) => {
651649
debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
652650
self.report_error(t);
@@ -655,15 +653,14 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
655653
}
656654
}
657655

658-
// FIXME This should be carefully checked
659-
// We could use `self.report_error` but it doesn't accept a ty::Region, right now.
660656
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
661-
self.infcx.fully_resolve(&r).unwrap_or(self.tcx.lifetimes.re_static)
657+
debug_assert!(!r.is_late_bound(), "Should not be resolving bound region.");
658+
self.tcx.lifetimes.re_erased
662659
}
663660

664661
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
665662
match self.infcx.fully_resolve(&ct) {
666-
Ok(ct) => ct,
663+
Ok(ct) => self.infcx.tcx.erase_regions(&ct),
667664
Err(_) => {
668665
debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
669666
// FIXME: we'd like to use `self.report_error`, but it doesn't yet

src/librustc_typeck/coherence/builtin.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_hir::def_id::DefId;
1212
use rustc_hir::ItemKind;
1313
use rustc_infer::infer;
1414
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
15-
use rustc_infer::infer::{SuppressRegionErrors, TyCtxtInferExt};
15+
use rustc_infer::infer::{RegionckMode, TyCtxtInferExt};
1616
use rustc_infer::traits::misc::{can_type_implement_copy, CopyImplementationError};
1717
use rustc_infer::traits::predicate_for_trait_def;
1818
use rustc_infer::traits::{self, ObligationCause, TraitEngine};
@@ -306,7 +306,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) {
306306
impl_did,
307307
&region_scope_tree,
308308
&outlives_env,
309-
SuppressRegionErrors::default(),
309+
RegionckMode::default(),
310310
);
311311
}
312312
}
@@ -567,7 +567,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
567567
impl_did,
568568
&region_scope_tree,
569569
&outlives_env,
570-
SuppressRegionErrors::default(),
570+
RegionckMode::default(),
571571
);
572572

573573
CoerceUnsizedInfo { custom_kind: kind }

0 commit comments

Comments
 (0)