1
Fork 0

use Vec for region constraints

This commit is contained in:
Ali MJ Al-Nasrawy 2023-12-11 13:03:35 +00:00
parent 604f185fae
commit 9f7d0e91b5
9 changed files with 50 additions and 33 deletions

View file

@ -137,6 +137,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
) -> LexicalRegionResolutions<'tcx> { ) -> LexicalRegionResolutions<'tcx> {
let mut var_data = self.construct_var_data(); let mut var_data = self.construct_var_data();
// Deduplicating constraints is shown to have a positive perf impact.
self.data.constraints.sort_by_key(|(constraint, _)| *constraint);
self.data.constraints.dedup_by_key(|(constraint, _)| *constraint);
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
self.dump_constraints(); self.dump_constraints();
} }
@ -183,7 +187,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
let mut constraints = IndexVec::from_elem(Vec::new(), &var_values.values); let mut constraints = IndexVec::from_elem(Vec::new(), &var_values.values);
// Tracks the changed region vids. // Tracks the changed region vids.
let mut changes = Vec::new(); let mut changes = Vec::new();
for constraint in self.data.constraints.keys() { for (constraint, _) in &self.data.constraints {
match *constraint { match *constraint {
Constraint::RegSubVar(a_region, b_vid) => { Constraint::RegSubVar(a_region, b_vid) => {
let b_data = var_values.value_mut(b_vid); let b_data = var_values.value_mut(b_vid);
@ -678,7 +682,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
let dummy_source = graph.add_node(()); let dummy_source = graph.add_node(());
let dummy_sink = graph.add_node(()); let dummy_sink = graph.add_node(());
for constraint in self.data.constraints.keys() { for (constraint, _) in &self.data.constraints {
match *constraint { match *constraint {
Constraint::VarSubVar(a_id, b_id) => { Constraint::VarSubVar(a_id, b_id) => {
graph.add_edge(NodeIndex(a_id.index()), NodeIndex(b_id.index()), *constraint); graph.add_edge(NodeIndex(a_id.index()), NodeIndex(b_id.index()), *constraint);
@ -885,9 +889,11 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
} }
Constraint::RegSubVar(region, _) | Constraint::VarSubReg(_, region) => { Constraint::RegSubVar(region, _) | Constraint::VarSubReg(_, region) => {
let constraint_idx =
this.constraints.binary_search_by(|(c, _)| c.cmp(&edge.data)).unwrap();
state.result.push(RegionAndOrigin { state.result.push(RegionAndOrigin {
region, region,
origin: this.constraints.get(&edge.data).unwrap().clone(), origin: this.constraints[constraint_idx].1.clone(),
}); });
} }

View file

@ -416,8 +416,8 @@ impl<'tcx> MiniGraph<'tcx> {
region_constraints.undo_log.region_constraints_in_snapshot(&snapshot.undo_snapshot) region_constraints.undo_log.region_constraints_in_snapshot(&snapshot.undo_snapshot)
{ {
match undo_entry { match undo_entry {
AddConstraint(constraint) => { &AddConstraint(i) => {
each_constraint(constraint); each_constraint(&region_constraints.data().constraints[i].0);
} }
&AddVerify(i) => span_bug!( &AddVerify(i) => span_bug!(
region_constraints.data().verifys[i].origin.span(), region_constraints.data().verifys[i].origin.span(),
@ -430,8 +430,8 @@ impl<'tcx> MiniGraph<'tcx> {
region_constraints region_constraints
.data() .data()
.constraints .constraints
.keys() .iter()
.for_each(|constraint| each_constraint(constraint)); .for_each(|(constraint, _)| each_constraint(constraint));
} }
} }

View file

@ -20,7 +20,6 @@ use rustc_middle::ty::{ReBound, ReVar};
use rustc_middle::ty::{Region, RegionVid}; use rustc_middle::ty::{Region, RegionVid};
use rustc_span::Span; use rustc_span::Span;
use std::collections::BTreeMap;
use std::ops::Range; use std::ops::Range;
use std::{cmp, fmt, mem}; use std::{cmp, fmt, mem};
@ -90,7 +89,7 @@ pub type VarInfos = IndexVec<RegionVid, RegionVariableInfo>;
pub struct RegionConstraintData<'tcx> { pub struct RegionConstraintData<'tcx> {
/// Constraints of the form `A <= B`, where either `A` or `B` can /// Constraints of the form `A <= B`, where either `A` or `B` can
/// be a region variable (or neither, as it happens). /// be a region variable (or neither, as it happens).
pub constraints: BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>, pub constraints: Vec<(Constraint<'tcx>, SubregionOrigin<'tcx>)>,
/// Constraints of the form `R0 member of [R1, ..., Rn]`, meaning that /// Constraints of the form `R0 member of [R1, ..., Rn]`, meaning that
/// `R0` must be equal to one of the regions `R1..Rn`. These occur /// `R0` must be equal to one of the regions `R1..Rn`. These occur
@ -273,7 +272,7 @@ pub(crate) enum UndoLog<'tcx> {
AddVar(RegionVid), AddVar(RegionVid),
/// We added the given `constraint`. /// We added the given `constraint`.
AddConstraint(Constraint<'tcx>), AddConstraint(usize),
/// We added the given `verify`. /// We added the given `verify`.
AddVerify(usize), AddVerify(usize),
@ -319,8 +318,9 @@ impl<'tcx> RegionConstraintStorage<'tcx> {
self.var_infos.pop().unwrap(); self.var_infos.pop().unwrap();
assert_eq!(self.var_infos.len(), vid.index()); assert_eq!(self.var_infos.len(), vid.index());
} }
AddConstraint(ref constraint) => { AddConstraint(index) => {
self.data.constraints.remove(constraint); self.data.constraints.pop().unwrap();
assert_eq!(self.data.constraints.len(), index);
} }
AddVerify(index) => { AddVerify(index) => {
self.data.verifys.pop(); self.data.verifys.pop();
@ -443,14 +443,9 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
// cannot add constraints once regions are resolved // cannot add constraints once regions are resolved
debug!("RegionConstraintCollector: add_constraint({:?})", constraint); debug!("RegionConstraintCollector: add_constraint({:?})", constraint);
// never overwrite an existing (constraint, origin) - only insert one if it isn't let index = self.storage.data.constraints.len();
// present in the map yet. This prevents origins from outside the snapshot being self.storage.data.constraints.push((constraint, origin));
// replaced with "less informative" origins e.g., during calls to `can_eq` self.undo_log.push(AddConstraint(index));
let undo_log = &mut self.undo_log;
self.storage.data.constraints.entry(constraint).or_insert_with(|| {
undo_log.push(AddConstraint(constraint));
origin
});
} }
fn add_verify(&mut self, verify: Verify<'tcx>) { fn add_verify(&mut self, verify: Verify<'tcx>) {

View file

@ -477,7 +477,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
let mut vid_map: FxHashMap<RegionTarget<'cx>, RegionDeps<'cx>> = FxHashMap::default(); let mut vid_map: FxHashMap<RegionTarget<'cx>, RegionDeps<'cx>> = FxHashMap::default();
let mut finished_map = FxHashMap::default(); let mut finished_map = FxHashMap::default();
for constraint in regions.constraints.keys() { for (constraint, _) in &regions.constraints {
match constraint { match constraint {
&Constraint::VarSubVar(r1, r2) => { &Constraint::VarSubVar(r1, r2) => {
{ {

View file

@ -195,7 +195,7 @@ where
// into a map. Each RegionTarget (either a RegionVid or a Region) maps // into a map. Each RegionTarget (either a RegionVid or a Region) maps
// to its smaller and larger regions. Note that 'larger' regions correspond // to its smaller and larger regions. Note that 'larger' regions correspond
// to sub-regions in Rust code (e.g., in 'a: 'b, 'a is the larger region). // to sub-regions in Rust code (e.g., in 'a: 'b, 'a is the larger region).
for constraint in regions.constraints.keys() { for (constraint, _) in &regions.constraints {
match *constraint { match *constraint {
Constraint::VarSubVar(r1, r2) => { Constraint::VarSubVar(r1, r2) => {
{ {

View file

@ -4,8 +4,8 @@ error[E0308]: mismatched types
LL | assert_all::<_, &String>(id); LL | assert_all::<_, &String>(id);
| ^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | ^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
| |
= note: expected reference `&String` = note: expected trait `for<'a> <for<'a> fn(&'a String) -> &'a String {id} as FnMut<(&'a String,)>>`
found reference `&String` found trait `for<'a> <for<'a> fn(&'a String) -> &'a String {id} as FnMut<(&'a String,)>>`
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -41,7 +41,7 @@ where
// isize>`, we require `T : for<'a> Bar<&'a isize>`, but the where // isize>`, we require `T : for<'a> Bar<&'a isize>`, but the where
// clause only specifies `T : Bar<&'b isize>`. // clause only specifies `T : Bar<&'b isize>`.
foo_hrtb_bar_not(&mut t); foo_hrtb_bar_not(&mut t);
//~^ ERROR implementation of `Bar` is not general enough //~^ ERROR mismatched types
//~^^ ERROR lifetime may not live long enough //~^^ ERROR lifetime may not live long enough
} }

View file

@ -53,14 +53,19 @@ note: due to current limitations in the borrow checker, this implies a `'static`
LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>,
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^
error: implementation of `Bar` is not general enough error[E0308]: mismatched types
--> $DIR/hrtb-perfect-forwarding.rs:43:5 --> $DIR/hrtb-perfect-forwarding.rs:43:5
| |
LL | foo_hrtb_bar_not(&mut t); LL | foo_hrtb_bar_not(&mut t);
| ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough | ^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
| |
= note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... = note: expected trait `for<'a> <T as Foo<&'a isize>>`
= note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` found trait `for<'a> <T as Foo<&'a isize>>`
note: the lifetime requirement is introduced here
--> $DIR/hrtb-perfect-forwarding.rs:37:8
|
LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>,
| ^^^^^^^^^^^^^^^^^^^^^^
warning: function cannot return without recursing warning: function cannot return without recursing
--> $DIR/hrtb-perfect-forwarding.rs:48:1 --> $DIR/hrtb-perfect-forwarding.rs:48:1
@ -77,3 +82,4 @@ LL | foo_hrtb_bar_hrtb(&mut t);
error: aborting due to 2 previous errors; 4 warnings emitted error: aborting due to 2 previous errors; 4 warnings emitted
For more information about this error, try `rustc --explain E0308`.

View file

@ -54,8 +54,13 @@ error[E0308]: mismatched types
LL | take_foo(|a: &i32| a); LL | take_foo(|a: &i32| a);
| ^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | ^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
| |
= note: expected reference `&_` = note: expected trait `for<'a> <{closure@$DIR/issue-79187-2.rs:11:14: 11:23} as FnOnce<(&'a i32,)>>`
found reference `&_` found trait `for<'a> <{closure@$DIR/issue-79187-2.rs:11:14: 11:23} as FnOnce<(&'a i32,)>>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-79187-2.rs:11:14
|
LL | take_foo(|a: &i32| a);
| ^^^^^^^^^
note: the lifetime requirement is introduced here note: the lifetime requirement is introduced here
--> $DIR/issue-79187-2.rs:5:21 --> $DIR/issue-79187-2.rs:5:21
| |
@ -68,8 +73,13 @@ error[E0308]: mismatched types
LL | take_foo(|a: &i32| -> &i32 { a }); LL | take_foo(|a: &i32| -> &i32 { a });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
| |
= note: expected reference `&_` = note: expected trait `for<'a> <{closure@$DIR/issue-79187-2.rs:14:14: 14:31} as FnOnce<(&'a i32,)>>`
found reference `&_` found trait `for<'a> <{closure@$DIR/issue-79187-2.rs:14:14: 14:31} as FnOnce<(&'a i32,)>>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-79187-2.rs:14:14
|
LL | take_foo(|a: &i32| -> &i32 { a });
| ^^^^^^^^^^^^^^^^^
note: the lifetime requirement is introduced here note: the lifetime requirement is introduced here
--> $DIR/issue-79187-2.rs:5:21 --> $DIR/issue-79187-2.rs:5:21
| |