Skip to content

Commit 0a7f16e

Browse files
committed
Erase regions in writeback
Also skip duplicated region solving entirely with `-Zborrowck=mir`.
1 parent cefd030 commit 0a7f16e

File tree

9 files changed

+103
-64
lines changed

9 files changed

+103
-64
lines changed

src/librustc_infer/infer/error_reporting/mod.rs

+2-11
Original file line numberDiff line numberDiff line change
@@ -49,7 +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::{self, SuppressRegionErrors};
52+
use crate::infer;
5353
use crate::traits::error_reporting::report_object_safety_error;
5454
use crate::traits::{
5555
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
@@ -372,17 +372,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
372372
&self,
373373
region_scope_tree: &region::ScopeTree,
374374
errors: &Vec<RegionResolutionError<'tcx>>,
375-
suppress: SuppressRegionErrors,
376375
) {
377-
debug!(
378-
"report_region_errors(): {} errors to start, suppress = {:?}",
379-
errors.len(),
380-
suppress
381-
);
382-
383-
if suppress.suppressed() {
384-
return;
385-
}
376+
debug!("report_region_errors(): {} errors to start", errors.len());
386377

387378
// try to pre-process the errors, which will group some of them
388379
// 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
@@ -79,31 +79,50 @@ pub type Bound<T> = Option<T>;
7979
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
8080
pub type FixupResult<'tcx, T> = Result<T, FixupError<'tcx>>; // "fixup result"
8181

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

90-
impl SuppressRegionErrors {
106+
impl RegionckMode {
91107
pub fn suppressed(self) -> bool {
92-
self.suppressed
108+
match self {
109+
Self::Solve => false,
110+
Self::Erase { suppress_errors } => suppress_errors,
111+
}
93112
}
94113

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

105124
// If we're on MIR, don't report AST region errors as they should be reported by NLL
106-
BorrowckMode::Mir => SuppressRegionErrors { suppressed: true },
125+
BorrowckMode::Mir => RegionckMode::Erase { suppress_errors: true },
107126
}
108127
}
109128
}
@@ -1207,29 +1226,30 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
12071226
region_context: DefId,
12081227
region_map: &region::ScopeTree,
12091228
outlives_env: &OutlivesEnvironment<'tcx>,
1210-
suppress: SuppressRegionErrors,
1229+
mode: RegionckMode,
12111230
) {
12121231
assert!(
12131232
self.is_tainted_by_errors() || self.inner.borrow().region_obligations.is_empty(),
12141233
"region_obligations not empty: {:#?}",
12151234
self.inner.borrow().region_obligations
12161235
);
1217-
1218-
let region_rels = &RegionRelations::new(
1219-
self.tcx,
1220-
region_context,
1221-
region_map,
1222-
outlives_env.free_region_map(),
1223-
);
12241236
let (var_infos, data) = self
12251237
.inner
12261238
.borrow_mut()
12271239
.region_constraints
12281240
.take()
12291241
.expect("regions already resolved")
12301242
.into_infos_and_data();
1243+
1244+
let region_rels = &RegionRelations::new(
1245+
self.tcx,
1246+
region_context,
1247+
region_map,
1248+
outlives_env.free_region_map(),
1249+
);
1250+
12311251
let (lexical_region_resolutions, errors) =
1232-
lexical_region_resolve::resolve(region_rels, var_infos, data);
1252+
lexical_region_resolve::resolve(region_rels, var_infos, data, mode);
12331253

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

src/librustc_trait_selection/traits/mod.rs

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

2323
use crate::infer::outlives::env::OutlivesEnvironment;
24-
use crate::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt};
24+
use crate::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
2525
use crate::traits::error_reporting::InferCtxtExt as _;
2626
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
2727
use rustc::middle::region;
@@ -244,7 +244,7 @@ fn do_normalize_predicates<'tcx>(
244244
region_context,
245245
&region_scope_tree,
246246
&outlives_env,
247-
SuppressRegionErrors::default(),
247+
RegionckMode::default(),
248248
);
249249

250250
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::TraitEngineExt as _;
1414
use rustc_span::Span;
1515
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
@@ -139,7 +139,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
139139
drop_impl_did,
140140
&region_scope_tree,
141141
&outlives_env,
142-
SuppressRegionErrors::default(),
142+
RegionckMode::default(),
143143
);
144144
Ok(())
145145
})

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 rustc_trait_selection::infer::OutlivesEnvironmentExt;
9191
use rustc_trait_selection::opaque_types::InferCtxtExt;
@@ -124,7 +124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
124124
rcx.visit_body(body);
125125
rcx.visit_region_obligations(id);
126126
}
127-
rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx));
127+
rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx));
128128
}
129129

130130
/// Region checking during the WF phase for items. `wf_tys` are the
@@ -142,7 +142,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
142142
rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span);
143143
rcx.outlives_environment.save_implied_bounds(item_id);
144144
rcx.visit_region_obligations(item_id);
145-
rcx.resolve_regions_and_report_errors(SuppressRegionErrors::default());
145+
rcx.resolve_regions_and_report_errors(RegionckMode::default());
146146
}
147147

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

168-
rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx));
168+
rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx));
169169
}
170170
}
171171

@@ -346,7 +346,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
346346
self.select_all_obligations_or_error();
347347
}
348348

349-
fn resolve_regions_and_report_errors(&self, suppress: SuppressRegionErrors) {
349+
fn resolve_regions_and_report_errors(&self, mode: RegionckMode) {
350350
self.infcx.process_registered_region_obligations(
351351
self.outlives_environment.region_bound_pairs_map(),
352352
self.implicit_region_bound,
@@ -357,7 +357,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
357357
self.subject_def_id,
358358
&self.region_scope_tree,
359359
&self.outlives_environment,
360-
suppress,
360+
mode,
361361
);
362362
}
363363

src/librustc_typeck/check/writeback.rs

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

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

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

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

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

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

648646
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
649647
match self.infcx.fully_resolve(&t) {
650-
Ok(t) => t,
648+
Ok(t) => self.infcx.tcx.erase_regions(&t),
651649
Err(_) => {
652650
debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
653651
self.report_error(t);
@@ -656,15 +654,14 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
656654
}
657655
}
658656

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

665662
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
666663
match self.infcx.fully_resolve(&ct) {
667-
Ok(ct) => ct,
664+
Ok(ct) => self.infcx.tcx.erase_regions(&ct),
668665
Err(_) => {
669666
debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
670667
// 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_trait_selection::traits::error_reporting::InferCtxtExt;
1717
use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError};
1818
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) {
307307
impl_did,
308308
&region_scope_tree,
309309
&outlives_env,
310-
SuppressRegionErrors::default(),
310+
RegionckMode::default(),
311311
);
312312
}
313313
}
@@ -568,7 +568,7 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
568568
impl_did,
569569
&region_scope_tree,
570570
&outlives_env,
571-
SuppressRegionErrors::default(),
571+
RegionckMode::default(),
572572
);
573573

574574
CoerceUnsizedInfo { custom_kind: kind }

0 commit comments

Comments
 (0)