Auto merge of #59657 - Centril:rollup-w5p98mc, r=Centril
Rollup of 4 pull requests Successful merges: - #55448 (Add 'partition_at_index/_by/_by_key' for slices.) - #59186 (improve worst-case performance of BTreeSet intersection v3) - #59514 (Remove adt_def from projections and downcasts in MIR) - #59630 (Shrink `mir::Statement`.) Failed merges: r? @ghost
This commit is contained in:
commit
546cb21f58
51 changed files with 1032 additions and 460 deletions
|
@ -3,59 +3,49 @@ use std::collections::BTreeSet;
|
|||
use rand::{thread_rng, Rng};
|
||||
use test::{black_box, Bencher};
|
||||
|
||||
fn random(n1: u32, n2: u32) -> [BTreeSet<usize>; 2] {
|
||||
fn random(n: usize) -> BTreeSet<usize> {
|
||||
let mut rng = thread_rng();
|
||||
let mut set1 = BTreeSet::new();
|
||||
let mut set2 = BTreeSet::new();
|
||||
for _ in 0..n1 {
|
||||
let i = rng.gen::<usize>();
|
||||
set1.insert(i);
|
||||
let mut set = BTreeSet::new();
|
||||
while set.len() < n {
|
||||
set.insert(rng.gen());
|
||||
}
|
||||
for _ in 0..n2 {
|
||||
let i = rng.gen::<usize>();
|
||||
set2.insert(i);
|
||||
}
|
||||
[set1, set2]
|
||||
assert_eq!(set.len(), n);
|
||||
set
|
||||
}
|
||||
|
||||
fn staggered(n1: u32, n2: u32) -> [BTreeSet<u32>; 2] {
|
||||
let mut even = BTreeSet::new();
|
||||
let mut odd = BTreeSet::new();
|
||||
for i in 0..n1 {
|
||||
even.insert(i * 2);
|
||||
fn neg(n: usize) -> BTreeSet<i32> {
|
||||
let mut set = BTreeSet::new();
|
||||
for i in -(n as i32)..=-1 {
|
||||
set.insert(i);
|
||||
}
|
||||
for i in 0..n2 {
|
||||
odd.insert(i * 2 + 1);
|
||||
}
|
||||
[even, odd]
|
||||
assert_eq!(set.len(), n);
|
||||
set
|
||||
}
|
||||
|
||||
fn neg_vs_pos(n1: u32, n2: u32) -> [BTreeSet<i32>; 2] {
|
||||
let mut neg = BTreeSet::new();
|
||||
let mut pos = BTreeSet::new();
|
||||
for i in -(n1 as i32)..=-1 {
|
||||
neg.insert(i);
|
||||
fn pos(n: usize) -> BTreeSet<i32> {
|
||||
let mut set = BTreeSet::new();
|
||||
for i in 1..=(n as i32) {
|
||||
set.insert(i);
|
||||
}
|
||||
for i in 1..=(n2 as i32) {
|
||||
pos.insert(i);
|
||||
}
|
||||
[neg, pos]
|
||||
assert_eq!(set.len(), n);
|
||||
set
|
||||
}
|
||||
|
||||
fn pos_vs_neg(n1: u32, n2: u32) -> [BTreeSet<i32>; 2] {
|
||||
let mut neg = BTreeSet::new();
|
||||
let mut pos = BTreeSet::new();
|
||||
for i in -(n1 as i32)..=-1 {
|
||||
neg.insert(i);
|
||||
|
||||
fn stagger(n1: usize, factor: usize) -> [BTreeSet<u32>; 2] {
|
||||
let n2 = n1 * factor;
|
||||
let mut sets = [BTreeSet::new(), BTreeSet::new()];
|
||||
for i in 0..(n1 + n2) {
|
||||
let b = i % (factor + 1) != 0;
|
||||
sets[b as usize].insert(i as u32);
|
||||
}
|
||||
for i in 1..=(n2 as i32) {
|
||||
pos.insert(i);
|
||||
}
|
||||
[pos, neg]
|
||||
assert_eq!(sets[0].len(), n1);
|
||||
assert_eq!(sets[1].len(), n2);
|
||||
sets
|
||||
}
|
||||
|
||||
macro_rules! set_intersection_bench {
|
||||
($name: ident, $sets: expr) => {
|
||||
macro_rules! set_bench {
|
||||
($name: ident, $set_func: ident, $result_func: ident, $sets: expr) => {
|
||||
#[bench]
|
||||
pub fn $name(b: &mut Bencher) {
|
||||
// setup
|
||||
|
@ -63,26 +53,36 @@ macro_rules! set_intersection_bench {
|
|||
|
||||
// measure
|
||||
b.iter(|| {
|
||||
let x = sets[0].intersection(&sets[1]).count();
|
||||
let x = sets[0].$set_func(&sets[1]).$result_func();
|
||||
black_box(x);
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
set_intersection_bench! {intersect_random_100, random(100, 100)}
|
||||
set_intersection_bench! {intersect_random_10k, random(10_000, 10_000)}
|
||||
set_intersection_bench! {intersect_random_10_vs_10k, random(10, 10_000)}
|
||||
set_intersection_bench! {intersect_random_10k_vs_10, random(10_000, 10)}
|
||||
set_intersection_bench! {intersect_staggered_100, staggered(100, 100)}
|
||||
set_intersection_bench! {intersect_staggered_10k, staggered(10_000, 10_000)}
|
||||
set_intersection_bench! {intersect_staggered_10_vs_10k, staggered(10, 10_000)}
|
||||
set_intersection_bench! {intersect_staggered_10k_vs_10, staggered(10_000, 10)}
|
||||
set_intersection_bench! {intersect_neg_vs_pos_100, neg_vs_pos(100, 100)}
|
||||
set_intersection_bench! {intersect_neg_vs_pos_10k, neg_vs_pos(10_000, 10_000)}
|
||||
set_intersection_bench! {intersect_neg_vs_pos_10_vs_10k,neg_vs_pos(10, 10_000)}
|
||||
set_intersection_bench! {intersect_neg_vs_pos_10k_vs_10,neg_vs_pos(10_000, 10)}
|
||||
set_intersection_bench! {intersect_pos_vs_neg_100, pos_vs_neg(100, 100)}
|
||||
set_intersection_bench! {intersect_pos_vs_neg_10k, pos_vs_neg(10_000, 10_000)}
|
||||
set_intersection_bench! {intersect_pos_vs_neg_10_vs_10k,pos_vs_neg(10, 10_000)}
|
||||
set_intersection_bench! {intersect_pos_vs_neg_10k_vs_10,pos_vs_neg(10_000, 10)}
|
||||
set_bench! {intersection_100_neg_vs_100_pos, intersection, count, [neg(100), pos(100)]}
|
||||
set_bench! {intersection_100_neg_vs_10k_pos, intersection, count, [neg(100), pos(10_000)]}
|
||||
set_bench! {intersection_100_pos_vs_100_neg, intersection, count, [pos(100), neg(100)]}
|
||||
set_bench! {intersection_100_pos_vs_10k_neg, intersection, count, [pos(100), neg(10_000)]}
|
||||
set_bench! {intersection_10k_neg_vs_100_pos, intersection, count, [neg(10_000), pos(100)]}
|
||||
set_bench! {intersection_10k_neg_vs_10k_pos, intersection, count, [neg(10_000), pos(10_000)]}
|
||||
set_bench! {intersection_10k_pos_vs_100_neg, intersection, count, [pos(10_000), neg(100)]}
|
||||
set_bench! {intersection_10k_pos_vs_10k_neg, intersection, count, [pos(10_000), neg(10_000)]}
|
||||
set_bench! {intersection_random_100_vs_100, intersection, count, [random(100), random(100)]}
|
||||
set_bench! {intersection_random_100_vs_10k, intersection, count, [random(100), random(10_000)]}
|
||||
set_bench! {intersection_random_10k_vs_100, intersection, count, [random(10_000), random(100)]}
|
||||
set_bench! {intersection_random_10k_vs_10k, intersection, count, [random(10_000), random(10_000)]}
|
||||
set_bench! {intersection_staggered_100_vs_100, intersection, count, stagger(100, 1)}
|
||||
set_bench! {intersection_staggered_10k_vs_10k, intersection, count, stagger(10_000, 1)}
|
||||
set_bench! {intersection_staggered_100_vs_10k, intersection, count, stagger(100, 100)}
|
||||
set_bench! {difference_random_100_vs_100, difference, count, [random(100), random(100)]}
|
||||
set_bench! {difference_random_100_vs_10k, difference, count, [random(100), random(10_000)]}
|
||||
set_bench! {difference_random_10k_vs_100, difference, count, [random(10_000), random(100)]}
|
||||
set_bench! {difference_random_10k_vs_10k, difference, count, [random(10_000), random(10_000)]}
|
||||
set_bench! {difference_staggered_100_vs_100, difference, count, stagger(100, 1)}
|
||||
set_bench! {difference_staggered_10k_vs_10k, difference, count, stagger(10_000, 1)}
|
||||
set_bench! {difference_staggered_100_vs_10k, difference, count, stagger(100, 100)}
|
||||
set_bench! {is_subset_100_vs_100, is_subset, clone, [pos(100), pos(100)]}
|
||||
set_bench! {is_subset_100_vs_10k, is_subset, clone, [pos(100), pos(10_000)]}
|
||||
set_bench! {is_subset_10k_vs_100, is_subset, clone, [pos(10_000), pos(100)]}
|
||||
set_bench! {is_subset_10k_vs_10k, is_subset, clone, [pos(10_000), pos(10_000)]}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
use core::borrow::Borrow;
|
||||
use core::cmp::Ordering::{self, Less, Greater, Equal};
|
||||
use core::cmp::{min, max};
|
||||
use core::cmp::max;
|
||||
use core::fmt::{self, Debug};
|
||||
use core::iter::{Peekable, FromIterator, FusedIterator};
|
||||
use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeBounds};
|
||||
|
@ -118,17 +118,36 @@ pub struct Range<'a, T: 'a> {
|
|||
/// [`difference`]: struct.BTreeSet.html#method.difference
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Difference<'a, T: 'a> {
|
||||
a: Peekable<Iter<'a, T>>,
|
||||
b: Peekable<Iter<'a, T>>,
|
||||
inner: DifferenceInner<'a, T>,
|
||||
}
|
||||
enum DifferenceInner<'a, T: 'a> {
|
||||
Stitch {
|
||||
self_iter: Iter<'a, T>,
|
||||
other_iter: Peekable<Iter<'a, T>>,
|
||||
},
|
||||
Search {
|
||||
self_iter: Iter<'a, T>,
|
||||
other_set: &'a BTreeSet<T>,
|
||||
},
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Difference<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Difference")
|
||||
.field(&self.a)
|
||||
.field(&self.b)
|
||||
.finish()
|
||||
match &self.inner {
|
||||
DifferenceInner::Stitch {
|
||||
self_iter,
|
||||
other_iter,
|
||||
} => f
|
||||
.debug_tuple("Difference")
|
||||
.field(&self_iter)
|
||||
.field(&other_iter)
|
||||
.finish(),
|
||||
DifferenceInner::Search {
|
||||
self_iter,
|
||||
other_set: _,
|
||||
} => f.debug_tuple("Difference").field(&self_iter).finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,17 +183,36 @@ impl<T: fmt::Debug> fmt::Debug for SymmetricDifference<'_, T> {
|
|||
/// [`intersection`]: struct.BTreeSet.html#method.intersection
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Intersection<'a, T: 'a> {
|
||||
a: Peekable<Iter<'a, T>>,
|
||||
b: Peekable<Iter<'a, T>>,
|
||||
inner: IntersectionInner<'a, T>,
|
||||
}
|
||||
enum IntersectionInner<'a, T: 'a> {
|
||||
Stitch {
|
||||
small_iter: Iter<'a, T>, // for size_hint, should be the smaller of the sets
|
||||
other_iter: Iter<'a, T>,
|
||||
},
|
||||
Search {
|
||||
small_iter: Iter<'a, T>,
|
||||
large_set: &'a BTreeSet<T>,
|
||||
},
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Intersection<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Intersection")
|
||||
.field(&self.a)
|
||||
.field(&self.b)
|
||||
.finish()
|
||||
match &self.inner {
|
||||
IntersectionInner::Stitch {
|
||||
small_iter,
|
||||
other_iter,
|
||||
} => f
|
||||
.debug_tuple("Intersection")
|
||||
.field(&small_iter)
|
||||
.field(&other_iter)
|
||||
.finish(),
|
||||
IntersectionInner::Search {
|
||||
small_iter,
|
||||
large_set: _,
|
||||
} => f.debug_tuple("Intersection").field(&small_iter).finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,6 +239,14 @@ impl<T: fmt::Debug> fmt::Debug for Union<'_, T> {
|
|||
}
|
||||
}
|
||||
|
||||
// This constant is used by functions that compare two sets.
|
||||
// It estimates the relative size at which searching performs better
|
||||
// than iterating, based on the benchmarks in
|
||||
// https://github.com/ssomers/rust_bench_btreeset_intersection;
|
||||
// It's used to divide rather than multiply sizes, to rule out overflow,
|
||||
// and it's a power of two to make that division cheap.
|
||||
const ITER_PERFORMANCE_TIPPING_SIZE_DIFF: usize = 16;
|
||||
|
||||
impl<T: Ord> BTreeSet<T> {
|
||||
/// Makes a new `BTreeSet` with a reasonable choice of B.
|
||||
///
|
||||
|
@ -268,9 +314,24 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> Difference<'a, T> {
|
||||
Difference {
|
||||
a: self.iter().peekable(),
|
||||
b: other.iter().peekable(),
|
||||
if self.len() > other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
|
||||
// Self is bigger than or not much smaller than other set.
|
||||
// Iterate both sets jointly, spotting matches along the way.
|
||||
Difference {
|
||||
inner: DifferenceInner::Stitch {
|
||||
self_iter: self.iter(),
|
||||
other_iter: other.iter().peekable(),
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// Self is much smaller than other set, or both sets are empty.
|
||||
// Iterate the small set, searching for matches in the large set.
|
||||
Difference {
|
||||
inner: DifferenceInner::Search {
|
||||
self_iter: self.iter(),
|
||||
other_set: other,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,9 +387,29 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn intersection<'a>(&'a self, other: &'a BTreeSet<T>) -> Intersection<'a, T> {
|
||||
Intersection {
|
||||
a: self.iter().peekable(),
|
||||
b: other.iter().peekable(),
|
||||
let (small, other) = if self.len() <= other.len() {
|
||||
(self, other)
|
||||
} else {
|
||||
(other, self)
|
||||
};
|
||||
if small.len() > other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
|
||||
// Small set is not much smaller than other set.
|
||||
// Iterate both sets jointly, spotting matches along the way.
|
||||
Intersection {
|
||||
inner: IntersectionInner::Stitch {
|
||||
small_iter: small.iter(),
|
||||
other_iter: other.iter(),
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// Big difference in number of elements, or both sets are empty.
|
||||
// Iterate the small set, searching for matches in the large set.
|
||||
Intersection {
|
||||
inner: IntersectionInner::Search {
|
||||
small_iter: small.iter(),
|
||||
large_set: other,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,28 +543,44 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn is_subset(&self, other: &BTreeSet<T>) -> bool {
|
||||
// Stolen from TreeMap
|
||||
let mut x = self.iter();
|
||||
let mut y = other.iter();
|
||||
let mut a = x.next();
|
||||
let mut b = y.next();
|
||||
while a.is_some() {
|
||||
if b.is_none() {
|
||||
return false;
|
||||
// Same result as self.difference(other).next().is_none()
|
||||
// but the 3 paths below are faster (in order: hugely, 20%, 5%).
|
||||
if self.len() > other.len() {
|
||||
false
|
||||
} else if self.len() > other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
|
||||
// Self is not much smaller than other set.
|
||||
// Stolen from TreeMap
|
||||
let mut x = self.iter();
|
||||
let mut y = other.iter();
|
||||
let mut a = x.next();
|
||||
let mut b = y.next();
|
||||
while a.is_some() {
|
||||
if b.is_none() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let a1 = a.unwrap();
|
||||
let b1 = b.unwrap();
|
||||
|
||||
match b1.cmp(a1) {
|
||||
Less => (),
|
||||
Greater => return false,
|
||||
Equal => a = x.next(),
|
||||
}
|
||||
|
||||
b = y.next();
|
||||
}
|
||||
|
||||
let a1 = a.unwrap();
|
||||
let b1 = b.unwrap();
|
||||
|
||||
match b1.cmp(a1) {
|
||||
Less => (),
|
||||
Greater => return false,
|
||||
Equal => a = x.next(),
|
||||
true
|
||||
} else {
|
||||
// Big difference in number of elements, or both sets are empty.
|
||||
// Iterate the small set, searching for matches in the large set.
|
||||
for next in self {
|
||||
if !other.contains(next) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
b = y.next();
|
||||
true
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// Returns `true` if the set is a superset of another,
|
||||
|
@ -1001,8 +1098,22 @@ fn cmp_opt<T: Ord>(x: Option<&T>, y: Option<&T>, short: Ordering, long: Ordering
|
|||
impl<T> Clone for Difference<'_, T> {
|
||||
fn clone(&self) -> Self {
|
||||
Difference {
|
||||
a: self.a.clone(),
|
||||
b: self.b.clone(),
|
||||
inner: match &self.inner {
|
||||
DifferenceInner::Stitch {
|
||||
self_iter,
|
||||
other_iter,
|
||||
} => DifferenceInner::Stitch {
|
||||
self_iter: self_iter.clone(),
|
||||
other_iter: other_iter.clone(),
|
||||
},
|
||||
DifferenceInner::Search {
|
||||
self_iter,
|
||||
other_set,
|
||||
} => DifferenceInner::Search {
|
||||
self_iter: self_iter.clone(),
|
||||
other_set,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1011,24 +1122,52 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> {
|
|||
type Item = &'a T;
|
||||
|
||||
fn next(&mut self) -> Option<&'a T> {
|
||||
loop {
|
||||
match cmp_opt(self.a.peek(), self.b.peek(), Less, Less) {
|
||||
Less => return self.a.next(),
|
||||
Equal => {
|
||||
self.a.next();
|
||||
self.b.next();
|
||||
}
|
||||
Greater => {
|
||||
self.b.next();
|
||||
match &mut self.inner {
|
||||
DifferenceInner::Stitch {
|
||||
self_iter,
|
||||
other_iter,
|
||||
} => {
|
||||
let mut self_next = self_iter.next()?;
|
||||
loop {
|
||||
match other_iter
|
||||
.peek()
|
||||
.map_or(Less, |other_next| Ord::cmp(self_next, other_next))
|
||||
{
|
||||
Less => return Some(self_next),
|
||||
Equal => {
|
||||
self_next = self_iter.next()?;
|
||||
other_iter.next();
|
||||
}
|
||||
Greater => {
|
||||
other_iter.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DifferenceInner::Search {
|
||||
self_iter,
|
||||
other_set,
|
||||
} => loop {
|
||||
let self_next = self_iter.next()?;
|
||||
if !other_set.contains(&self_next) {
|
||||
return Some(self_next);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let a_len = self.a.len();
|
||||
let b_len = self.b.len();
|
||||
(a_len.saturating_sub(b_len), Some(a_len))
|
||||
let (self_len, other_len) = match &self.inner {
|
||||
DifferenceInner::Stitch {
|
||||
self_iter,
|
||||
other_iter
|
||||
} => (self_iter.len(), other_iter.len()),
|
||||
DifferenceInner::Search {
|
||||
self_iter,
|
||||
other_set
|
||||
} => (self_iter.len(), other_set.len()),
|
||||
};
|
||||
(self_len.saturating_sub(other_len), Some(self_len))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1073,8 +1212,22 @@ impl<T: Ord> FusedIterator for SymmetricDifference<'_, T> {}
|
|||
impl<T> Clone for Intersection<'_, T> {
|
||||
fn clone(&self) -> Self {
|
||||
Intersection {
|
||||
a: self.a.clone(),
|
||||
b: self.b.clone(),
|
||||
inner: match &self.inner {
|
||||
IntersectionInner::Stitch {
|
||||
small_iter,
|
||||
other_iter,
|
||||
} => IntersectionInner::Stitch {
|
||||
small_iter: small_iter.clone(),
|
||||
other_iter: other_iter.clone(),
|
||||
},
|
||||
IntersectionInner::Search {
|
||||
small_iter,
|
||||
large_set,
|
||||
} => IntersectionInner::Search {
|
||||
small_iter: small_iter.clone(),
|
||||
large_set,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1083,24 +1236,39 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> {
|
|||
type Item = &'a T;
|
||||
|
||||
fn next(&mut self) -> Option<&'a T> {
|
||||
loop {
|
||||
match Ord::cmp(self.a.peek()?, self.b.peek()?) {
|
||||
Less => {
|
||||
self.a.next();
|
||||
}
|
||||
Equal => {
|
||||
self.b.next();
|
||||
return self.a.next();
|
||||
}
|
||||
Greater => {
|
||||
self.b.next();
|
||||
match &mut self.inner {
|
||||
IntersectionInner::Stitch {
|
||||
small_iter,
|
||||
other_iter,
|
||||
} => {
|
||||
let mut small_next = small_iter.next()?;
|
||||
let mut other_next = other_iter.next()?;
|
||||
loop {
|
||||
match Ord::cmp(small_next, other_next) {
|
||||
Less => small_next = small_iter.next()?,
|
||||
Greater => other_next = other_iter.next()?,
|
||||
Equal => return Some(small_next),
|
||||
}
|
||||
}
|
||||
}
|
||||
IntersectionInner::Search {
|
||||
small_iter,
|
||||
large_set,
|
||||
} => loop {
|
||||
let small_next = small_iter.next()?;
|
||||
if large_set.contains(&small_next) {
|
||||
return Some(small_next);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(0, Some(min(self.a.len(), self.b.len())))
|
||||
let min_len = match &self.inner {
|
||||
IntersectionInner::Stitch { small_iter, .. } => small_iter.len(),
|
||||
IntersectionInner::Search { small_iter, .. } => small_iter.len(),
|
||||
};
|
||||
(0, Some(min_len))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,20 @@ fn test_intersection() {
|
|||
check_intersection(&[11, 1, 3, 77, 103, 5, -5],
|
||||
&[2, 11, 77, -9, -42, 5, 3],
|
||||
&[3, 5, 11, 77]);
|
||||
let large = (0..1000).collect::<Vec<_>>();
|
||||
check_intersection(&[], &large, &[]);
|
||||
check_intersection(&large, &[], &[]);
|
||||
check_intersection(&[-1], &large, &[]);
|
||||
check_intersection(&large, &[-1], &[]);
|
||||
check_intersection(&[0], &large, &[0]);
|
||||
check_intersection(&large, &[0], &[0]);
|
||||
check_intersection(&[999], &large, &[999]);
|
||||
check_intersection(&large, &[999], &[999]);
|
||||
check_intersection(&[1000], &large, &[]);
|
||||
check_intersection(&large, &[1000], &[]);
|
||||
check_intersection(&[11, 5000, 1, 3, 77, 8924, 103],
|
||||
&large,
|
||||
&[1, 3, 11, 77, 103]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -84,6 +98,18 @@ fn test_difference() {
|
|||
check_difference(&[-5, 11, 22, 33, 40, 42],
|
||||
&[-12, -5, 14, 23, 34, 38, 39, 50],
|
||||
&[11, 22, 33, 40, 42]);
|
||||
let large = (0..1000).collect::<Vec<_>>();
|
||||
check_difference(&[], &large, &[]);
|
||||
check_difference(&[-1], &large, &[-1]);
|
||||
check_difference(&[0], &large, &[]);
|
||||
check_difference(&[999], &large, &[]);
|
||||
check_difference(&[1000], &large, &[1000]);
|
||||
check_difference(&[11, 5000, 1, 3, 77, 8924, 103],
|
||||
&large,
|
||||
&[5000, 8924]);
|
||||
check_difference(&large, &[], &large);
|
||||
check_difference(&large, &[-1], &large);
|
||||
check_difference(&large, &[1000], &large);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -114,6 +140,41 @@ fn test_union() {
|
|||
&[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Only tests the simple function definition with respect to intersection
|
||||
fn test_is_disjoint() {
|
||||
let one = [1].into_iter().collect::<BTreeSet<_>>();
|
||||
let two = [2].into_iter().collect::<BTreeSet<_>>();
|
||||
assert!(one.is_disjoint(&two));
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Also tests the trivial function definition of is_superset
|
||||
fn test_is_subset() {
|
||||
fn is_subset(a: &[i32], b: &[i32]) -> bool {
|
||||
let set_a = a.iter().collect::<BTreeSet<_>>();
|
||||
let set_b = b.iter().collect::<BTreeSet<_>>();
|
||||
set_a.is_subset(&set_b)
|
||||
}
|
||||
|
||||
assert_eq!(is_subset(&[], &[]), true);
|
||||
assert_eq!(is_subset(&[], &[1, 2]), true);
|
||||
assert_eq!(is_subset(&[0], &[1, 2]), false);
|
||||
assert_eq!(is_subset(&[1], &[1, 2]), true);
|
||||
assert_eq!(is_subset(&[2], &[1, 2]), true);
|
||||
assert_eq!(is_subset(&[3], &[1, 2]), false);
|
||||
assert_eq!(is_subset(&[1, 2], &[1]), false);
|
||||
assert_eq!(is_subset(&[1, 2], &[1, 2]), true);
|
||||
assert_eq!(is_subset(&[1, 2], &[2, 3]), false);
|
||||
let large = (0..1000).collect::<Vec<_>>();
|
||||
assert_eq!(is_subset(&[], &large), true);
|
||||
assert_eq!(is_subset(&large, &[]), false);
|
||||
assert_eq!(is_subset(&[-1], &large), false);
|
||||
assert_eq!(is_subset(&[0], &large), true);
|
||||
assert_eq!(is_subset(&[1, 2], &large), true);
|
||||
assert_eq!(is_subset(&[999, 1000], &large), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zip() {
|
||||
let mut x = BTreeSet::new();
|
||||
|
|
|
@ -1585,6 +1585,153 @@ impl<T> [T] {
|
|||
sort::quicksort(self, |a, b| f(a).lt(&f(b)));
|
||||
}
|
||||
|
||||
/// Reorder the slice such that the element at `index` is at its final sorted position.
|
||||
///
|
||||
/// This reordering has the additional property that any value at position `i < index` will be
|
||||
/// less than or equal to any value at a position `j > index`. Additionally, this reordering is
|
||||
/// unstable (i.e. any number of equal elements may end up at position `index`), in-place
|
||||
/// (i.e. does not allocate), and `O(n)` worst-case. This function is also/ known as "kth
|
||||
/// element" in other libraries. It returns a triplet of the following values: all elements less
|
||||
/// than the one at the given index, the value at the given index, and all elements greater than
|
||||
/// the one at the given index.
|
||||
///
|
||||
/// # Current implementation
|
||||
///
|
||||
/// The current algorithm is based on the quickselect portion of the same quicksort algorithm
|
||||
/// used for [`sort_unstable`].
|
||||
///
|
||||
/// [`sort_unstable`]: #method.sort_unstable
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics when `index >= len()`, meaning it always panics on empty slices.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_partition_at_index)]
|
||||
///
|
||||
/// let mut v = [-5i32, 4, 1, -3, 2];
|
||||
///
|
||||
/// // Find the median
|
||||
/// v.partition_at_index(2);
|
||||
///
|
||||
/// // We are only guaranteed the slice will be one of the following, based on the way we sort
|
||||
/// // about the specified index.
|
||||
/// assert!(v == [-3, -5, 1, 2, 4] ||
|
||||
/// v == [-5, -3, 1, 2, 4] ||
|
||||
/// v == [-3, -5, 1, 4, 2] ||
|
||||
/// v == [-5, -3, 1, 4, 2]);
|
||||
/// ```
|
||||
#[unstable(feature = "slice_partition_at_index", issue = "55300")]
|
||||
#[inline]
|
||||
pub fn partition_at_index(&mut self, index: usize) -> (&mut [T], &mut T, &mut [T])
|
||||
where T: Ord
|
||||
{
|
||||
let mut f = |a: &T, b: &T| a.lt(b);
|
||||
sort::partition_at_index(self, index, &mut f)
|
||||
}
|
||||
|
||||
/// Reorder the slice with a comparator function such that the element at `index` is at its
|
||||
/// final sorted position.
|
||||
///
|
||||
/// This reordering has the additional property that any value at position `i < index` will be
|
||||
/// less than or equal to any value at a position `j > index` using the comparator function.
|
||||
/// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
|
||||
/// position `index`), in-place (i.e. does not allocate), and `O(n)` worst-case. This function
|
||||
/// is also known as "kth element" in other libraries. It returns a triplet of the following
|
||||
/// values: all elements less than the one at the given index, the value at the given index,
|
||||
/// and all elements greater than the one at the given index, using the provided comparator
|
||||
/// function.
|
||||
///
|
||||
/// # Current implementation
|
||||
///
|
||||
/// The current algorithm is based on the quickselect portion of the same quicksort algorithm
|
||||
/// used for [`sort_unstable`].
|
||||
///
|
||||
/// [`sort_unstable`]: #method.sort_unstable
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics when `index >= len()`, meaning it always panics on empty slices.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_partition_at_index)]
|
||||
///
|
||||
/// let mut v = [-5i32, 4, 1, -3, 2];
|
||||
///
|
||||
/// // Find the median as if the slice were sorted in descending order.
|
||||
/// v.partition_at_index_by(2, |a, b| b.cmp(a));
|
||||
///
|
||||
/// // We are only guaranteed the slice will be one of the following, based on the way we sort
|
||||
/// // about the specified index.
|
||||
/// assert!(v == [2, 4, 1, -5, -3] ||
|
||||
/// v == [2, 4, 1, -3, -5] ||
|
||||
/// v == [4, 2, 1, -5, -3] ||
|
||||
/// v == [4, 2, 1, -3, -5]);
|
||||
/// ```
|
||||
#[unstable(feature = "slice_partition_at_index", issue = "55300")]
|
||||
#[inline]
|
||||
pub fn partition_at_index_by<F>(&mut self, index: usize, mut compare: F)
|
||||
-> (&mut [T], &mut T, &mut [T])
|
||||
where F: FnMut(&T, &T) -> Ordering
|
||||
{
|
||||
let mut f = |a: &T, b: &T| compare(a, b) == Less;
|
||||
sort::partition_at_index(self, index, &mut f)
|
||||
}
|
||||
|
||||
/// Reorder the slice with a key extraction function such that the element at `index` is at its
|
||||
/// final sorted position.
|
||||
///
|
||||
/// This reordering has the additional property that any value at position `i < index` will be
|
||||
/// less than or equal to any value at a position `j > index` using the key extraction function.
|
||||
/// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
|
||||
/// position `index`), in-place (i.e. does not allocate), and `O(n)` worst-case. This function
|
||||
/// is also known as "kth element" in other libraries. It returns a triplet of the following
|
||||
/// values: all elements less than the one at the given index, the value at the given index, and
|
||||
/// all elements greater than the one at the given index, using the provided key extraction
|
||||
/// function.
|
||||
///
|
||||
/// # Current implementation
|
||||
///
|
||||
/// The current algorithm is based on the quickselect portion of the same quicksort algorithm
|
||||
/// used for [`sort_unstable`].
|
||||
///
|
||||
/// [`sort_unstable`]: #method.sort_unstable
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics when `index >= len()`, meaning it always panics on empty slices.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_partition_at_index)]
|
||||
///
|
||||
/// let mut v = [-5i32, 4, 1, -3, 2];
|
||||
///
|
||||
/// // Return the median as if the array were sorted according to absolute value.
|
||||
/// v.partition_at_index_by_key(2, |a| a.abs());
|
||||
///
|
||||
/// // We are only guaranteed the slice will be one of the following, based on the way we sort
|
||||
/// // about the specified index.
|
||||
/// assert!(v == [1, 2, -3, 4, -5] ||
|
||||
/// v == [1, 2, -3, -5, 4] ||
|
||||
/// v == [2, 1, -3, 4, -5] ||
|
||||
/// v == [2, 1, -3, -5, 4]);
|
||||
/// ```
|
||||
#[unstable(feature = "slice_partition_at_index", issue = "55300")]
|
||||
#[inline]
|
||||
pub fn partition_at_index_by_key<K, F>(&mut self, index: usize, mut f: F)
|
||||
-> (&mut [T], &mut T, &mut [T])
|
||||
where F: FnMut(&T) -> K, K: Ord
|
||||
{
|
||||
let mut g = |a: &T, b: &T| f(a).lt(&f(b));
|
||||
sort::partition_at_index(self, index, &mut g)
|
||||
}
|
||||
|
||||
/// Moves all consecutive repeated elements to the end of the slice according to the
|
||||
/// [`PartialEq`] trait implementation.
|
||||
///
|
||||
|
|
|
@ -691,3 +691,92 @@ pub fn quicksort<T, F>(v: &mut [T], mut is_less: F)
|
|||
|
||||
recurse(v, &mut is_less, None, limit);
|
||||
}
|
||||
|
||||
fn partition_at_index_loop<'a, T, F>( mut v: &'a mut [T], mut index: usize, is_less: &mut F
|
||||
, mut pred: Option<&'a T>) where F: FnMut(&T, &T) -> bool
|
||||
{
|
||||
loop {
|
||||
// For slices of up to this length it's probably faster to simply sort them.
|
||||
const MAX_INSERTION: usize = 10;
|
||||
if v.len() <= MAX_INSERTION {
|
||||
insertion_sort(v, is_less);
|
||||
return;
|
||||
}
|
||||
|
||||
// Choose a pivot
|
||||
let (pivot, _) = choose_pivot(v, is_less);
|
||||
|
||||
// If the chosen pivot is equal to the predecessor, then it's the smallest element in the
|
||||
// slice. Partition the slice into elements equal to and elements greater than the pivot.
|
||||
// This case is usually hit when the slice contains many duplicate elements.
|
||||
if let Some(p) = pred {
|
||||
if !is_less(p, &v[pivot]) {
|
||||
let mid = partition_equal(v, pivot, is_less);
|
||||
|
||||
// If we've passed our index, then we're good.
|
||||
if mid > index {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, continue sorting elements greater than the pivot.
|
||||
v = &mut v[mid..];
|
||||
index = index - mid;
|
||||
pred = None;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let (mid, _) = partition(v, pivot, is_less);
|
||||
|
||||
// Split the slice into `left`, `pivot`, and `right`.
|
||||
let (left, right) = {v}.split_at_mut(mid);
|
||||
let (pivot, right) = right.split_at_mut(1);
|
||||
let pivot = &pivot[0];
|
||||
|
||||
if mid < index {
|
||||
v = right;
|
||||
index = index - mid - 1;
|
||||
pred = Some(pivot);
|
||||
} else if mid > index {
|
||||
v = left;
|
||||
} else {
|
||||
// If mid == index, then we're done, since partition() guaranteed that all elements
|
||||
// after mid are greater than or equal to mid.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn partition_at_index<T, F>(v: &mut [T], index: usize, mut is_less: F)
|
||||
-> (&mut [T], &mut T, &mut [T]) where F: FnMut(&T, &T) -> bool
|
||||
{
|
||||
use cmp::Ordering::Less;
|
||||
use cmp::Ordering::Greater;
|
||||
|
||||
if index >= v.len() {
|
||||
panic!("partition_at_index index {} greater than length of slice {}", index, v.len());
|
||||
}
|
||||
|
||||
if mem::size_of::<T>() == 0 {
|
||||
// Sorting has no meaningful behavior on zero-sized types. Do nothing.
|
||||
} else if index == v.len() - 1 {
|
||||
// Find max element and place it in the last position of the array. We're free to use
|
||||
// `unwrap()` here because we know v must not be empty.
|
||||
let (max_index, _) = v.iter().enumerate().max_by(
|
||||
|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater }).unwrap();
|
||||
v.swap(max_index, index);
|
||||
} else if index == 0 {
|
||||
// Find min element and place it in the first position of the array. We're free to use
|
||||
// `unwrap()` here because we know v must not be empty.
|
||||
let (min_index, _) = v.iter().enumerate().min_by(
|
||||
|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater }).unwrap();
|
||||
v.swap(min_index, index);
|
||||
} else {
|
||||
partition_at_index_loop(v, index, &mut is_less, None);
|
||||
}
|
||||
|
||||
let (left, right) = v.split_at_mut(index);
|
||||
let (pivot, right) = right.split_at_mut(1);
|
||||
let pivot = &mut pivot[0];
|
||||
(left, pivot, right)
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#![feature(raw)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(sort_internals)]
|
||||
#![feature(slice_partition_at_index)]
|
||||
#![feature(specialization)]
|
||||
#![feature(step_trait)]
|
||||
#![feature(str_internals)]
|
||||
|
|
|
@ -1093,6 +1093,124 @@ fn sort_unstable() {
|
|||
assert!(v == [0xDEADBEEF]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[cfg(not(miri))] // Miri does not support entropy
|
||||
fn partition_at_index() {
|
||||
use core::cmp::Ordering::{Equal, Greater, Less};
|
||||
use rand::rngs::SmallRng;
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::{FromEntropy, Rng};
|
||||
|
||||
let mut rng = SmallRng::from_entropy();
|
||||
|
||||
for len in (2..21).chain(500..501) {
|
||||
let mut orig = vec![0; len];
|
||||
|
||||
for &modulus in &[5, 10, 1000] {
|
||||
for _ in 0..10 {
|
||||
for i in 0..len {
|
||||
orig[i] = rng.gen::<i32>() % modulus;
|
||||
}
|
||||
|
||||
let v_sorted = {
|
||||
let mut v = orig.clone();
|
||||
v.sort();
|
||||
v
|
||||
};
|
||||
|
||||
// Sort in default order.
|
||||
for pivot in 0..len {
|
||||
let mut v = orig.clone();
|
||||
v.partition_at_index(pivot);
|
||||
|
||||
assert_eq!(v_sorted[pivot], v[pivot]);
|
||||
for i in 0..pivot {
|
||||
for j in pivot..len {
|
||||
assert!(v[i] <= v[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort in ascending order.
|
||||
for pivot in 0..len {
|
||||
let mut v = orig.clone();
|
||||
let (left, pivot, right) = v.partition_at_index_by(pivot, |a, b| a.cmp(b));
|
||||
|
||||
assert_eq!(left.len() + right.len(), len - 1);
|
||||
|
||||
for l in left {
|
||||
assert!(l <= pivot);
|
||||
for r in right.iter_mut() {
|
||||
assert!(l <= r);
|
||||
assert!(pivot <= r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort in descending order.
|
||||
let sort_descending_comparator = |a: &i32, b: &i32| b.cmp(a);
|
||||
let v_sorted_descending = {
|
||||
let mut v = orig.clone();
|
||||
v.sort_by(sort_descending_comparator);
|
||||
v
|
||||
};
|
||||
|
||||
for pivot in 0..len {
|
||||
let mut v = orig.clone();
|
||||
v.partition_at_index_by(pivot, sort_descending_comparator);
|
||||
|
||||
assert_eq!(v_sorted_descending[pivot], v[pivot]);
|
||||
for i in 0..pivot {
|
||||
for j in pivot..len {
|
||||
assert!(v[j] <= v[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort at index using a completely random comparison function.
|
||||
// This will reorder the elements *somehow*, but won't panic.
|
||||
let mut v = [0; 500];
|
||||
for i in 0..v.len() {
|
||||
v[i] = i as i32;
|
||||
}
|
||||
|
||||
for pivot in 0..v.len() {
|
||||
v.partition_at_index_by(pivot, |_, _| *[Less, Equal, Greater].choose(&mut rng).unwrap());
|
||||
v.sort();
|
||||
for i in 0..v.len() {
|
||||
assert_eq!(v[i], i as i32);
|
||||
}
|
||||
}
|
||||
|
||||
// Should not panic.
|
||||
[(); 10].partition_at_index(0);
|
||||
[(); 10].partition_at_index(5);
|
||||
[(); 10].partition_at_index(9);
|
||||
[(); 100].partition_at_index(0);
|
||||
[(); 100].partition_at_index(50);
|
||||
[(); 100].partition_at_index(99);
|
||||
|
||||
let mut v = [0xDEADBEEFu64];
|
||||
v.partition_at_index(0);
|
||||
assert!(v == [0xDEADBEEF]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "index 0 greater than length of slice")]
|
||||
fn partition_at_index_zero_length() {
|
||||
[0i32; 0].partition_at_index(0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "index 20 greater than length of slice")]
|
||||
fn partition_at_index_past_length() {
|
||||
[0i32; 10].partition_at_index(20);
|
||||
}
|
||||
|
||||
pub mod memchr {
|
||||
use core::slice::memchr::{memchr, memrchr};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use crate::hir::def::{CtorKind, Namespace};
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::hir::{self, HirId, InlineAsm};
|
||||
use crate::hir::{self, HirId, InlineAsm as HirInlineAsm};
|
||||
use crate::mir::interpret::{ConstValue, InterpError, Scalar};
|
||||
use crate::mir::visit::MirVisitable;
|
||||
use rustc_apfloat::ieee::{Double, Single};
|
||||
|
@ -25,7 +25,7 @@ use std::slice;
|
|||
use std::vec::IntoIter;
|
||||
use std::{iter, mem, option, u32};
|
||||
use syntax::ast::{self, Name};
|
||||
use syntax::symbol::InternedString;
|
||||
use syntax::symbol::{InternedString, Symbol};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
use crate::ty::subst::{Subst, SubstsRef};
|
||||
|
@ -772,7 +772,7 @@ pub struct LocalDecl<'tcx> {
|
|||
/// e.g., via `let x: T`, then we carry that type here. The MIR
|
||||
/// borrow checker needs this information since it can affect
|
||||
/// region inference.
|
||||
pub user_ty: UserTypeProjections<'tcx>,
|
||||
pub user_ty: UserTypeProjections,
|
||||
|
||||
/// Name of the local, used in debuginfo and pretty-printing.
|
||||
///
|
||||
|
@ -1735,7 +1735,7 @@ pub struct Statement<'tcx> {
|
|||
|
||||
// `Statement` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
static_assert!(MEM_SIZE_OF_STATEMENT: mem::size_of::<Statement<'_>>() == 56);
|
||||
static_assert!(MEM_SIZE_OF_STATEMENT: mem::size_of::<Statement<'_>>() == 48);
|
||||
|
||||
impl<'tcx> Statement<'tcx> {
|
||||
/// Changes a statement to a nop. This is both faster than deleting instructions and avoids
|
||||
|
@ -1779,12 +1779,9 @@ pub enum StatementKind<'tcx> {
|
|||
/// End the current live range for the storage of the local.
|
||||
StorageDead(Local),
|
||||
|
||||
/// Executes a piece of inline Assembly.
|
||||
InlineAsm {
|
||||
asm: Box<InlineAsm>,
|
||||
outputs: Box<[Place<'tcx>]>,
|
||||
inputs: Box<[(Span, Operand<'tcx>)]>,
|
||||
},
|
||||
/// Executes a piece of inline Assembly. Stored in a Box to keep the size
|
||||
/// of `StatementKind` low.
|
||||
InlineAsm(Box<InlineAsm<'tcx>>),
|
||||
|
||||
/// Retag references in the given place, ensuring they got fresh tags. This is
|
||||
/// part of the Stacked Borrows model. These statements are currently only interpreted
|
||||
|
@ -1805,7 +1802,7 @@ pub enum StatementKind<'tcx> {
|
|||
/// - `Contravariant` -- requires that `T_y :> T`
|
||||
/// - `Invariant` -- requires that `T_y == T`
|
||||
/// - `Bivariant` -- no effect
|
||||
AscribeUserType(Place<'tcx>, ty::Variance, Box<UserTypeProjection<'tcx>>),
|
||||
AscribeUserType(Place<'tcx>, ty::Variance, Box<UserTypeProjection>),
|
||||
|
||||
/// No-op. Useful for deleting instructions without affecting statement indices.
|
||||
Nop,
|
||||
|
@ -1858,6 +1855,13 @@ pub enum FakeReadCause {
|
|||
ForLet,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub struct InlineAsm<'tcx> {
|
||||
pub asm: HirInlineAsm,
|
||||
pub outputs: Box<[Place<'tcx>]>,
|
||||
pub inputs: Box<[(Span, Operand<'tcx>)]>,
|
||||
}
|
||||
|
||||
impl<'tcx> Debug for Statement<'tcx> {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||
use self::StatementKind::*;
|
||||
|
@ -1880,11 +1884,8 @@ impl<'tcx> Debug for Statement<'tcx> {
|
|||
ref place,
|
||||
variant_index,
|
||||
} => write!(fmt, "discriminant({:?}) = {:?}", place, variant_index),
|
||||
InlineAsm {
|
||||
ref asm,
|
||||
ref outputs,
|
||||
ref inputs,
|
||||
} => write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs),
|
||||
InlineAsm(ref asm) =>
|
||||
write!(fmt, "asm!({:?} : {:?} : {:?})", asm.asm, asm.outputs, asm.inputs),
|
||||
AscribeUserType(ref place, ref variance, ref c_ty) => {
|
||||
write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty)
|
||||
}
|
||||
|
@ -1939,14 +1940,14 @@ impl_stable_hash_for!(struct Static<'tcx> {
|
|||
/// `PlaceProjection` etc below.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord,
|
||||
Hash, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub struct Projection<'tcx, B, V, T> {
|
||||
pub struct Projection<B, V, T> {
|
||||
pub base: B,
|
||||
pub elem: ProjectionElem<'tcx, V, T>,
|
||||
pub elem: ProjectionElem<V, T>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord,
|
||||
Hash, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub enum ProjectionElem<'tcx, V, T> {
|
||||
pub enum ProjectionElem<V, T> {
|
||||
Deref,
|
||||
Field(Field, T),
|
||||
Index(V),
|
||||
|
@ -1980,16 +1981,18 @@ pub enum ProjectionElem<'tcx, V, T> {
|
|||
/// "Downcast" to a variant of an ADT. Currently, we only introduce
|
||||
/// this for ADTs with more than one variant. It may be better to
|
||||
/// just introduce it always, or always for enums.
|
||||
Downcast(&'tcx AdtDef, VariantIdx),
|
||||
///
|
||||
/// The included Symbol is the name of the variant, used for printing MIR.
|
||||
Downcast(Option<Symbol>, VariantIdx),
|
||||
}
|
||||
|
||||
/// Alias for projections as they appear in places, where the base is a place
|
||||
/// and the index is a local.
|
||||
pub type PlaceProjection<'tcx> = Projection<'tcx, Place<'tcx>, Local, Ty<'tcx>>;
|
||||
pub type PlaceProjection<'tcx> = Projection<Place<'tcx>, Local, Ty<'tcx>>;
|
||||
|
||||
/// Alias for projections as they appear in places, where the base is a place
|
||||
/// and the index is a local.
|
||||
pub type PlaceElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;
|
||||
pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
|
||||
|
||||
// at least on 64 bit systems, `PlaceElem` should not be larger than two pointers
|
||||
static_assert!(PROJECTION_ELEM_IS_2_PTRS_LARGE:
|
||||
|
@ -1998,7 +2001,7 @@ static_assert!(PROJECTION_ELEM_IS_2_PTRS_LARGE:
|
|||
|
||||
/// Alias for projections as they appear in `UserTypeProjection`, where we
|
||||
/// need neither the `V` parameter for `Index` nor the `T` for `Field`.
|
||||
pub type ProjectionKind<'tcx> = ProjectionElem<'tcx, (), ()>;
|
||||
pub type ProjectionKind = ProjectionElem<(), ()>;
|
||||
|
||||
newtype_index! {
|
||||
pub struct Field {
|
||||
|
@ -2019,7 +2022,9 @@ impl<'tcx> Place<'tcx> {
|
|||
}
|
||||
|
||||
pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Place<'tcx> {
|
||||
self.elem(ProjectionElem::Downcast(adt_def, variant_index))
|
||||
self.elem(ProjectionElem::Downcast(
|
||||
Some(adt_def.variants[variant_index].ident.name),
|
||||
variant_index))
|
||||
}
|
||||
|
||||
pub fn index(self, index: Local) -> Place<'tcx> {
|
||||
|
@ -2080,8 +2085,11 @@ impl<'tcx> Debug for Place<'tcx> {
|
|||
)
|
||||
},
|
||||
Projection(ref data) => match data.elem {
|
||||
ProjectionElem::Downcast(ref adt_def, index) => {
|
||||
write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident)
|
||||
ProjectionElem::Downcast(Some(name), _index) => {
|
||||
write!(fmt, "({:?} as {})", data.base, name)
|
||||
}
|
||||
ProjectionElem::Downcast(None, index) => {
|
||||
write!(fmt, "({:?} as variant#{:?})", data.base, index)
|
||||
}
|
||||
ProjectionElem::Deref => write!(fmt, "(*{:?})", data.base),
|
||||
ProjectionElem::Field(field, ty) => {
|
||||
|
@ -2542,36 +2550,36 @@ pub struct Constant<'tcx> {
|
|||
/// inferred region `'1`). The second will lead to the constraint `w:
|
||||
/// &'static str`.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub struct UserTypeProjections<'tcx> {
|
||||
pub(crate) contents: Vec<(UserTypeProjection<'tcx>, Span)>,
|
||||
pub struct UserTypeProjections {
|
||||
pub(crate) contents: Vec<(UserTypeProjection, Span)>,
|
||||
}
|
||||
|
||||
BraceStructTypeFoldableImpl! {
|
||||
impl<'tcx> TypeFoldable<'tcx> for UserTypeProjections<'tcx> {
|
||||
impl<'tcx> TypeFoldable<'tcx> for UserTypeProjections {
|
||||
contents
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UserTypeProjections<'tcx> {
|
||||
impl<'tcx> UserTypeProjections {
|
||||
pub fn none() -> Self {
|
||||
UserTypeProjections { contents: vec![] }
|
||||
}
|
||||
|
||||
pub fn from_projections(projs: impl Iterator<Item=(UserTypeProjection<'tcx>, Span)>) -> Self {
|
||||
pub fn from_projections(projs: impl Iterator<Item=(UserTypeProjection, Span)>) -> Self {
|
||||
UserTypeProjections { contents: projs.collect() }
|
||||
}
|
||||
|
||||
pub fn projections_and_spans(&self) -> impl Iterator<Item=&(UserTypeProjection<'tcx>, Span)> {
|
||||
pub fn projections_and_spans(&self) -> impl Iterator<Item=&(UserTypeProjection, Span)> {
|
||||
self.contents.iter()
|
||||
}
|
||||
|
||||
pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection<'tcx>> {
|
||||
pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection> {
|
||||
self.contents.iter().map(|&(ref user_type, _span)| user_type)
|
||||
}
|
||||
|
||||
pub fn push_projection(
|
||||
mut self,
|
||||
user_ty: &UserTypeProjection<'tcx>,
|
||||
user_ty: &UserTypeProjection,
|
||||
span: Span,
|
||||
) -> Self {
|
||||
self.contents.push((user_ty.clone(), span));
|
||||
|
@ -2580,7 +2588,7 @@ impl<'tcx> UserTypeProjections<'tcx> {
|
|||
|
||||
fn map_projections(
|
||||
mut self,
|
||||
mut f: impl FnMut(UserTypeProjection<'tcx>) -> UserTypeProjection<'tcx>
|
||||
mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection
|
||||
) -> Self {
|
||||
self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect();
|
||||
self
|
||||
|
@ -2628,14 +2636,14 @@ impl<'tcx> UserTypeProjections<'tcx> {
|
|||
/// `field[0]` (aka `.0`), indicating that the type of `s` is
|
||||
/// determined by finding the type of the `.0` field from `T`.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub struct UserTypeProjection<'tcx> {
|
||||
pub struct UserTypeProjection {
|
||||
pub base: UserTypeAnnotationIndex,
|
||||
pub projs: Vec<ProjectionElem<'tcx, (), ()>>,
|
||||
pub projs: Vec<ProjectionElem<(), ()>>,
|
||||
}
|
||||
|
||||
impl<'tcx> Copy for ProjectionKind<'tcx> { }
|
||||
impl Copy for ProjectionKind { }
|
||||
|
||||
impl<'tcx> UserTypeProjection<'tcx> {
|
||||
impl UserTypeProjection {
|
||||
pub(crate) fn index(mut self) -> Self {
|
||||
self.projs.push(ProjectionElem::Index(()));
|
||||
self
|
||||
|
@ -2662,15 +2670,17 @@ impl<'tcx> UserTypeProjection<'tcx> {
|
|||
variant_index: VariantIdx,
|
||||
field: Field,
|
||||
) -> Self {
|
||||
self.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
|
||||
self.projs.push(ProjectionElem::Downcast(
|
||||
Some(adt_def.variants[variant_index].ident.name),
|
||||
variant_index));
|
||||
self.projs.push(ProjectionElem::Field(field, ()));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
CloneTypeFoldableAndLiftImpls! { ProjectionKind<'tcx>, }
|
||||
CloneTypeFoldableAndLiftImpls! { ProjectionKind, }
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection<'tcx> {
|
||||
impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
use crate::mir::ProjectionElem::*;
|
||||
|
||||
|
@ -3140,13 +3150,21 @@ EnumTypeFoldableImpl! {
|
|||
(StatementKind::SetDiscriminant) { place, variant_index },
|
||||
(StatementKind::StorageLive)(a),
|
||||
(StatementKind::StorageDead)(a),
|
||||
(StatementKind::InlineAsm) { asm, outputs, inputs },
|
||||
(StatementKind::InlineAsm)(a),
|
||||
(StatementKind::Retag)(kind, place),
|
||||
(StatementKind::AscribeUserType)(a, v, b),
|
||||
(StatementKind::Nop),
|
||||
}
|
||||
}
|
||||
|
||||
BraceStructTypeFoldableImpl! {
|
||||
impl<'tcx> TypeFoldable<'tcx> for InlineAsm<'tcx> {
|
||||
asm,
|
||||
outputs,
|
||||
inputs,
|
||||
}
|
||||
}
|
||||
|
||||
EnumTypeFoldableImpl! {
|
||||
impl<'tcx, T> TypeFoldable<'tcx> for ClearCrossCrate<T> {
|
||||
(ClearCrossCrate::Clear),
|
||||
|
@ -3428,7 +3446,7 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<'tcx, B, V, T>
|
||||
impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<B, V, T>
|
||||
where
|
||||
B: TypeFoldable<'tcx>,
|
||||
V: TypeFoldable<'tcx>,
|
||||
|
|
|
@ -4,21 +4,17 @@
|
|||
*/
|
||||
|
||||
use crate::mir::*;
|
||||
use crate::ty::subst::{Subst, SubstsRef};
|
||||
use crate::ty::{self, AdtDef, Ty, TyCtxt};
|
||||
use crate::ty::subst::Subst;
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use crate::ty::layout::VariantIdx;
|
||||
use crate::hir;
|
||||
use crate::ty::util::IntTypeExt;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum PlaceTy<'tcx> {
|
||||
/// Normal type.
|
||||
Ty { ty: Ty<'tcx> },
|
||||
|
||||
/// Downcast to a particular variant of an enum.
|
||||
Downcast { adt_def: &'tcx AdtDef,
|
||||
substs: SubstsRef<'tcx>,
|
||||
variant_index: VariantIdx },
|
||||
pub struct PlaceTy<'tcx> {
|
||||
pub ty: Ty<'tcx>,
|
||||
/// Downcast to a particular variant of an enum, if included.
|
||||
pub variant_index: Option<VariantIdx>,
|
||||
}
|
||||
|
||||
static_assert!(PLACE_TY_IS_3_PTRS_LARGE:
|
||||
|
@ -27,16 +23,7 @@ static_assert!(PLACE_TY_IS_3_PTRS_LARGE:
|
|||
|
||||
impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
|
||||
pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> {
|
||||
PlaceTy::Ty { ty }
|
||||
}
|
||||
|
||||
pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
|
||||
match *self {
|
||||
PlaceTy::Ty { ty } =>
|
||||
ty,
|
||||
PlaceTy::Downcast { adt_def, substs, variant_index: _ } =>
|
||||
tcx.mk_adt(adt_def, substs),
|
||||
}
|
||||
PlaceTy { ty, variant_index: None }
|
||||
}
|
||||
|
||||
/// `place_ty.field_ty(tcx, f)` computes the type at a given field
|
||||
|
@ -48,21 +35,20 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
|
|||
/// Note that the resulting type has not been normalized.
|
||||
pub fn field_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, f: &Field) -> Ty<'tcx>
|
||||
{
|
||||
// Pass `0` here so it can be used as a "default" variant_index in first arm below
|
||||
let answer = match (self, VariantIdx::new(0)) {
|
||||
(PlaceTy::Ty {
|
||||
ty: &ty::TyS { sty: ty::TyKind::Adt(adt_def, substs), .. } }, variant_index) |
|
||||
(PlaceTy::Downcast { adt_def, substs, variant_index }, _) => {
|
||||
let variant_def = &adt_def.variants[variant_index];
|
||||
let answer = match self.ty.sty {
|
||||
ty::TyKind::Adt(adt_def, substs) => {
|
||||
let variant_def = match self.variant_index {
|
||||
None => adt_def.non_enum_variant(),
|
||||
Some(variant_index) => {
|
||||
assert!(adt_def.is_enum());
|
||||
&adt_def.variants[variant_index]
|
||||
}
|
||||
};
|
||||
let field_def = &variant_def.fields[f.index()];
|
||||
field_def.ty(tcx, substs)
|
||||
}
|
||||
(PlaceTy::Ty { ty }, _) => {
|
||||
match ty.sty {
|
||||
ty::Tuple(ref tys) => tys[f.index()],
|
||||
_ => bug!("extracting field of non-tuple non-adt: {:?}", self),
|
||||
}
|
||||
}
|
||||
ty::Tuple(ref tys) => tys[f.index()],
|
||||
_ => bug!("extracting field of non-tuple non-adt: {:?}", self),
|
||||
};
|
||||
debug!("field_ty self: {:?} f: {:?} yields: {:?}", self, f, answer);
|
||||
answer
|
||||
|
@ -86,7 +72,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
|
|||
pub fn projection_ty_core<V, T>(
|
||||
self,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
elem: &ProjectionElem<'tcx, V, T>,
|
||||
elem: &ProjectionElem<V, T>,
|
||||
mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>)
|
||||
-> PlaceTy<'tcx>
|
||||
where
|
||||
|
@ -94,62 +80,43 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
|
|||
{
|
||||
let answer = match *elem {
|
||||
ProjectionElem::Deref => {
|
||||
let ty = self.to_ty(tcx)
|
||||
let ty = self.ty
|
||||
.builtin_deref(true)
|
||||
.unwrap_or_else(|| {
|
||||
bug!("deref projection of non-dereferencable ty {:?}", self)
|
||||
})
|
||||
.ty;
|
||||
PlaceTy::Ty {
|
||||
ty,
|
||||
}
|
||||
PlaceTy::from_ty(ty)
|
||||
}
|
||||
ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
|
||||
PlaceTy::Ty {
|
||||
ty: self.to_ty(tcx).builtin_index().unwrap()
|
||||
},
|
||||
PlaceTy::from_ty(self.ty.builtin_index().unwrap()),
|
||||
ProjectionElem::Subslice { from, to } => {
|
||||
let ty = self.to_ty(tcx);
|
||||
PlaceTy::Ty {
|
||||
ty: match ty.sty {
|
||||
ty::Array(inner, size) => {
|
||||
let size = size.unwrap_usize(tcx);
|
||||
let len = size - (from as u64) - (to as u64);
|
||||
tcx.mk_array(inner, len)
|
||||
}
|
||||
ty::Slice(..) => ty,
|
||||
_ => {
|
||||
bug!("cannot subslice non-array type: `{:?}`", self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ProjectionElem::Downcast(adt_def1, index) =>
|
||||
match self.to_ty(tcx).sty {
|
||||
ty::Adt(adt_def, substs) => {
|
||||
assert!(adt_def.is_enum());
|
||||
assert!(index.as_usize() < adt_def.variants.len());
|
||||
assert_eq!(adt_def, adt_def1);
|
||||
PlaceTy::Downcast { adt_def,
|
||||
substs,
|
||||
variant_index: index }
|
||||
PlaceTy::from_ty(match self.ty.sty {
|
||||
ty::Array(inner, size) => {
|
||||
let size = size.unwrap_usize(tcx);
|
||||
let len = size - (from as u64) - (to as u64);
|
||||
tcx.mk_array(inner, len)
|
||||
}
|
||||
ty::Slice(..) => self.ty,
|
||||
_ => {
|
||||
bug!("cannot downcast non-ADT type: `{:?}`", self)
|
||||
bug!("cannot subslice non-array type: `{:?}`", self)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
ProjectionElem::Downcast(_name, index) =>
|
||||
PlaceTy { ty: self.ty, variant_index: Some(index) },
|
||||
ProjectionElem::Field(ref f, ref fty) =>
|
||||
PlaceTy::Ty { ty: handle_field(&self, f, fty) },
|
||||
PlaceTy::from_ty(handle_field(&self, f, fty)),
|
||||
};
|
||||
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
|
||||
answer
|
||||
}
|
||||
}
|
||||
|
||||
EnumTypeFoldableImpl! {
|
||||
BraceStructTypeFoldableImpl! {
|
||||
impl<'tcx> TypeFoldable<'tcx> for PlaceTy<'tcx> {
|
||||
(PlaceTy::Ty) { ty },
|
||||
(PlaceTy::Downcast) { adt_def, substs, variant_index },
|
||||
ty,
|
||||
variant_index,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,9 +126,9 @@ impl<'tcx> Place<'tcx> {
|
|||
{
|
||||
match *self {
|
||||
Place::Base(PlaceBase::Local(index)) =>
|
||||
PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
|
||||
PlaceTy::from_ty(local_decls.local_decls()[index].ty),
|
||||
Place::Base(PlaceBase::Static(ref data)) =>
|
||||
PlaceTy::Ty { ty: data.ty },
|
||||
PlaceTy::from_ty(data.ty),
|
||||
Place::Projection(ref proj) =>
|
||||
proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
|
||||
}
|
||||
|
@ -186,7 +153,7 @@ impl<'tcx> Place<'tcx> {
|
|||
match place {
|
||||
Place::Projection(ref proj) => match proj.elem {
|
||||
ProjectionElem::Field(field, _ty) => {
|
||||
let base_ty = proj.base.ty(mir, *tcx).to_ty(*tcx);
|
||||
let base_ty = proj.base.ty(mir, *tcx).ty;
|
||||
|
||||
if (base_ty.is_closure() || base_ty.is_generator()) &&
|
||||
(!by_ref || mir.upvar_decls[field.index()].by_ref)
|
||||
|
@ -218,7 +185,7 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
tcx.mk_array(operand.ty(local_decls, tcx), count)
|
||||
}
|
||||
Rvalue::Ref(reg, bk, ref place) => {
|
||||
let place_ty = place.ty(local_decls, tcx).to_ty(tcx);
|
||||
let place_ty = place.ty(local_decls, tcx).ty;
|
||||
tcx.mk_ref(reg,
|
||||
ty::TypeAndMut {
|
||||
ty: place_ty,
|
||||
|
@ -244,7 +211,7 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
operand.ty(local_decls, tcx)
|
||||
}
|
||||
Rvalue::Discriminant(ref place) => {
|
||||
let ty = place.ty(local_decls, tcx).to_ty(tcx);
|
||||
let ty = place.ty(local_decls, tcx).ty;
|
||||
if let ty::Adt(adt_def, _) = ty.sty {
|
||||
adt_def.repr.discr_type().to_ty(tcx)
|
||||
} else {
|
||||
|
@ -293,7 +260,7 @@ impl<'tcx> Operand<'tcx> {
|
|||
{
|
||||
match self {
|
||||
&Operand::Copy(ref l) |
|
||||
&Operand::Move(ref l) => l.ty(local_decls, tcx).to_ty(tcx),
|
||||
&Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
|
||||
&Operand::Constant(ref c) => c.ty,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ macro_rules! make_mir_visitor {
|
|||
fn visit_ascribe_user_ty(&mut self,
|
||||
place: & $($mutability)? Place<'tcx>,
|
||||
variance: & $($mutability)? ty::Variance,
|
||||
user_ty: & $($mutability)? UserTypeProjection<'tcx>,
|
||||
user_ty: & $($mutability)? UserTypeProjection,
|
||||
location: Location) {
|
||||
self.super_ascribe_user_ty(place, variance, user_ty, location);
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ macro_rules! make_mir_visitor {
|
|||
|
||||
fn visit_user_type_projection(
|
||||
&mut self,
|
||||
ty: & $($mutability)? UserTypeProjection<'tcx>,
|
||||
ty: & $($mutability)? UserTypeProjection,
|
||||
) {
|
||||
self.super_user_type_projection(ty);
|
||||
}
|
||||
|
@ -391,15 +391,15 @@ macro_rules! make_mir_visitor {
|
|||
location
|
||||
);
|
||||
}
|
||||
StatementKind::InlineAsm { outputs, inputs, asm: _ } => {
|
||||
for output in & $($mutability)? outputs[..] {
|
||||
StatementKind::InlineAsm(asm) => {
|
||||
for output in & $($mutability)? asm.outputs[..] {
|
||||
self.visit_place(
|
||||
output,
|
||||
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
|
||||
location
|
||||
);
|
||||
}
|
||||
for (span, input) in & $($mutability)? inputs[..] {
|
||||
for (span, input) in & $($mutability)? asm.inputs[..] {
|
||||
self.visit_span(span);
|
||||
self.visit_operand(input, location);
|
||||
}
|
||||
|
@ -700,7 +700,7 @@ macro_rules! make_mir_visitor {
|
|||
fn super_ascribe_user_ty(&mut self,
|
||||
place: & $($mutability)? Place<'tcx>,
|
||||
_variance: & $($mutability)? ty::Variance,
|
||||
user_ty: & $($mutability)? UserTypeProjection<'tcx>,
|
||||
user_ty: & $($mutability)? UserTypeProjection,
|
||||
location: Location) {
|
||||
self.visit_place(
|
||||
place,
|
||||
|
@ -777,7 +777,7 @@ macro_rules! make_mir_visitor {
|
|||
min_length: _,
|
||||
from_end: _ } => {
|
||||
}
|
||||
ProjectionElem::Downcast(_adt_def, _variant_index) => {
|
||||
ProjectionElem::Downcast(_name, _variant_index) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -851,7 +851,7 @@ macro_rules! make_mir_visitor {
|
|||
|
||||
fn super_user_type_projection(
|
||||
&mut self,
|
||||
_ty: & $($mutability)? UserTypeProjection<'tcx>,
|
||||
_ty: & $($mutability)? UserTypeProjection,
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ pub struct CtxtInterners<'tcx> {
|
|||
clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
|
||||
goal: InternedSet<'tcx, GoalKind<'tcx>>,
|
||||
goal_list: InternedSet<'tcx, List<Goal<'tcx>>>,
|
||||
projs: InternedSet<'tcx, List<ProjectionKind<'tcx>>>,
|
||||
projs: InternedSet<'tcx, List<ProjectionKind>>,
|
||||
const_: InternedSet<'tcx, Const<'tcx>>,
|
||||
}
|
||||
|
||||
|
@ -1802,7 +1802,7 @@ nop_list_lift!{Ty<'a> => Ty<'tcx>}
|
|||
nop_list_lift!{ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
|
||||
nop_list_lift!{Predicate<'a> => Predicate<'tcx>}
|
||||
nop_list_lift!{CanonicalVarInfo => CanonicalVarInfo}
|
||||
nop_list_lift!{ProjectionKind<'a> => ProjectionKind<'tcx>}
|
||||
nop_list_lift!{ProjectionKind => ProjectionKind}
|
||||
|
||||
// this is the impl for `&'a InternalSubsts<'a>`
|
||||
nop_list_lift!{Kind<'a> => Kind<'tcx>}
|
||||
|
@ -2261,9 +2261,9 @@ impl<'tcx: 'lcx, 'lcx> Borrow<[Kind<'lcx>]> for Interned<'tcx, InternalSubsts<'t
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx: 'lcx, 'lcx> Borrow<[ProjectionKind<'lcx>]>
|
||||
for Interned<'tcx, List<ProjectionKind<'tcx>>> {
|
||||
fn borrow<'a>(&'a self) -> &'a [ProjectionKind<'lcx>] {
|
||||
impl<'tcx> Borrow<[ProjectionKind]>
|
||||
for Interned<'tcx, List<ProjectionKind>> {
|
||||
fn borrow<'a>(&'a self) -> &'a [ProjectionKind] {
|
||||
&self.0[..]
|
||||
}
|
||||
}
|
||||
|
@ -2391,22 +2391,22 @@ direct_interners!('tcx,
|
|||
);
|
||||
|
||||
macro_rules! slice_interners {
|
||||
($($field:ident: $method:ident($ty:ident)),+) => (
|
||||
($($field:ident: $method:ident($ty:ty)),+) => (
|
||||
$(intern_method!( 'tcx, $field: $method(
|
||||
&[$ty<'tcx>],
|
||||
&[$ty],
|
||||
|a, v| List::from_arena(a, v),
|
||||
Deref::deref,
|
||||
|xs: &[$ty<'_>]| xs.iter().any(keep_local)) -> List<$ty<'tcx>>);)+
|
||||
)
|
||||
|xs: &[$ty]| xs.iter().any(keep_local)) -> List<$ty>);)+
|
||||
);
|
||||
}
|
||||
|
||||
slice_interners!(
|
||||
existential_predicates: _intern_existential_predicates(ExistentialPredicate),
|
||||
predicates: _intern_predicates(Predicate),
|
||||
type_list: _intern_type_list(Ty),
|
||||
substs: _intern_substs(Kind),
|
||||
clauses: _intern_clauses(Clause),
|
||||
goal_list: _intern_goals(Goal),
|
||||
existential_predicates: _intern_existential_predicates(ExistentialPredicate<'tcx>),
|
||||
predicates: _intern_predicates(Predicate<'tcx>),
|
||||
type_list: _intern_type_list(Ty<'tcx>),
|
||||
substs: _intern_substs(Kind<'tcx>),
|
||||
clauses: _intern_clauses(Clause<'tcx>),
|
||||
goal_list: _intern_goals(Goal<'tcx>),
|
||||
projs: _intern_projs(ProjectionKind)
|
||||
);
|
||||
|
||||
|
@ -2774,7 +2774,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn intern_projs(self, ps: &[ProjectionKind<'tcx>]) -> &'tcx List<ProjectionKind<'tcx>> {
|
||||
pub fn intern_projs(self, ps: &[ProjectionKind]) -> &'tcx List<ProjectionKind> {
|
||||
if ps.len() == 0 {
|
||||
List::empty()
|
||||
} else {
|
||||
|
|
|
@ -936,7 +936,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind<'tcx>> {
|
||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let v = self.iter().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
|
||||
folder.tcx().intern_projs(&v)
|
||||
|
|
|
@ -172,14 +172,14 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
|
|||
// ZSTs don't require any actual memory access.
|
||||
let elem_ty = base_ty
|
||||
.projection_ty(cx.tcx(), &proj.elem)
|
||||
.to_ty(cx.tcx());
|
||||
.ty;
|
||||
let elem_ty = self.fx.monomorphize(&elem_ty);
|
||||
if cx.layout_of(elem_ty).is_zst() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let mir::ProjectionElem::Field(..) = proj.elem {
|
||||
let layout = cx.layout_of(base_ty.to_ty(cx.tcx()));
|
||||
let layout = cx.layout_of(base_ty.ty);
|
||||
if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
|
||||
// Recurse with the same context, instead of `Projection`,
|
||||
// potentially stopping at non-operand projections,
|
||||
|
@ -247,7 +247,7 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
|
|||
PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
|
||||
let ty = mir::Place::Base(mir::PlaceBase::Local(local)).ty(self.fx.mir,
|
||||
self.fx.cx.tcx());
|
||||
let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx()));
|
||||
let ty = self.fx.monomorphize(&ty.ty);
|
||||
|
||||
// Only need the place if we're actually dropping it.
|
||||
if self.fx.cx.type_needs_drop(ty) {
|
||||
|
|
|
@ -301,7 +301,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
target: mir::BasicBlock,
|
||||
unwind: Option<mir::BasicBlock>,
|
||||
) {
|
||||
let ty = location.ty(self.mir, bx.tcx()).to_ty(bx.tcx());
|
||||
let ty = location.ty(self.mir, bx.tcx()).ty;
|
||||
let ty = self.monomorphize(&ty);
|
||||
let drop_fn = monomorphize::resolve_drop_in_place(bx.tcx(), ty);
|
||||
|
||||
|
|
|
@ -494,8 +494,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
mir::ProjectionElem::Subslice { from, to } => {
|
||||
let mut subslice = cg_base.project_index(bx,
|
||||
bx.cx().const_usize(from as u64));
|
||||
let projected_ty = PlaceTy::Ty { ty: cg_base.layout.ty }
|
||||
.projection_ty(tcx, &projection.elem).to_ty(tcx);
|
||||
let projected_ty = PlaceTy::from_ty(cg_base.layout.ty)
|
||||
.projection_ty(tcx, &projection.elem).ty;
|
||||
subslice.layout = bx.cx().layout_of(self.monomorphize(&projected_ty));
|
||||
|
||||
if subslice.layout.is_unsized() {
|
||||
|
@ -523,6 +523,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
pub fn monomorphized_place_ty(&self, place: &mir::Place<'tcx>) -> Ty<'tcx> {
|
||||
let tcx = self.cx.tcx();
|
||||
let place_ty = place.ty(self.mir, tcx);
|
||||
self.monomorphize(&place_ty.to_ty(tcx))
|
||||
self.monomorphize(&place_ty.ty)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,13 +68,13 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
bx
|
||||
}
|
||||
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
|
||||
let outputs = outputs.iter().map(|output| {
|
||||
mir::StatementKind::InlineAsm(ref asm) => {
|
||||
let outputs = asm.outputs.iter().map(|output| {
|
||||
self.codegen_place(&mut bx, output)
|
||||
}).collect();
|
||||
|
||||
let input_vals = inputs.iter()
|
||||
.fold(Vec::with_capacity(inputs.len()), |mut acc, (span, input)| {
|
||||
let input_vals = asm.inputs.iter()
|
||||
.fold(Vec::with_capacity(asm.inputs.len()), |mut acc, (span, input)| {
|
||||
let op = self.codegen_operand(&mut bx, input);
|
||||
if let OperandValue::Immediate(_) = op.val {
|
||||
acc.push(op.immediate());
|
||||
|
@ -85,8 +85,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
acc
|
||||
});
|
||||
|
||||
if input_vals.len() == inputs.len() {
|
||||
let res = bx.codegen_inline_asm(asm, outputs, input_vals);
|
||||
if input_vals.len() == asm.inputs.len() {
|
||||
let res = bx.codegen_inline_asm(&asm.asm, outputs, input_vals);
|
||||
if !res {
|
||||
span_err!(bx.sess(), statement.source_info.span, E0668,
|
||||
"malformed inline assembly");
|
||||
|
|
|
@ -13,6 +13,7 @@ use rustc::mir::{
|
|||
Static, StaticKind, TerminatorKind, VarBindingForm,
|
||||
};
|
||||
use rustc::ty::{self, DefIdTree};
|
||||
use rustc::ty::layout::VariantIdx;
|
||||
use rustc::ty::print::Print;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
|
@ -201,7 +202,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
let ty = used_place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
|
||||
let ty = used_place.ty(self.mir, self.infcx.tcx).ty;
|
||||
let needs_note = match ty.sty {
|
||||
ty::Closure(id, _) => {
|
||||
let tables = self.infcx.tcx.typeck_tables_of(id);
|
||||
|
@ -216,7 +217,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
let mpi = self.move_data.moves[move_out_indices[0]].path;
|
||||
let place = &self.move_data.move_paths[mpi].place;
|
||||
|
||||
let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
|
||||
let ty = place.ty(self.mir, self.infcx.tcx).ty;
|
||||
let opt_name = self.describe_place_with_options(place, IncludingDowncast(true));
|
||||
let note_msg = match opt_name {
|
||||
Some(ref name) => format!("`{}`", name),
|
||||
|
@ -596,8 +597,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
// Define a small closure that we can use to check if the type of a place
|
||||
// is a union.
|
||||
let is_union = |place: &Place<'tcx>| -> bool {
|
||||
place.ty(self.mir, self.infcx.tcx)
|
||||
.to_ty(self.infcx.tcx)
|
||||
place.ty(self.mir, self.infcx.tcx).ty
|
||||
.ty_adt_def()
|
||||
.map(|adt| adt.is_union())
|
||||
.unwrap_or(false)
|
||||
|
@ -646,7 +646,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
|
||||
// Also compute the name of the union type, eg. `Foo` so we
|
||||
// can add a helpful note with it.
|
||||
let ty = base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
|
||||
let ty = base.ty(self.mir, self.infcx.tcx).ty;
|
||||
|
||||
return Some((desc_base, desc_first, desc_second, ty.to_string()));
|
||||
},
|
||||
|
@ -1761,20 +1761,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
/// End-user visible description of the `field`nth field of `base`
|
||||
fn describe_field(&self, base: &Place<'_>, field: Field) -> String {
|
||||
fn describe_field(&self, base: &Place<'tcx>, field: Field) -> String {
|
||||
match *base {
|
||||
Place::Base(PlaceBase::Local(local)) => {
|
||||
let local = &self.mir.local_decls[local];
|
||||
self.describe_field_from_ty(&local.ty, field)
|
||||
self.describe_field_from_ty(&local.ty, field, None)
|
||||
}
|
||||
Place::Base(PlaceBase::Static(ref static_)) =>
|
||||
self.describe_field_from_ty(&static_.ty, field),
|
||||
self.describe_field_from_ty(&static_.ty, field, None),
|
||||
Place::Projection(ref proj) => match proj.elem {
|
||||
ProjectionElem::Deref => self.describe_field(&proj.base, field),
|
||||
ProjectionElem::Downcast(def, variant_index) =>
|
||||
def.variants[variant_index].fields[field.index()].ident.to_string(),
|
||||
ProjectionElem::Downcast(_, variant_index) => {
|
||||
let base_ty = base.ty(self.mir, self.infcx.tcx).ty;
|
||||
self.describe_field_from_ty(&base_ty, field, Some(variant_index))
|
||||
}
|
||||
ProjectionElem::Field(_, field_type) => {
|
||||
self.describe_field_from_ty(&field_type, field)
|
||||
self.describe_field_from_ty(&field_type, field, None)
|
||||
}
|
||||
ProjectionElem::Index(..)
|
||||
| ProjectionElem::ConstantIndex { .. }
|
||||
|
@ -1786,24 +1788,34 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
/// End-user visible description of the `field_index`nth field of `ty`
|
||||
fn describe_field_from_ty(&self, ty: &ty::Ty<'_>, field: Field) -> String {
|
||||
fn describe_field_from_ty(
|
||||
&self,
|
||||
ty: &ty::Ty<'_>,
|
||||
field: Field,
|
||||
variant_index: Option<VariantIdx>
|
||||
) -> String {
|
||||
if ty.is_box() {
|
||||
// If the type is a box, the field is described from the boxed type
|
||||
self.describe_field_from_ty(&ty.boxed_ty(), field)
|
||||
self.describe_field_from_ty(&ty.boxed_ty(), field, variant_index)
|
||||
} else {
|
||||
match ty.sty {
|
||||
ty::Adt(def, _) => if def.is_enum() {
|
||||
field.index().to_string()
|
||||
} else {
|
||||
def.non_enum_variant().fields[field.index()]
|
||||
ty::Adt(def, _) => {
|
||||
let variant = if let Some(idx) = variant_index {
|
||||
assert!(def.is_enum());
|
||||
&def.variants[idx]
|
||||
} else {
|
||||
def.non_enum_variant()
|
||||
};
|
||||
variant.fields[field.index()]
|
||||
.ident
|
||||
.to_string()
|
||||
},
|
||||
ty::Tuple(_) => field.index().to_string(),
|
||||
ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
|
||||
self.describe_field_from_ty(&ty, field)
|
||||
self.describe_field_from_ty(&ty, field, variant_index)
|
||||
}
|
||||
ty::Array(ty, _) | ty::Slice(ty) => self.describe_field_from_ty(&ty, field),
|
||||
ty::Array(ty, _) | ty::Slice(ty) =>
|
||||
self.describe_field_from_ty(&ty, field, variant_index),
|
||||
ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
|
||||
// Convert the def-id into a node-id. node-ids are only valid for
|
||||
// the local code in the current crate, so this returns an `Option` in case
|
||||
|
@ -1861,7 +1873,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
StorageDeadOrDrop::LocalStorageDead
|
||||
| StorageDeadOrDrop::BoxedStorageDead => {
|
||||
assert!(
|
||||
base.ty(self.mir, tcx).to_ty(tcx).is_box(),
|
||||
base.ty(self.mir, tcx).ty.is_box(),
|
||||
"Drop of value behind a reference or raw pointer"
|
||||
);
|
||||
StorageDeadOrDrop::BoxedStorageDead
|
||||
|
@ -1869,7 +1881,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
StorageDeadOrDrop::Destructor(_) => base_access,
|
||||
},
|
||||
ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
|
||||
let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
|
||||
let base_ty = base.ty(self.mir, tcx).ty;
|
||||
match base_ty.sty {
|
||||
ty::Adt(def, _) if def.has_dtor(tcx) => {
|
||||
// Report the outermost adt with a destructor
|
||||
|
|
|
@ -525,16 +525,12 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
|||
flow_state,
|
||||
);
|
||||
}
|
||||
StatementKind::InlineAsm {
|
||||
ref asm,
|
||||
ref outputs,
|
||||
ref inputs,
|
||||
} => {
|
||||
StatementKind::InlineAsm(ref asm) => {
|
||||
let context = ContextKind::InlineAsm.new(location);
|
||||
for (o, output) in asm.outputs.iter().zip(outputs.iter()) {
|
||||
for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) {
|
||||
if o.is_indirect {
|
||||
// FIXME(eddyb) indirect inline asm outputs should
|
||||
// be encoeded through MIR place derefs instead.
|
||||
// be encoded through MIR place derefs instead.
|
||||
self.access_place(
|
||||
context,
|
||||
(output, o.span),
|
||||
|
@ -558,7 +554,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
|||
);
|
||||
}
|
||||
}
|
||||
for (_, input) in inputs.iter() {
|
||||
for (_, input) in asm.inputs.iter() {
|
||||
self.consume_operand(context, (input, span), flow_state);
|
||||
}
|
||||
}
|
||||
|
@ -616,8 +612,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
|||
let drop_place_ty = drop_place.ty(self.mir, self.infcx.tcx);
|
||||
|
||||
// Erase the regions.
|
||||
let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty)
|
||||
.to_ty(self.infcx.tcx);
|
||||
let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty).ty;
|
||||
|
||||
// "Lift" into the gcx -- once regions are erased, this type should be in the
|
||||
// global arenas; this "lift" operation basically just asserts that is true, but
|
||||
|
@ -1641,7 +1636,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
// assigning to `P.f` requires `P` itself
|
||||
// be already initialized
|
||||
let tcx = self.infcx.tcx;
|
||||
match base.ty(self.mir, tcx).to_ty(tcx).sty {
|
||||
match base.ty(self.mir, tcx).ty.sty {
|
||||
ty::Adt(def, _) if def.has_dtor(tcx) => {
|
||||
self.check_if_path_or_subpath_is_moved(
|
||||
context, InitializationRequiringAction::Assignment,
|
||||
|
@ -1746,7 +1741,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
// no move out from an earlier location) then this is an attempt at initialization
|
||||
// of the union - we should error in that case.
|
||||
let tcx = this.infcx.tcx;
|
||||
if let ty::TyKind::Adt(def, _) = base.ty(this.mir, tcx).to_ty(tcx).sty {
|
||||
if let ty::TyKind::Adt(def, _) = base.ty(this.mir, tcx).ty.sty {
|
||||
if def.is_union() {
|
||||
if this.move_data.path_map[mpi].iter().any(|moi| {
|
||||
this.move_data.moves[*moi].source.is_predecessor_of(
|
||||
|
@ -2007,7 +2002,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
Place::Projection(ref proj) => {
|
||||
match proj.elem {
|
||||
ProjectionElem::Deref => {
|
||||
let base_ty = proj.base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
|
||||
let base_ty = proj.base.ty(self.mir, self.infcx.tcx).ty;
|
||||
|
||||
// Check the kind of deref to decide
|
||||
match base_ty.sty {
|
||||
|
|
|
@ -266,7 +266,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
// Inspect the type of the content behind the
|
||||
// borrow to provide feedback about why this
|
||||
// was a move rather than a copy.
|
||||
let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
|
||||
let ty = place.ty(self.mir, self.infcx.tcx).ty;
|
||||
let is_upvar_field_projection =
|
||||
self.prefixes(&original_path, PrefixSet::All)
|
||||
.any(|p| p.is_upvar_field_projection(self.mir, &self.infcx.tcx)
|
||||
|
@ -530,7 +530,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
// We're only interested in assignments (in particular, where the
|
||||
// assignment came from - was it an `Rc` or `Arc`?).
|
||||
if let StatementKind::Assign(_, box Rvalue::Ref(_, _, source)) = &stmt.kind {
|
||||
let ty = source.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
|
||||
let ty = source.ty(self.mir, self.infcx.tcx).ty;
|
||||
let ty = match ty.sty {
|
||||
ty::TyKind::Ref(_, ty, _) => ty,
|
||||
_ => ty,
|
||||
|
@ -555,7 +555,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
_ => continue,
|
||||
};
|
||||
|
||||
let ty = source.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
|
||||
let ty = source.ty(self.mir, self.infcx.tcx).ty;
|
||||
let ty = match ty.sty {
|
||||
ty::TyKind::Ref(_, ty, _) => ty,
|
||||
_ => ty,
|
||||
|
@ -581,7 +581,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
base,
|
||||
elem: ProjectionElem::Deref,
|
||||
}) = place {
|
||||
if base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx).is_unsafe_ptr() {
|
||||
if base.ty(self.mir, self.infcx.tcx).ty.is_unsafe_ptr() {
|
||||
return BorrowedContentSource::DerefRawPointer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
elem: ProjectionElem::Field(upvar_index, _),
|
||||
}) => {
|
||||
debug_assert!(is_closure_or_generator(
|
||||
base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx)
|
||||
base.ty(self.mir, self.infcx.tcx).ty
|
||||
));
|
||||
|
||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||
|
@ -85,7 +85,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||
debug_assert!(self.mir.local_decls[Local::new(1)].ty.is_region_ptr());
|
||||
debug_assert!(is_closure_or_generator(
|
||||
the_place_err.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx)
|
||||
the_place_err.ty(self.mir, self.infcx.tcx).ty
|
||||
));
|
||||
|
||||
reason = if access_place.is_upvar_field_projection(self.mir,
|
||||
|
@ -110,7 +110,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
reason = ", as it is immutable for the pattern guard".to_string();
|
||||
} else {
|
||||
let pointer_type =
|
||||
if base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx).is_region_ptr() {
|
||||
if base.ty(self.mir, self.infcx.tcx).ty.is_region_ptr() {
|
||||
"`&` reference"
|
||||
} else {
|
||||
"`*const` pointer"
|
||||
|
@ -232,7 +232,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
if let Some((span, message)) = annotate_struct_field(
|
||||
self.infcx.tcx,
|
||||
base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx),
|
||||
base.ty(self.mir, self.infcx.tcx).ty,
|
||||
field,
|
||||
) {
|
||||
err.span_suggestion(
|
||||
|
@ -304,7 +304,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
elem: ProjectionElem::Field(upvar_index, _),
|
||||
}) => {
|
||||
debug_assert!(is_closure_or_generator(
|
||||
base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx)
|
||||
base.ty(self.mir, self.infcx.tcx).ty
|
||||
));
|
||||
|
||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||
|
|
|
@ -174,7 +174,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
|
|||
&mut self,
|
||||
_place: &Place<'tcx>,
|
||||
_variance: &ty::Variance,
|
||||
_user_ty: &UserTypeProjection<'tcx>,
|
||||
_user_ty: &UserTypeProjection,
|
||||
_location: Location,
|
||||
) {
|
||||
}
|
||||
|
|
|
@ -92,16 +92,12 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
|||
JustWrite,
|
||||
);
|
||||
}
|
||||
StatementKind::InlineAsm {
|
||||
ref asm,
|
||||
ref outputs,
|
||||
ref inputs,
|
||||
} => {
|
||||
StatementKind::InlineAsm(ref asm) => {
|
||||
let context = ContextKind::InlineAsm.new(location);
|
||||
for (o, output) in asm.outputs.iter().zip(outputs.iter()) {
|
||||
for (o, output) in asm.asm.outputs.iter().zip(asm.outputs.iter()) {
|
||||
if o.is_indirect {
|
||||
// FIXME(eddyb) indirect inline asm outputs should
|
||||
// be encoeded through MIR place derefs instead.
|
||||
// be encoded through MIR place derefs instead.
|
||||
self.access_place(
|
||||
context,
|
||||
output,
|
||||
|
@ -117,7 +113,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
|
|||
);
|
||||
}
|
||||
}
|
||||
for (_, input) in inputs.iter() {
|
||||
for (_, input) in asm.inputs.iter() {
|
||||
self.consume_operand(context, input);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -450,9 +450,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
|||
) -> PlaceTy<'tcx> {
|
||||
debug!("sanitize_place: {:?}", place);
|
||||
let place_ty = match place {
|
||||
Place::Base(PlaceBase::Local(index)) => PlaceTy::Ty {
|
||||
ty: self.mir.local_decls[*index].ty,
|
||||
},
|
||||
Place::Base(PlaceBase::Local(index)) =>
|
||||
PlaceTy::from_ty(self.mir.local_decls[*index].ty),
|
||||
Place::Base(PlaceBase::Static(box Static { kind, ty: sty })) => {
|
||||
let sty = self.sanitize_type(place, sty);
|
||||
let check_err =
|
||||
|
@ -493,7 +492,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
|||
check_err(self, place, ty, sty);
|
||||
}
|
||||
}
|
||||
PlaceTy::Ty { ty: sty }
|
||||
PlaceTy::from_ty(sty)
|
||||
}
|
||||
Place::Projection(ref proj) => {
|
||||
let base_context = if context.is_mutating_use() {
|
||||
|
@ -502,12 +501,10 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
|||
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
|
||||
};
|
||||
let base_ty = self.sanitize_place(&proj.base, location, base_context);
|
||||
if let PlaceTy::Ty { ty } = base_ty {
|
||||
if ty.references_error() {
|
||||
if base_ty.variant_index.is_none() {
|
||||
if base_ty.ty.references_error() {
|
||||
assert!(self.errors_reported);
|
||||
return PlaceTy::Ty {
|
||||
ty: self.tcx().types.err,
|
||||
};
|
||||
return PlaceTy::from_ty(self.tcx().types.err);
|
||||
}
|
||||
}
|
||||
self.sanitize_projection(base_ty, &proj.elem, place, location)
|
||||
|
@ -517,7 +514,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
|||
let tcx = self.tcx();
|
||||
let trait_ref = ty::TraitRef {
|
||||
def_id: tcx.lang_items().copy_trait().unwrap(),
|
||||
substs: tcx.mk_substs_trait(place_ty.to_ty(tcx), &[]),
|
||||
substs: tcx.mk_substs_trait(place_ty.ty, &[]),
|
||||
};
|
||||
|
||||
// In order to have a Copy operand, the type T of the
|
||||
|
@ -615,40 +612,40 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
|||
) -> PlaceTy<'tcx> {
|
||||
debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, place);
|
||||
let tcx = self.tcx();
|
||||
let base_ty = base.to_ty(tcx);
|
||||
let base_ty = base.ty;
|
||||
match *pi {
|
||||
ProjectionElem::Deref => {
|
||||
let deref_ty = base_ty.builtin_deref(true);
|
||||
PlaceTy::Ty {
|
||||
ty: deref_ty.map(|t| t.ty).unwrap_or_else(|| {
|
||||
PlaceTy::from_ty(
|
||||
deref_ty.map(|t| t.ty).unwrap_or_else(|| {
|
||||
span_mirbug_and_err!(self, place, "deref of non-pointer {:?}", base_ty)
|
||||
}),
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
ProjectionElem::Index(i) => {
|
||||
let index_ty = Place::Base(PlaceBase::Local(i)).ty(self.mir, tcx).to_ty(tcx);
|
||||
let index_ty = Place::Base(PlaceBase::Local(i)).ty(self.mir, tcx).ty;
|
||||
if index_ty != tcx.types.usize {
|
||||
PlaceTy::Ty {
|
||||
ty: span_mirbug_and_err!(self, i, "index by non-usize {:?}", i),
|
||||
}
|
||||
PlaceTy::from_ty(
|
||||
span_mirbug_and_err!(self, i, "index by non-usize {:?}", i),
|
||||
)
|
||||
} else {
|
||||
PlaceTy::Ty {
|
||||
ty: base_ty.builtin_index().unwrap_or_else(|| {
|
||||
PlaceTy::from_ty(
|
||||
base_ty.builtin_index().unwrap_or_else(|| {
|
||||
span_mirbug_and_err!(self, place, "index of non-array {:?}", base_ty)
|
||||
}),
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
ProjectionElem::ConstantIndex { .. } => {
|
||||
// consider verifying in-bounds
|
||||
PlaceTy::Ty {
|
||||
ty: base_ty.builtin_index().unwrap_or_else(|| {
|
||||
PlaceTy::from_ty(
|
||||
base_ty.builtin_index().unwrap_or_else(|| {
|
||||
span_mirbug_and_err!(self, place, "index of non-array {:?}", base_ty)
|
||||
}),
|
||||
}
|
||||
)
|
||||
}
|
||||
ProjectionElem::Subslice { from, to } => PlaceTy::Ty {
|
||||
ty: match base_ty.sty {
|
||||
ProjectionElem::Subslice { from, to } => PlaceTy::from_ty(
|
||||
match base_ty.sty {
|
||||
ty::Array(inner, size) => {
|
||||
let size = size.unwrap_usize(tcx);
|
||||
let min_size = (from as u64) + (to as u64);
|
||||
|
@ -666,35 +663,39 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
|||
ty::Slice(..) => base_ty,
|
||||
_ => span_mirbug_and_err!(self, place, "slice of non-array {:?}", base_ty),
|
||||
},
|
||||
},
|
||||
ProjectionElem::Downcast(adt_def1, index) => match base_ty.sty {
|
||||
ty::Adt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => {
|
||||
),
|
||||
ProjectionElem::Downcast(maybe_name, index) => match base_ty.sty {
|
||||
ty::Adt(adt_def, _substs) if adt_def.is_enum() => {
|
||||
if index.as_usize() >= adt_def.variants.len() {
|
||||
PlaceTy::Ty {
|
||||
ty: span_mirbug_and_err!(
|
||||
PlaceTy::from_ty(
|
||||
span_mirbug_and_err!(
|
||||
self,
|
||||
place,
|
||||
"cast to variant #{:?} but enum only has {:?}",
|
||||
index,
|
||||
adt_def.variants.len()
|
||||
),
|
||||
}
|
||||
)
|
||||
} else {
|
||||
PlaceTy::Downcast {
|
||||
adt_def,
|
||||
substs,
|
||||
variant_index: index,
|
||||
PlaceTy {
|
||||
ty: base_ty,
|
||||
variant_index: Some(index),
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => PlaceTy::Ty {
|
||||
ty: span_mirbug_and_err!(
|
||||
self,
|
||||
place,
|
||||
"can't downcast {:?} as {:?}",
|
||||
base_ty,
|
||||
adt_def1
|
||||
),
|
||||
_ => {
|
||||
let ty = if let Some(name) = maybe_name {
|
||||
span_mirbug_and_err!(
|
||||
self,
|
||||
place,
|
||||
"can't downcast {:?} as {:?}",
|
||||
base_ty,
|
||||
name
|
||||
)
|
||||
} else {
|
||||
span_mirbug_and_err!(self, place, "can't downcast {:?}", base_ty)
|
||||
};
|
||||
PlaceTy::from_ty(ty)
|
||||
},
|
||||
},
|
||||
ProjectionElem::Field(field, fty) => {
|
||||
|
@ -723,7 +724,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
|||
field_count
|
||||
),
|
||||
}
|
||||
PlaceTy::Ty { ty: fty }
|
||||
PlaceTy::from_ty(fty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -743,12 +744,13 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
|||
let tcx = self.tcx();
|
||||
|
||||
let (variant, substs) = match base_ty {
|
||||
PlaceTy::Downcast {
|
||||
adt_def,
|
||||
substs,
|
||||
variant_index,
|
||||
} => (&adt_def.variants[variant_index], substs),
|
||||
PlaceTy::Ty { ty } => match ty.sty {
|
||||
PlaceTy { ty, variant_index: Some(variant_index) } => {
|
||||
match ty.sty {
|
||||
ty::TyKind::Adt(adt_def, substs) => (&adt_def.variants[variant_index], substs),
|
||||
_ => bug!("can't have downcast of non-adt type"),
|
||||
}
|
||||
}
|
||||
PlaceTy { ty, variant_index: None } => match ty.sty {
|
||||
ty::Adt(adt_def, substs) if !adt_def.is_enum() =>
|
||||
(&adt_def.variants[VariantIdx::new(0)], substs),
|
||||
ty::Closure(def_id, substs) => {
|
||||
|
@ -1161,7 +1163,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
&mut self,
|
||||
a: Ty<'tcx>,
|
||||
v: ty::Variance,
|
||||
user_ty: &UserTypeProjection<'tcx>,
|
||||
user_ty: &UserTypeProjection,
|
||||
locations: Locations,
|
||||
category: ConstraintCategory,
|
||||
) -> Fallible<()> {
|
||||
|
@ -1185,7 +1187,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
debug!("user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
|
||||
user_ty.base, annotated_type, user_ty.projs, curr_projected_ty);
|
||||
|
||||
let ty = curr_projected_ty.to_ty(tcx);
|
||||
let ty = curr_projected_ty.ty;
|
||||
self.relate_types(a, v, ty, locations, category)?;
|
||||
|
||||
Ok(())
|
||||
|
@ -1333,7 +1335,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
_ => ConstraintCategory::Assignment,
|
||||
};
|
||||
|
||||
let place_ty = place.ty(mir, tcx).to_ty(tcx);
|
||||
let place_ty = place.ty(mir, tcx).ty;
|
||||
let rv_ty = rv.ty(mir, tcx);
|
||||
if let Err(terr) =
|
||||
self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category)
|
||||
|
@ -1385,7 +1387,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
ref place,
|
||||
variant_index,
|
||||
} => {
|
||||
let place_type = place.ty(mir, tcx).to_ty(tcx);
|
||||
let place_type = place.ty(mir, tcx).ty;
|
||||
let adt = match place_type.sty {
|
||||
TyKind::Adt(adt, _) if adt.is_enum() => adt,
|
||||
_ => {
|
||||
|
@ -1407,7 +1409,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
};
|
||||
}
|
||||
StatementKind::AscribeUserType(ref place, variance, box ref projection) => {
|
||||
let place_ty = place.ty(mir, tcx).to_ty(tcx);
|
||||
let place_ty = place.ty(mir, tcx).ty;
|
||||
if let Err(terr) = self.relate_type_and_user_type(
|
||||
place_ty,
|
||||
variance,
|
||||
|
@ -1463,7 +1465,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
target: _,
|
||||
unwind: _,
|
||||
} => {
|
||||
let place_ty = location.ty(mir, tcx).to_ty(tcx);
|
||||
let place_ty = location.ty(mir, tcx).ty;
|
||||
let rv_ty = value.ty(mir, tcx);
|
||||
|
||||
let locations = term_location.to_locations();
|
||||
|
@ -1611,7 +1613,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
let tcx = self.tcx();
|
||||
match *destination {
|
||||
Some((ref dest, _target_block)) => {
|
||||
let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
|
||||
let dest_ty = dest.ty(mir, tcx).ty;
|
||||
let category = match *dest {
|
||||
Place::Base(PlaceBase::Local(RETURN_PLACE)) => {
|
||||
if let Some(BorrowCheckContext {
|
||||
|
@ -2370,7 +2372,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
match *elem {
|
||||
ProjectionElem::Deref => {
|
||||
let tcx = self.infcx.tcx;
|
||||
let base_ty = base.ty(mir, tcx).to_ty(tcx);
|
||||
let base_ty = base.ty(mir, tcx).ty;
|
||||
|
||||
debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
|
||||
match base_ty.sty {
|
||||
|
|
|
@ -63,7 +63,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
|
|||
tcx, mir, locals_state_at_exit),
|
||||
|
||||
ProjectionElem::Deref => {
|
||||
let ty = proj.base.ty(mir, tcx).to_ty(tcx);
|
||||
let ty = proj.base.ty(mir, tcx).ty;
|
||||
match ty.sty {
|
||||
// For both derefs of raw pointers and `&T`
|
||||
// references, the original path is `Copy` and
|
||||
|
|
|
@ -191,7 +191,7 @@ fn place_components_conflict<'gcx, 'tcx>(
|
|||
Place::Projection(box Projection { base, elem }) => (base, elem),
|
||||
_ => bug!("place has no base?"),
|
||||
};
|
||||
let base_ty = base.ty(mir, tcx).to_ty(tcx);
|
||||
let base_ty = base.ty(mir, tcx).ty;
|
||||
|
||||
match (elem, &base_ty.sty, access) {
|
||||
(_, _, Shallow(Some(ArtificialField::ArrayLength)))
|
||||
|
@ -427,7 +427,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
|
|||
debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD");
|
||||
Overlap::EqualOrDisjoint
|
||||
} else {
|
||||
let ty = pi1.base.ty(mir, tcx).to_ty(tcx);
|
||||
let ty = pi1.base.ty(mir, tcx).ty;
|
||||
match ty.sty {
|
||||
ty::Adt(def, _) if def.is_union() => {
|
||||
// Different fields of a union, we are basically stuck.
|
||||
|
|
|
@ -139,7 +139,7 @@ impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> {
|
|||
// derefs, except we stop at the deref of a shared
|
||||
// reference.
|
||||
|
||||
let ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
|
||||
let ty = proj.base.ty(self.mir, self.tcx).ty;
|
||||
match ty.sty {
|
||||
ty::RawPtr(_) |
|
||||
ty::Ref(
|
||||
|
|
|
@ -163,7 +163,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
// Then, the block may have an optional trailing expression which is a “return” value
|
||||
// of the block, which is stored into `destination`.
|
||||
let tcx = this.hir.tcx();
|
||||
let destination_ty = destination.ty(&this.local_decls, tcx).to_ty(tcx);
|
||||
let destination_ty = destination.ty(&this.local_decls, tcx).ty;
|
||||
if let Some(expr) = expr {
|
||||
let tail_result_is_ignored = destination_ty.is_unit() ||
|
||||
this.block_context.currently_ignores_tail_results();
|
||||
|
|
|
@ -188,11 +188,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
block,
|
||||
Statement {
|
||||
source_info,
|
||||
kind: StatementKind::InlineAsm {
|
||||
asm: box asm.clone(),
|
||||
kind: StatementKind::InlineAsm(box InlineAsm {
|
||||
asm: asm.clone(),
|
||||
outputs,
|
||||
inputs,
|
||||
},
|
||||
}),
|
||||
},
|
||||
);
|
||||
this.block_context.pop();
|
||||
|
|
|
@ -374,7 +374,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
let ty_source_info = self.source_info(user_ty_span);
|
||||
let user_ty = box pat_ascription_ty.user_ty(
|
||||
&mut self.canonical_user_type_annotations,
|
||||
place.ty(&self.local_decls, self.hir.tcx()).to_ty(self.hir.tcx()),
|
||||
place.ty(&self.local_decls, self.hir.tcx()).ty,
|
||||
ty_source_info.span,
|
||||
);
|
||||
self.cfg.push(
|
||||
|
@ -575,7 +575,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
pub(super) fn visit_bindings(
|
||||
&mut self,
|
||||
pattern: &Pattern<'tcx>,
|
||||
pattern_user_ty: UserTypeProjections<'tcx>,
|
||||
pattern_user_ty: UserTypeProjections,
|
||||
f: &mut impl FnMut(
|
||||
&mut Self,
|
||||
Mutability,
|
||||
|
@ -584,7 +584,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
HirId,
|
||||
Span,
|
||||
Ty<'tcx>,
|
||||
UserTypeProjections<'tcx>,
|
||||
UserTypeProjections,
|
||||
),
|
||||
) {
|
||||
debug!("visit_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty);
|
||||
|
@ -1293,7 +1293,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
debug!("add_fake_borrows all_fake_borrows = {:?}", all_fake_borrows);
|
||||
|
||||
all_fake_borrows.into_iter().map(|matched_place| {
|
||||
let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).to_ty(tcx);
|
||||
let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).ty;
|
||||
let fake_borrow_ty = tcx.mk_imm_ref(tcx.types.re_erased, fake_borrow_deref_ty);
|
||||
let fake_borrow_temp = self.local_decls.push(
|
||||
LocalDecl::new_temp(fake_borrow_ty, temp_span)
|
||||
|
@ -1587,7 +1587,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
|
||||
let user_ty = box ascription.user_ty.clone().user_ty(
|
||||
&mut self.canonical_user_type_annotations,
|
||||
ascription.source.ty(&self.local_decls, self.hir.tcx()).to_ty(self.hir.tcx()),
|
||||
ascription.source.ty(&self.local_decls, self.hir.tcx()).ty,
|
||||
source_info.span
|
||||
);
|
||||
self.cfg.push(
|
||||
|
@ -1701,7 +1701,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
mode: BindingMode,
|
||||
var_id: HirId,
|
||||
var_ty: Ty<'tcx>,
|
||||
user_ty: UserTypeProjections<'tcx>,
|
||||
user_ty: UserTypeProjections,
|
||||
has_guard: ArmHasGuard,
|
||||
opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
|
||||
pat_span: Span,
|
||||
|
|
|
@ -693,7 +693,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
// So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`,
|
||||
// we want to create a set of derived match-patterns like
|
||||
// `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
|
||||
let elem = ProjectionElem::Downcast(adt_def, variant_index);
|
||||
let elem = ProjectionElem::Downcast(
|
||||
Some(adt_def.variants[variant_index].ident.name), variant_index);
|
||||
let downcast_place = match_pair.place.elem(elem); // `(x as Variant)`
|
||||
let consequent_match_pairs =
|
||||
subpatterns.iter()
|
||||
|
|
|
@ -70,7 +70,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
|
||||
pub fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
|
||||
let tcx = self.hir.tcx();
|
||||
let ty = place.ty(&self.local_decls, tcx).to_ty(tcx);
|
||||
let ty = place.ty(&self.local_decls, tcx).ty;
|
||||
if !self.hir.type_is_copy_modulo_regions(ty, DUMMY_SP) {
|
||||
Operand::Move(place)
|
||||
} else {
|
||||
|
|
|
@ -49,7 +49,7 @@ pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>,
|
|||
fn place_contents_drop_state_cannot_differ<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
place: &mir::Place<'tcx>) -> bool {
|
||||
let ty = place.ty(mir, tcx).to_ty(tcx);
|
||||
let ty = place.ty(mir, tcx).ty;
|
||||
match ty.sty {
|
||||
ty::Array(..) => {
|
||||
debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false",
|
||||
|
@ -141,7 +141,7 @@ pub(crate) fn on_all_drop_children_bits<'a, 'gcx, 'tcx, F>(
|
|||
{
|
||||
on_all_children_bits(tcx, mir, &ctxt.move_data, path, |child| {
|
||||
let place = &ctxt.move_data.move_paths[path].place;
|
||||
let ty = place.ty(mir, tcx).to_ty(tcx);
|
||||
let ty = place.ty(mir, tcx).ty;
|
||||
debug!("on_all_drop_children_bits({:?}, {:?} : {:?})", path, place, ty);
|
||||
|
||||
let gcx = tcx.global_tcx();
|
||||
|
|
|
@ -288,8 +288,8 @@ impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'gcx, 'tcx> {
|
|||
self.kill_borrows_on_place(sets, &Place::Base(PlaceBase::Local(local)));
|
||||
}
|
||||
|
||||
mir::StatementKind::InlineAsm { ref outputs, ref asm, .. } => {
|
||||
for (output, kind) in outputs.iter().zip(&asm.outputs) {
|
||||
mir::StatementKind::InlineAsm(ref asm) => {
|
||||
for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) {
|
||||
if !kind.is_indirect && !kind.is_rw {
|
||||
self.kill_borrows_on_place(sets, output);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,7 @@ use rustc::ty::Ty;
|
|||
pub struct AbstractOperand;
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct AbstractType;
|
||||
pub type AbstractElem<'tcx> =
|
||||
ProjectionElem<'tcx, AbstractOperand, AbstractType>;
|
||||
pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType>;
|
||||
|
||||
pub trait Lift {
|
||||
type Abstract;
|
||||
|
@ -38,7 +37,7 @@ impl<'tcx> Lift for Ty<'tcx> {
|
|||
fn lift(&self) -> Self::Abstract { AbstractType }
|
||||
}
|
||||
impl<'tcx> Lift for PlaceElem<'tcx> {
|
||||
type Abstract = AbstractElem<'tcx>;
|
||||
type Abstract = AbstractElem;
|
||||
fn lift(&self) -> Self::Abstract {
|
||||
match *self {
|
||||
ProjectionElem::Deref =>
|
||||
|
@ -56,7 +55,7 @@ impl<'tcx> Lift for PlaceElem<'tcx> {
|
|||
from_end,
|
||||
},
|
||||
ProjectionElem::Downcast(a, u) =>
|
||||
ProjectionElem::Downcast(a.clone(), u.clone()),
|
||||
ProjectionElem::Downcast(a, u.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
|||
let base = self.move_path_for(&proj.base)?;
|
||||
let mir = self.builder.mir;
|
||||
let tcx = self.builder.tcx;
|
||||
let place_ty = proj.base.ty(mir, tcx).to_ty(tcx);
|
||||
let place_ty = proj.base.ty(mir, tcx).ty;
|
||||
match place_ty.sty {
|
||||
ty::Ref(..) | ty::RawPtr(..) =>
|
||||
return Err(MoveError::cannot_move_out_of(
|
||||
|
@ -272,13 +272,13 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
|||
StatementKind::FakeRead(_, ref place) => {
|
||||
self.create_move_path(place);
|
||||
}
|
||||
StatementKind::InlineAsm { ref outputs, ref inputs, ref asm } => {
|
||||
for (output, kind) in outputs.iter().zip(&asm.outputs) {
|
||||
StatementKind::InlineAsm(ref asm) => {
|
||||
for (output, kind) in asm.outputs.iter().zip(&asm.asm.outputs) {
|
||||
if !kind.is_indirect {
|
||||
self.gather_init(output, InitKind::Deep);
|
||||
}
|
||||
}
|
||||
for (_, input) in inputs.iter() {
|
||||
for (_, input) in asm.inputs.iter() {
|
||||
self.gather_operand(input);
|
||||
}
|
||||
}
|
||||
|
@ -424,7 +424,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
|||
Place::Projection(box Projection {
|
||||
base,
|
||||
elem: ProjectionElem::Field(_, _),
|
||||
}) if match base.ty(self.builder.mir, self.builder.tcx).to_ty(self.builder.tcx).sty {
|
||||
}) if match base.ty(self.builder.mir, self.builder.tcx).ty.sty {
|
||||
ty::TyKind::Adt(def, _) if def.is_union() => true,
|
||||
_ => false,
|
||||
} => base,
|
||||
|
|
|
@ -148,7 +148,7 @@ pub struct MoveData<'tcx> {
|
|||
/// particular path being moved.)
|
||||
pub loc_map: LocationMap<SmallVec<[MoveOutIndex; 4]>>,
|
||||
pub path_map: IndexVec<MovePathIndex, SmallVec<[MoveOutIndex; 4]>>,
|
||||
pub rev_lookup: MovePathLookup<'tcx>,
|
||||
pub rev_lookup: MovePathLookup,
|
||||
pub inits: IndexVec<InitIndex, Init>,
|
||||
/// Each Location `l` is mapped to the Inits that are effects
|
||||
/// of executing the code at `l`.
|
||||
|
@ -258,7 +258,7 @@ impl Init {
|
|||
|
||||
/// Tables mapping from a place to its MovePathIndex.
|
||||
#[derive(Debug)]
|
||||
pub struct MovePathLookup<'tcx> {
|
||||
pub struct MovePathLookup {
|
||||
locals: IndexVec<Local, MovePathIndex>,
|
||||
|
||||
/// projections are made from a base-place and a projection
|
||||
|
@ -267,7 +267,7 @@ pub struct MovePathLookup<'tcx> {
|
|||
/// subsequent search so that it is solely relative to that
|
||||
/// base-place). For the remaining lookup, we map the projection
|
||||
/// elem to the associated MovePathIndex.
|
||||
projections: FxHashMap<(MovePathIndex, AbstractElem<'tcx>), MovePathIndex>
|
||||
projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex>
|
||||
}
|
||||
|
||||
mod builder;
|
||||
|
@ -278,7 +278,7 @@ pub enum LookupResult {
|
|||
Parent(Option<MovePathIndex>)
|
||||
}
|
||||
|
||||
impl<'tcx> MovePathLookup<'tcx> {
|
||||
impl MovePathLookup {
|
||||
// Unlike the builder `fn move_path_for` below, this lookup
|
||||
// alternative will *not* create a MovePath on the fly for an
|
||||
// unknown place, but will rather return the nearest available
|
||||
|
|
|
@ -74,7 +74,7 @@ impl<'tcx> PatternTypeProjection<'tcx> {
|
|||
annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
|
||||
inferred_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> UserTypeProjection<'tcx> {
|
||||
) -> UserTypeProjection {
|
||||
UserTypeProjection {
|
||||
base: annotations.push(CanonicalUserTypeAnnotation {
|
||||
span,
|
||||
|
@ -1094,7 +1094,7 @@ CloneImpls!{ <'tcx>
|
|||
Span, Field, Mutability, ast::Name, hir::HirId, usize, ty::Const<'tcx>,
|
||||
Region<'tcx>, Ty<'tcx>, BindingMode, &'tcx AdtDef,
|
||||
SubstsRef<'tcx>, &'tcx Kind<'tcx>, UserType<'tcx>,
|
||||
UserTypeProjection<'tcx>, PatternTypeProjection<'tcx>
|
||||
UserTypeProjection, PatternTypeProjection<'tcx>
|
||||
}
|
||||
|
||||
impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> {
|
||||
|
|
|
@ -558,7 +558,7 @@ where
|
|||
pub fn place_projection(
|
||||
&mut self,
|
||||
base: PlaceTy<'tcx, M::PointerTag>,
|
||||
proj_elem: &mir::ProjectionElem<'tcx, mir::Local, Ty<'tcx>>,
|
||||
proj_elem: &mir::ProjectionElem<mir::Local, Ty<'tcx>>,
|
||||
) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
|
||||
use rustc::mir::ProjectionElem::*;
|
||||
Ok(match *proj_elem {
|
||||
|
|
|
@ -625,8 +625,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
|||
}
|
||||
mir::TerminatorKind::Drop { ref location, .. } |
|
||||
mir::TerminatorKind::DropAndReplace { ref location, .. } => {
|
||||
let ty = location.ty(self.mir, self.tcx)
|
||||
.to_ty(self.tcx);
|
||||
let ty = location.ty(self.mir, self.tcx).ty;
|
||||
let ty = tcx.subst_and_normalize_erasing_regions(
|
||||
self.param_substs,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
|
|
|
@ -106,7 +106,7 @@ fn add_move_for_packed_drop<'a, 'tcx>(
|
|||
};
|
||||
|
||||
let source_info = terminator.source_info;
|
||||
let ty = location.ty(mir, tcx).to_ty(tcx);
|
||||
let ty = location.ty(mir, tcx).ty;
|
||||
let temp = patch.new_temp(ty, terminator.source_info.span);
|
||||
|
||||
let storage_dead_block = patch.new_block(BasicBlockData {
|
||||
|
|
|
@ -87,7 +87,7 @@ impl MirPass for AddRetag {
|
|||
let needs_retag = |place: &Place<'tcx>| {
|
||||
// FIXME: Instead of giving up for unstable places, we should introduce
|
||||
// a temporary and retag on that.
|
||||
is_stable(place) && may_have_reference(place.ty(&*local_decls, tcx).to_ty(tcx), tcx)
|
||||
is_stable(place) && may_have_reference(place.ty(&*local_decls, tcx).ty, tcx)
|
||||
};
|
||||
|
||||
// PART 1
|
||||
|
|
|
@ -227,7 +227,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
|||
}
|
||||
let is_borrow_of_interior_mut = context.is_borrow() && !base
|
||||
.ty(self.mir, self.tcx)
|
||||
.to_ty(self.tcx)
|
||||
.ty
|
||||
.is_freeze(self.tcx, self.param_env, self.source_info.span);
|
||||
// prevent
|
||||
// * `&mut x.field`
|
||||
|
@ -249,7 +249,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
|||
self.source_info = self.mir.local_decls[local].source_info;
|
||||
}
|
||||
}
|
||||
let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx);
|
||||
let base_ty = base.ty(self.mir, self.tcx).ty;
|
||||
match base_ty.sty {
|
||||
ty::RawPtr(..) => {
|
||||
self.require_unsafe("dereference of raw pointer",
|
||||
|
@ -420,7 +420,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
|
|||
}) = place {
|
||||
match *elem {
|
||||
ProjectionElem::Field(..) => {
|
||||
let ty = base.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx);
|
||||
let ty = base.ty(&self.mir.local_decls, self.tcx).ty;
|
||||
match ty.sty {
|
||||
ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) {
|
||||
(Bound::Unbounded, Bound::Unbounded) => {},
|
||||
|
|
|
@ -556,7 +556,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
|
|||
if let StatementKind::Assign(ref place, ref rval) = statement.kind {
|
||||
let place_ty: ty::Ty<'tcx> = place
|
||||
.ty(&self.mir.local_decls, self.tcx)
|
||||
.to_ty(self.tcx);
|
||||
.ty;
|
||||
if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
|
||||
if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) {
|
||||
if let Place::Base(PlaceBase::Local(local)) = *place {
|
||||
|
|
|
@ -319,8 +319,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||
work_list.push(target);
|
||||
// If the location doesn't actually need dropping, treat it like
|
||||
// a regular goto.
|
||||
let ty = location.ty(callee_mir, tcx).subst(tcx, callsite.substs);
|
||||
let ty = ty.to_ty(tcx);
|
||||
let ty = location.ty(callee_mir, tcx).subst(tcx, callsite.substs).ty;
|
||||
if ty.needs_drop(tcx, param_env) {
|
||||
cost += CALL_PENALTY;
|
||||
if let Some(unwind) = unwind {
|
||||
|
@ -563,7 +562,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||
assert!(args.next().is_none());
|
||||
|
||||
let tuple = Place::Base(PlaceBase::Local(tuple));
|
||||
let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
|
||||
let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_mir, tcx).ty.sty {
|
||||
s
|
||||
} else {
|
||||
bug!("Closure arguments are not passed as a tuple");
|
||||
|
|
|
@ -82,14 +82,14 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
|
|||
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
|
||||
if let Rvalue::Ref(_, _, Place::Projection(ref projection)) = *rvalue {
|
||||
if let ProjectionElem::Deref = projection.elem {
|
||||
if projection.base.ty(self.mir, self.tcx).to_ty(self.tcx).is_region_ptr() {
|
||||
if projection.base.ty(self.mir, self.tcx).ty.is_region_ptr() {
|
||||
self.optimizations.and_stars.insert(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Rvalue::Len(ref place) = *rvalue {
|
||||
let place_ty = place.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx);
|
||||
let place_ty = place.ty(&self.mir.local_decls, self.tcx).ty;
|
||||
if let TyKind::Array(_, len) = place_ty.sty {
|
||||
let span = self.mir.source_info(location).span;
|
||||
let ty = self.tcx.types.usize;
|
||||
|
|
|
@ -135,7 +135,7 @@ fn check_lang_item_type<'a, 'tcx, D>(
|
|||
let sig = poly_sig.no_bound_vars().unwrap();
|
||||
let lhs_ty = lhs.ty(local_decls, tcx);
|
||||
let rhs_ty = rhs.ty(local_decls, tcx);
|
||||
let place_ty = place.ty(local_decls, tcx).to_ty(tcx);
|
||||
let place_ty = place.ty(local_decls, tcx).ty;
|
||||
let expected = [lhs_ty, rhs_ty, place_ty];
|
||||
assert_eq!(sig.inputs_and_output[..], expected,
|
||||
"lang item `{}`", tcx.def_path_str(did));
|
||||
|
|
|
@ -310,7 +310,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
|||
place = &mut proj.base;
|
||||
};
|
||||
|
||||
let ty = place.ty(local_decls, self.tcx).to_ty(self.tcx);
|
||||
let ty = place.ty(local_decls, self.tcx).ty;
|
||||
let span = statement.source_info.span;
|
||||
|
||||
Operand::Move(mem::replace(place, promoted_place(ty, span)))
|
||||
|
|
|
@ -168,7 +168,7 @@ trait Qualif {
|
|||
cx,
|
||||
proj.base.ty(cx.mir, cx.tcx)
|
||||
.projection_ty(cx.tcx, &proj.elem)
|
||||
.to_ty(cx.tcx),
|
||||
.ty,
|
||||
);
|
||||
match proj.elem {
|
||||
ProjectionElem::Deref |
|
||||
|
@ -245,7 +245,7 @@ trait Qualif {
|
|||
// Special-case reborrows to be more like a copy of the reference.
|
||||
if let Place::Projection(ref proj) = *place {
|
||||
if let ProjectionElem::Deref = proj.elem {
|
||||
let base_ty = proj.base.ty(cx.mir, cx.tcx).to_ty(cx.tcx);
|
||||
let base_ty = proj.base.ty(cx.mir, cx.tcx).ty;
|
||||
if let ty::Ref(..) = base_ty.sty {
|
||||
return Self::in_place(cx, &proj.base);
|
||||
}
|
||||
|
@ -301,7 +301,7 @@ impl Qualif for HasMutInterior {
|
|||
// allowed in constants (and the `Checker` will error), and/or it
|
||||
// won't be promoted, due to `&mut ...` or interior mutability.
|
||||
Rvalue::Ref(_, kind, ref place) => {
|
||||
let ty = place.ty(cx.mir, cx.tcx).to_ty(cx.tcx);
|
||||
let ty = place.ty(cx.mir, cx.tcx).ty;
|
||||
|
||||
if let BorrowKind::Mut { .. } = kind {
|
||||
// In theory, any zero-sized value could be borrowed
|
||||
|
@ -398,7 +398,7 @@ impl Qualif for IsNotConst {
|
|||
|
||||
ProjectionElem::Field(..) => {
|
||||
if cx.mode == Mode::Fn {
|
||||
let base_ty = proj.base.ty(cx.mir, cx.tcx).to_ty(cx.tcx);
|
||||
let base_ty = proj.base.ty(cx.mir, cx.tcx).ty;
|
||||
if let Some(def) = base_ty.ty_adt_def() {
|
||||
if def.is_union() {
|
||||
return true;
|
||||
|
@ -988,7 +988,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
|||
// `not_const` errors out in const contexts
|
||||
self.not_const()
|
||||
}
|
||||
let base_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
|
||||
let base_ty = proj.base.ty(self.mir, self.tcx).ty;
|
||||
match self.mode {
|
||||
Mode::Fn => {},
|
||||
_ => {
|
||||
|
@ -1012,7 +1012,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
|||
ProjectionElem::Subslice {..} |
|
||||
ProjectionElem::Field(..) |
|
||||
ProjectionElem::Index(_) => {
|
||||
let base_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
|
||||
let base_ty = proj.base.ty(self.mir, self.tcx).ty;
|
||||
if let Some(def) = base_ty.ty_adt_def() {
|
||||
if def.is_union() {
|
||||
match self.mode {
|
||||
|
@ -1069,7 +1069,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
|||
let mut is_reborrow = false;
|
||||
if let Place::Projection(ref proj) = *place {
|
||||
if let ProjectionElem::Deref = proj.elem {
|
||||
let base_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
|
||||
let base_ty = proj.base.ty(self.mir, self.tcx).ty;
|
||||
if let ty::Ref(..) = base_ty.sty {
|
||||
is_reborrow = true;
|
||||
}
|
||||
|
@ -1193,7 +1193,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
|||
self.assign(dest, ValueSource::Call {
|
||||
callee: func,
|
||||
args,
|
||||
return_ty: dest.ty(self.mir, self.tcx).to_ty(self.tcx),
|
||||
return_ty: dest.ty(self.mir, self.tcx).ty,
|
||||
}, location);
|
||||
}
|
||||
|
||||
|
@ -1367,7 +1367,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
|||
|
||||
if let Some(span) = needs_drop {
|
||||
// Double-check the type being dropped, to minimize false positives.
|
||||
let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
|
||||
let ty = place.ty(self.mir, self.tcx).ty;
|
||||
if ty.needs_drop(self.tcx, self.param_env) {
|
||||
struct_span_err!(self.tcx.sess, span, E0493,
|
||||
"destructors cannot be evaluated at compile-time")
|
||||
|
|
|
@ -69,7 +69,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> {
|
|||
from_end: false} = proj.elem {
|
||||
// no need to transformation
|
||||
} else {
|
||||
let place_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
|
||||
let place_ty = proj.base.ty(self.mir, self.tcx).ty;
|
||||
if let ty::Array(item_ty, const_size) = place_ty.sty {
|
||||
if let Some(size) = const_size.assert_usize(self.tcx) {
|
||||
assert!(size <= u32::max_value() as u64,
|
||||
|
@ -195,7 +195,7 @@ impl MirPass for RestoreSubsliceArrayMoveOut {
|
|||
|
||||
let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2);
|
||||
let opt_size = opt_src_place.and_then(|src_place| {
|
||||
let src_ty = src_place.ty(mir, tcx).to_ty(tcx);
|
||||
let src_ty = src_place.ty(mir, tcx).ty;
|
||||
if let ty::Array(_, ref size_o) = src_ty.sty {
|
||||
size_o.assert_usize(tcx)
|
||||
} else {
|
||||
|
|
|
@ -17,7 +17,7 @@ pub fn is_disaligned<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
return false
|
||||
}
|
||||
|
||||
let ty = place.ty(local_decls, tcx).to_ty(tcx);
|
||||
let ty = place.ty(local_decls, tcx).ty;
|
||||
match tcx.layout_raw(param_env.and(ty)) {
|
||||
Ok(layout) if layout.align.abi.bytes() == 1 => {
|
||||
// if the alignment is 1, the type can't be further
|
||||
|
@ -46,7 +46,7 @@ fn is_within_packed<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
// encountered a Deref, which is ABI-aligned
|
||||
ProjectionElem::Deref => break,
|
||||
ProjectionElem::Field(..) => {
|
||||
let ty = base.ty(local_decls, tcx).to_ty(tcx);
|
||||
let ty = base.ty(local_decls, tcx).ty;
|
||||
match ty.sty {
|
||||
ty::Adt(def, _) if def.repr.packed() => {
|
||||
return true
|
||||
|
|
|
@ -122,7 +122,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
|||
where D: DropElaborator<'b, 'tcx>
|
||||
{
|
||||
fn place_ty(&self, place: &Place<'tcx>) -> Ty<'tcx> {
|
||||
place.ty(self.elaborator.mir(), self.tcx()).to_ty(self.tcx())
|
||||
place.ty(self.elaborator.mir(), self.tcx()).ty
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
||||
|
@ -412,8 +412,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
|||
self.path, variant_index);
|
||||
if let Some(variant_path) = subpath {
|
||||
let base_place = self.place.clone().elem(
|
||||
ProjectionElem::Downcast(adt, variant_index)
|
||||
);
|
||||
ProjectionElem::Downcast(Some(adt.variants[variant_index].ident.name),
|
||||
variant_index));
|
||||
let fields = self.move_paths_for_fields(
|
||||
&base_place,
|
||||
variant_path,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue