Skip to content

Commit ecf19c3

Browse files
authored
Rollup merge of rust-lang#69189 - matthewjasper:erase-the-world, r=nikomatsakis
Erase regions in writeback Regions in `TypeckTables` (except canonicalized user annotations) are now erased. Further, we no longer do lexical region solving on item bodies with `-Zborrowck=mir`. cc rust-lang#68261 r? @nikomatsakis
2 parents 0789d63 + 1ee5829 commit ecf19c3

34 files changed

+264
-237
lines changed

src/librustc/ty/context.rs

-9
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use crate::mir::{
2323
};
2424
use crate::traits;
2525
use crate::traits::{Clause, Clauses, Goal, GoalKind, Goals};
26-
use crate::ty::free_region_map::FreeRegionMap;
2726
use crate::ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx};
2827
use crate::ty::query;
2928
use crate::ty::steal::Steal;
@@ -416,11 +415,6 @@ pub struct TypeckTables<'tcx> {
416415
/// this field will be set to `true`.
417416
pub tainted_by_errors: bool,
418417

419-
/// Stores the free-region relationships that were deduced from
420-
/// its where-clauses and parameter types. These are then
421-
/// read-again by borrowck.
422-
pub free_region_map: FreeRegionMap<'tcx>,
423-
424418
/// All the opaque types that are restricted to concrete types
425419
/// by this function.
426420
pub concrete_opaque_types: FxHashMap<DefId, ResolvedOpaqueTy<'tcx>>,
@@ -456,7 +450,6 @@ impl<'tcx> TypeckTables<'tcx> {
456450
coercion_casts: Default::default(),
457451
used_trait_imports: Lrc::new(Default::default()),
458452
tainted_by_errors: false,
459-
free_region_map: Default::default(),
460453
concrete_opaque_types: Default::default(),
461454
upvar_list: Default::default(),
462455
generator_interior_types: Default::default(),
@@ -719,7 +712,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
719712

720713
ref used_trait_imports,
721714
tainted_by_errors,
722-
ref free_region_map,
723715
ref concrete_opaque_types,
724716
ref upvar_list,
725717
ref generator_interior_types,
@@ -757,7 +749,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
757749
coercion_casts.hash_stable(hcx, hasher);
758750
used_trait_imports.hash_stable(hcx, hasher);
759751
tainted_by_errors.hash_stable(hcx, hasher);
760-
free_region_map.hash_stable(hcx, hasher);
761752
concrete_opaque_types.hash_stable(hcx, hasher);
762753
upvar_list.hash_stable(hcx, hasher);
763754
generator_interior_types.hash_stable(hcx, hasher);

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/error_reporting/nice_region_error/different_lifetimes.rs

+11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
44
use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo;
55
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
6+
use crate::infer::lexical_region_resolve::RegionResolutionError;
7+
use crate::infer::SubregionOrigin;
68
use rustc::util::common::ErrorReported;
79

810
use rustc_errors::struct_span_err;
@@ -47,6 +49,15 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
4749
pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
4850
let (span, sub, sup) = self.regions()?;
4951

52+
if let Some(RegionResolutionError::ConcreteFailure(
53+
SubregionOrigin::ReferenceOutlivesReferent(..),
54+
..,
55+
)) = self.error
56+
{
57+
// This error doesn't make much sense in this case.
58+
return None;
59+
}
60+
5061
// Determine whether the sub and sup consist of both anonymous (elided) regions.
5162
let anon_reg_sup = self.tcx().is_suitable_region(sup)?;
5263

src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs

+4-15
Original file line numberDiff line numberDiff line change
@@ -17,39 +17,28 @@ mod util;
1717

1818
impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
1919
pub fn try_report_nice_region_error(&self, error: &RegionResolutionError<'tcx>) -> bool {
20-
if let Some(tables) = self.in_progress_tables {
21-
let tables = tables.borrow();
22-
NiceRegionError::new(self, error.clone(), Some(&tables)).try_report().is_some()
23-
} else {
24-
NiceRegionError::new(self, error.clone(), None).try_report().is_some()
25-
}
20+
NiceRegionError::new(self, error.clone()).try_report().is_some()
2621
}
2722
}
2823

2924
pub struct NiceRegionError<'cx, 'tcx> {
3025
infcx: &'cx InferCtxt<'cx, 'tcx>,
3126
error: Option<RegionResolutionError<'tcx>>,
3227
regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>,
33-
tables: Option<&'cx ty::TypeckTables<'tcx>>,
3428
}
3529

3630
impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
37-
pub fn new(
38-
infcx: &'cx InferCtxt<'cx, 'tcx>,
39-
error: RegionResolutionError<'tcx>,
40-
tables: Option<&'cx ty::TypeckTables<'tcx>>,
41-
) -> Self {
42-
Self { infcx, error: Some(error), regions: None, tables }
31+
pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>, error: RegionResolutionError<'tcx>) -> Self {
32+
Self { infcx, error: Some(error), regions: None }
4333
}
4434

4535
pub fn new_from_span(
4636
infcx: &'cx InferCtxt<'cx, 'tcx>,
4737
span: Span,
4838
sub: ty::Region<'tcx>,
4939
sup: ty::Region<'tcx>,
50-
tables: Option<&'cx ty::TypeckTables<'tcx>>,
5140
) -> Self {
52-
Self { infcx, error: None, regions: Some((span, sub, sup)), tables }
41+
Self { infcx, error: None, regions: Some((span, sub, sup)) }
5342
}
5443

5544
fn tcx(&self) -> TyCtxt<'tcx> {

src/librustc_infer/infer/error_reporting/nice_region_error/util.rs

+35-43
Original file line numberDiff line numberDiff line change
@@ -51,52 +51,44 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
5151
};
5252

5353
let hir = &self.tcx().hir();
54-
if let Some(hir_id) = hir.as_local_hir_id(id) {
55-
if let Some(body_id) = hir.maybe_body_owned_by(hir_id) {
56-
let body = hir.body(body_id);
57-
let owner_id = hir.body_owner(body_id);
58-
let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap();
59-
if let Some(tables) = self.tables {
60-
body.params
61-
.iter()
62-
.enumerate()
63-
.filter_map(|(index, param)| {
64-
// May return None; sometimes the tables are not yet populated.
65-
let ty_hir_id = fn_decl.inputs[index].hir_id;
66-
let param_ty_span = hir.span(ty_hir_id);
67-
let ty = tables.node_type_opt(param.hir_id)?;
68-
let mut found_anon_region = false;
69-
let new_param_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| {
70-
if *r == *anon_region {
71-
found_anon_region = true;
72-
replace_region
73-
} else {
74-
r
75-
}
76-
});
77-
if found_anon_region {
78-
let is_first = index == 0;
79-
Some(AnonymousParamInfo {
80-
param,
81-
param_ty: new_param_ty,
82-
param_ty_span,
83-
bound_region,
84-
is_first,
85-
})
86-
} else {
87-
None
88-
}
89-
})
90-
.next()
54+
let hir_id = hir.as_local_hir_id(id)?;
55+
let body_id = hir.maybe_body_owned_by(hir_id)?;
56+
let body = hir.body(body_id);
57+
let owner_id = hir.body_owner(body_id);
58+
let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap();
59+
let poly_fn_sig = self.tcx().fn_sig(id);
60+
let fn_sig = self.tcx().liberate_late_bound_regions(id, &poly_fn_sig);
61+
body.params
62+
.iter()
63+
.enumerate()
64+
.filter_map(|(index, param)| {
65+
// May return None; sometimes the tables are not yet populated.
66+
let ty = fn_sig.inputs()[index];
67+
let mut found_anon_region = false;
68+
let new_param_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| {
69+
if *r == *anon_region {
70+
found_anon_region = true;
71+
replace_region
72+
} else {
73+
r
74+
}
75+
});
76+
if found_anon_region {
77+
let ty_hir_id = fn_decl.inputs[index].hir_id;
78+
let param_ty_span = hir.span(ty_hir_id);
79+
let is_first = index == 0;
80+
Some(AnonymousParamInfo {
81+
param,
82+
param_ty: new_param_ty,
83+
param_ty_span,
84+
bound_region,
85+
is_first,
86+
})
9187
} else {
9288
None
9389
}
94-
} else {
95-
None
96-
}
97-
} else {
98-
None
99-
}
90+
})
91+
.next()
10092
}
10193

10294
// Here, we check for the case where the anonymous region

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

0 commit comments

Comments
 (0)