Skip to content

Commit fc81e36

Browse files
committed
Auto merge of #53327 - wesleywiser:wip_optimize_nll, r=nikomatsakis
[nll] teach SCC about `'static` r? @nikomatsakis I think this is right? I am seeing better performance on the `html5ever` benchmark but I'd like a perf run to quantify the exact speedup. There's a few ui tests failing due to changes in the error messages. The main issue seems to be that returns aren't being detected correctly? `mir_check_cast_unsize.rs` before: ``` error: unsatisfied lifetime constraints --> mir_check_cast_unsize.rs:17:46 | 17 | fn bar<'a>(x: &'a u32) -> &'static dyn Debug { | ________--____________________________________^ | | | | | lifetime `'a` defined here 18 | | //~^ ERROR unsatisfied lifetime constraints 19 | | x 20 | | //~^ WARNING not reporting region error due to nll 21 | | } | |_^ return requires that `'a` must outlive `'static` ``` `mir_check_cast_unsize.rs` after: ``` error: unsatisfied lifetime constraints --> mir_check_cast_unsize.rs:19:5 | 17 | fn bar<'a>(x: &'a u32) -> &'static dyn Debug { | -- lifetime `'a` defined here 18 | //~^ ERROR unsatisfied lifetime constraints 19 | x | ^ cast requires that `'a` must outlive `'static` ```
2 parents 24ef47b + b1211e8 commit fc81e36

File tree

39 files changed

+376
-190
lines changed

39 files changed

+376
-190
lines changed

src/librustc/middle/resolve_lifetime.rs

+7
Original file line numberDiff line numberDiff line change
@@ -2567,6 +2567,13 @@ fn insert_late_bound_lifetimes(
25672567
// - do not appear in the where-clauses
25682568
// - are not implicitly captured by `impl Trait`
25692569
for param in &generics.params {
2570+
match param.kind {
2571+
hir::GenericParamKind::Lifetime { .. } => { /* fall through */ }
2572+
2573+
// Types are not late-bound.
2574+
hir::GenericParamKind::Type { .. } => continue,
2575+
}
2576+
25702577
let lt_name = hir::LifetimeName::Param(param.name.modern());
25712578
// appears in the where clauses? early-bound.
25722579
if appears_in_where_clause.regions.contains(&lt_name) {

src/librustc_mir/borrow_check/nll/constraints/graph.rs

+70-14
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use borrow_check::nll::type_check::Locations;
1112
use borrow_check::nll::constraints::{ConstraintIndex, ConstraintSet, OutlivesConstraint};
1213
use rustc::ty::RegionVid;
1314
use rustc_data_structures::graph;
@@ -31,6 +32,7 @@ crate type ReverseConstraintGraph = ConstraintGraph<Reverse>;
3132
crate trait ConstraintGraphDirecton: Copy + 'static {
3233
fn start_region(c: &OutlivesConstraint) -> RegionVid;
3334
fn end_region(c: &OutlivesConstraint) -> RegionVid;
35+
fn is_normal() -> bool;
3436
}
3537

3638
/// In normal mode, a `R1: R2` constraint results in an edge `R1 ->
@@ -48,6 +50,10 @@ impl ConstraintGraphDirecton for Normal {
4850
fn end_region(c: &OutlivesConstraint) -> RegionVid {
4951
c.sub
5052
}
53+
54+
fn is_normal() -> bool {
55+
true
56+
}
5157
}
5258

5359
/// In reverse mode, a `R1: R2` constraint results in an edge `R2 ->
@@ -65,6 +71,10 @@ impl ConstraintGraphDirecton for Reverse {
6571
fn end_region(c: &OutlivesConstraint) -> RegionVid {
6672
c.sup
6773
}
74+
75+
fn is_normal() -> bool {
76+
false
77+
}
6878
}
6979

7080
impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
@@ -98,32 +108,74 @@ impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
98108
/// Given the constraint set from which this graph was built
99109
/// creates a region graph so that you can iterate over *regions*
100110
/// and not constraints.
101-
crate fn region_graph<'rg>(&'rg self, set: &'rg ConstraintSet) -> RegionGraph<'rg, D> {
102-
RegionGraph::new(set, self)
111+
crate fn region_graph<'rg>(
112+
&'rg self,
113+
set: &'rg ConstraintSet,
114+
static_region: RegionVid,
115+
) -> RegionGraph<'rg, D> {
116+
RegionGraph::new(set, self, static_region)
103117
}
104118

105119
/// Given a region `R`, iterate over all constraints `R: R1`.
106-
crate fn outgoing_edges(&self, region_sup: RegionVid) -> Edges<'_, D> {
107-
let first = self.first_constraints[region_sup];
108-
Edges {
109-
graph: self,
110-
pointer: first,
120+
crate fn outgoing_edges<'a>(
121+
&'a self,
122+
region_sup: RegionVid,
123+
constraints: &'a ConstraintSet,
124+
static_region: RegionVid,
125+
) -> Edges<'a, D> {
126+
//if this is the `'static` region and the graph's direction is normal,
127+
//then setup the Edges iterator to return all regions #53178
128+
if region_sup == static_region && D::is_normal() {
129+
Edges {
130+
graph: self,
131+
constraints,
132+
pointer: None,
133+
next_static_idx: Some(0),
134+
static_region,
135+
}
136+
} else {
137+
//otherwise, just setup the iterator as normal
138+
let first = self.first_constraints[region_sup];
139+
Edges {
140+
graph: self,
141+
constraints,
142+
pointer: first,
143+
next_static_idx: None,
144+
static_region,
145+
}
111146
}
112147
}
113148
}
114149

115150
crate struct Edges<'s, D: ConstraintGraphDirecton> {
116151
graph: &'s ConstraintGraph<D>,
152+
constraints: &'s ConstraintSet,
117153
pointer: Option<ConstraintIndex>,
154+
next_static_idx: Option<usize>,
155+
static_region: RegionVid,
118156
}
119157

120158
impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> {
121-
type Item = ConstraintIndex;
159+
type Item = OutlivesConstraint;
122160

123161
fn next(&mut self) -> Option<Self::Item> {
124162
if let Some(p) = self.pointer {
125163
self.pointer = self.graph.next_constraints[p];
126-
Some(p)
164+
165+
Some(self.constraints[p])
166+
} else if let Some(next_static_idx) = self.next_static_idx {
167+
self.next_static_idx =
168+
if next_static_idx == (self.graph.first_constraints.len() - 1) {
169+
None
170+
} else {
171+
Some(next_static_idx + 1)
172+
};
173+
174+
Some(OutlivesConstraint {
175+
sup: self.static_region,
176+
sub: next_static_idx.into(),
177+
locations: Locations::All,
178+
})
127179
} else {
128180
None
129181
}
@@ -136,40 +188,44 @@ impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> {
136188
crate struct RegionGraph<'s, D: ConstraintGraphDirecton> {
137189
set: &'s ConstraintSet,
138190
constraint_graph: &'s ConstraintGraph<D>,
191+
static_region: RegionVid,
139192
}
140193

141194
impl<'s, D: ConstraintGraphDirecton> RegionGraph<'s, D> {
142195
/// Create a "dependency graph" where each region constraint `R1:
143196
/// R2` is treated as an edge `R1 -> R2`. We use this graph to
144197
/// construct SCCs for region inference but also for error
145198
/// reporting.
146-
crate fn new(set: &'s ConstraintSet, constraint_graph: &'s ConstraintGraph<D>) -> Self {
199+
crate fn new(
200+
set: &'s ConstraintSet,
201+
constraint_graph: &'s ConstraintGraph<D>,
202+
static_region: RegionVid,
203+
) -> Self {
147204
Self {
148205
set,
149206
constraint_graph,
207+
static_region,
150208
}
151209
}
152210

153211
/// Given a region `R`, iterate over all regions `R1` such that
154212
/// there exists a constraint `R: R1`.
155213
crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'_, D> {
156214
Successors {
157-
set: self.set,
158-
edges: self.constraint_graph.outgoing_edges(region_sup),
215+
edges: self.constraint_graph.outgoing_edges(region_sup, self.set, self.static_region),
159216
}
160217
}
161218
}
162219

163220
crate struct Successors<'s, D: ConstraintGraphDirecton> {
164-
set: &'s ConstraintSet,
165221
edges: Edges<'s, D>,
166222
}
167223

168224
impl<'s, D: ConstraintGraphDirecton> Iterator for Successors<'s, D> {
169225
type Item = RegionVid;
170226

171227
fn next(&mut self) -> Option<Self::Item> {
172-
self.edges.next().map(|c| D::end_region(&self.set[c]))
228+
self.edges.next().map(|c| D::end_region(&c))
173229
}
174230
}
175231

src/librustc_mir/borrow_check/nll/constraints/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,9 @@ impl ConstraintSet {
5858
crate fn compute_sccs(
5959
&self,
6060
constraint_graph: &graph::NormalConstraintGraph,
61+
static_region: RegionVid,
6162
) -> Sccs<RegionVid, ConstraintSccIndex> {
62-
let region_graph = &constraint_graph.region_graph(self);
63+
let region_graph = &constraint_graph.region_graph(self, static_region);
6364
Sccs::new(region_graph)
6465
}
6566
}

src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs

+22-21
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use borrow_check::nll::region_infer::{ConstraintIndex, RegionInferenceContext};
11+
use borrow_check::nll::constraints::OutlivesConstraint;
12+
use borrow_check::nll::region_infer::RegionInferenceContext;
1213
use borrow_check::nll::type_check::Locations;
1314
use rustc::hir::def_id::DefId;
1415
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
@@ -53,7 +54,7 @@ impl fmt::Display for ConstraintCategory {
5354
#[derive(Copy, Clone, PartialEq, Eq)]
5455
enum Trace {
5556
StartRegion,
56-
FromConstraint(ConstraintIndex),
57+
FromOutlivesConstraint(OutlivesConstraint),
5758
NotVisited,
5859
}
5960

@@ -80,12 +81,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
8081
debug!(
8182
"best_blame_constraint: path={:#?}",
8283
path.iter()
83-
.map(|&ci| format!(
84-
"{:?}: {:?} ({:?}: {:?})",
85-
ci,
86-
&self.constraints[ci],
87-
self.constraint_sccs.scc(self.constraints[ci].sup),
88-
self.constraint_sccs.scc(self.constraints[ci].sub),
84+
.map(|&c| format!(
85+
"{:?} ({:?}: {:?})",
86+
c,
87+
self.constraint_sccs.scc(c.sup),
88+
self.constraint_sccs.scc(c.sub),
8989
))
9090
.collect::<Vec<_>>()
9191
);
@@ -121,7 +121,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
121121
// highlight (e.g., a call site or something).
122122
let target_scc = self.constraint_sccs.scc(target_region);
123123
let best_choice = (0..path.len()).rev().find(|&i| {
124-
let constraint = &self.constraints[path[i]];
124+
let constraint = path[i];
125125

126126
let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup);
127127

@@ -164,7 +164,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
164164
&self,
165165
from_region: RegionVid,
166166
target_test: impl Fn(RegionVid) -> bool,
167-
) -> Option<(Vec<ConstraintIndex>, RegionVid)> {
167+
) -> Option<(Vec<OutlivesConstraint>, RegionVid)> {
168168
let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
169169
context[from_region] = Trace::StartRegion;
170170

@@ -185,9 +185,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
185185
Trace::NotVisited => {
186186
bug!("found unvisited region {:?} on path to {:?}", p, r)
187187
}
188-
Trace::FromConstraint(c) => {
188+
Trace::FromOutlivesConstraint(c) => {
189189
result.push(c);
190-
p = self.constraints[c].sup;
190+
p = c.sup;
191191
}
192192

193193
Trace::StartRegion => {
@@ -201,11 +201,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
201201
// Otherwise, walk over the outgoing constraints and
202202
// enqueue any regions we find, keeping track of how we
203203
// reached them.
204-
for constraint in self.constraint_graph.outgoing_edges(r) {
205-
assert_eq!(self.constraints[constraint].sup, r);
206-
let sub_region = self.constraints[constraint].sub;
204+
let fr_static = self.universal_regions.fr_static;
205+
for constraint in self.constraint_graph.outgoing_edges(r,
206+
&self.constraints,
207+
fr_static) {
208+
assert_eq!(constraint.sup, r);
209+
let sub_region = constraint.sub;
207210
if let Trace::NotVisited = context[sub_region] {
208-
context[sub_region] = Trace::FromConstraint(constraint);
211+
context[sub_region] = Trace::FromOutlivesConstraint(constraint);
209212
deque.push_back(sub_region);
210213
}
211214
}
@@ -216,8 +219,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
216219

217220
/// This function will return true if a constraint is interesting and false if a constraint
218221
/// is not. It is useful in filtering constraint paths to only interesting points.
219-
fn constraint_is_interesting(&self, index: ConstraintIndex) -> bool {
220-
let constraint = self.constraints[index];
222+
fn constraint_is_interesting(&self, constraint: OutlivesConstraint) -> bool {
221223
debug!(
222224
"constraint_is_interesting: locations={:?} constraint={:?}",
223225
constraint.locations, constraint
@@ -232,19 +234,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
232234
/// This function classifies a constraint from a location.
233235
fn classify_constraint(
234236
&self,
235-
index: ConstraintIndex,
237+
constraint: OutlivesConstraint,
236238
mir: &Mir<'tcx>,
237239
tcx: TyCtxt<'_, '_, 'tcx>,
238240
) -> (ConstraintCategory, Span) {
239-
let constraint = self.constraints[index];
240241
debug!("classify_constraint: constraint={:?}", constraint);
241242
let span = constraint.locations.span(mir);
242243
let location = constraint
243244
.locations
244245
.from_location()
245246
.unwrap_or(Location::START);
246247

247-
if !self.constraint_is_interesting(index) {
248+
if !self.constraint_is_interesting(constraint) {
248249
return (ConstraintCategory::Boring, span);
249250
}
250251

0 commit comments

Comments
 (0)