Auto merge of #41469 - arielb1:rustc-spring-cleaning, r=eddyb
Performance audit, Spring 2017 Fix up some quite important performance "surprises" I've found running callgrind on rustc.
This commit is contained in:
commit
252d3da8a6
47 changed files with 322 additions and 185 deletions
|
@ -16,7 +16,6 @@
|
||||||
issue = "27700")]
|
issue = "27700")]
|
||||||
|
|
||||||
use core::{isize, usize};
|
use core::{isize, usize};
|
||||||
#[cfg(not(test))]
|
|
||||||
use core::intrinsics::{min_align_of_val, size_of_val};
|
use core::intrinsics::{min_align_of_val, size_of_val};
|
||||||
|
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
|
@ -158,10 +157,9 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(test))]
|
#[cfg_attr(not(test), lang = "box_free")]
|
||||||
#[lang = "box_free"]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
|
pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
|
||||||
let size = size_of_val(&*ptr);
|
let size = size_of_val(&*ptr);
|
||||||
let align = min_align_of_val(&*ptr);
|
let align = min_align_of_val(&*ptr);
|
||||||
// We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
|
// We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
|
||||||
|
|
|
@ -87,6 +87,7 @@
|
||||||
#![feature(needs_allocator)]
|
#![feature(needs_allocator)]
|
||||||
#![feature(optin_builtin_traits)]
|
#![feature(optin_builtin_traits)]
|
||||||
#![feature(placement_in_syntax)]
|
#![feature(placement_in_syntax)]
|
||||||
|
#![cfg_attr(stage0, feature(pub_restricted))]
|
||||||
#![feature(shared)]
|
#![feature(shared)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
|
|
|
@ -239,7 +239,7 @@ use core::ops::CoerceUnsized;
|
||||||
use core::ptr::{self, Shared};
|
use core::ptr::{self, Shared};
|
||||||
use core::convert::From;
|
use core::convert::From;
|
||||||
|
|
||||||
use heap::deallocate;
|
use heap::{allocate, deallocate, box_free};
|
||||||
use raw_vec::RawVec;
|
use raw_vec::RawVec;
|
||||||
|
|
||||||
struct RcBox<T: ?Sized> {
|
struct RcBox<T: ?Sized> {
|
||||||
|
@ -248,7 +248,6 @@ struct RcBox<T: ?Sized> {
|
||||||
value: T,
|
value: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// A single-threaded reference-counting pointer.
|
/// A single-threaded reference-counting pointer.
|
||||||
///
|
///
|
||||||
/// See the [module-level documentation](./index.html) for more details.
|
/// See the [module-level documentation](./index.html) for more details.
|
||||||
|
@ -438,6 +437,38 @@ impl Rc<str> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Rc<[T]> {
|
||||||
|
/// Constructs a new `Rc<[T]>` from a `Box<[T]>`.
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[unstable(feature = "rustc_private",
|
||||||
|
reason = "for internal use in rustc",
|
||||||
|
issue = "0")]
|
||||||
|
pub fn __from_array(value: Box<[T]>) -> Rc<[T]> {
|
||||||
|
unsafe {
|
||||||
|
let ptr: *mut RcBox<[T]> =
|
||||||
|
mem::transmute([mem::align_of::<RcBox<[T; 1]>>(), value.len()]);
|
||||||
|
// FIXME(custom-DST): creating this invalid &[T] is dubiously defined,
|
||||||
|
// we should have a better way of getting the size/align
|
||||||
|
// of a DST from its unsized part.
|
||||||
|
let ptr = allocate(size_of_val(&*ptr), align_of_val(&*ptr));
|
||||||
|
let ptr: *mut RcBox<[T]> = mem::transmute([ptr as usize, value.len()]);
|
||||||
|
|
||||||
|
// Initialize the new RcBox.
|
||||||
|
ptr::write(&mut (*ptr).strong, Cell::new(1));
|
||||||
|
ptr::write(&mut (*ptr).weak, Cell::new(1));
|
||||||
|
ptr::copy_nonoverlapping(
|
||||||
|
value.as_ptr(),
|
||||||
|
&mut (*ptr).value as *mut [T] as *mut T,
|
||||||
|
value.len());
|
||||||
|
|
||||||
|
// Free the original allocation without freeing its (moved) contents.
|
||||||
|
box_free(Box::into_raw(value));
|
||||||
|
|
||||||
|
Rc { ptr: Shared::new(ptr as *const _) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: ?Sized> Rc<T> {
|
impl<T: ?Sized> Rc<T> {
|
||||||
/// Creates a new [`Weak`][weak] pointer to this value.
|
/// Creates a new [`Weak`][weak] pointer to this value.
|
||||||
///
|
///
|
||||||
|
|
|
@ -99,7 +99,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
|
||||||
ty::ReEmpty |
|
ty::ReEmpty |
|
||||||
ty::ReErased => {
|
ty::ReErased => {
|
||||||
// replace all free regions with 'erased
|
// replace all free regions with 'erased
|
||||||
self.tcx().mk_region(ty::ReErased)
|
self.tcx().types.re_erased
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -948,7 +948,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
// otherwise, we don't know what the free region is,
|
// otherwise, we don't know what the free region is,
|
||||||
// so we must conservatively say the LUB is static:
|
// so we must conservatively say the LUB is static:
|
||||||
self.tcx.mk_region(ReStatic)
|
self.tcx.types.re_static
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -971,7 +971,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||||
if a == b {
|
if a == b {
|
||||||
a
|
a
|
||||||
} else {
|
} else {
|
||||||
self.tcx.mk_region(ReStatic)
|
self.tcx.types.re_static
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1018,7 +1018,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
fn construct_var_data(&self) -> Vec<VarValue<'tcx>> {
|
fn construct_var_data(&self) -> Vec<VarValue<'tcx>> {
|
||||||
(0..self.num_vars() as usize)
|
(0..self.num_vars() as usize)
|
||||||
.map(|_| Value(self.tcx.mk_region(ty::ReEmpty)))
|
.map(|_| Value(self.tcx.types.re_empty))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1493,7 +1493,7 @@ fn lookup<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
-> &'tcx ty::Region {
|
-> &'tcx ty::Region {
|
||||||
match values[rid.index as usize] {
|
match values[rid.index as usize] {
|
||||||
Value(r) => r,
|
Value(r) => r,
|
||||||
ErrorValue => tcx.mk_region(ReStatic), // Previously reported error.
|
ErrorValue => tcx.types.re_static, // Previously reported error.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -188,14 +188,13 @@ pub trait CrateStore {
|
||||||
fn visibility(&self, def: DefId) -> ty::Visibility;
|
fn visibility(&self, def: DefId) -> ty::Visibility;
|
||||||
fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>>;
|
fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>>;
|
||||||
fn item_generics_cloned(&self, def: DefId) -> ty::Generics;
|
fn item_generics_cloned(&self, def: DefId) -> ty::Generics;
|
||||||
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
|
fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]>;
|
||||||
fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>;
|
fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>;
|
||||||
|
|
||||||
// trait info
|
// trait info
|
||||||
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;
|
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;
|
||||||
|
|
||||||
// impl info
|
// impl info
|
||||||
fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity;
|
|
||||||
fn impl_parent(&self, impl_def_id: DefId) -> Option<DefId>;
|
fn impl_parent(&self, impl_def_id: DefId) -> Option<DefId>;
|
||||||
|
|
||||||
// trait/impl-item info
|
// trait/impl-item info
|
||||||
|
@ -323,14 +322,13 @@ impl CrateStore for DummyCrateStore {
|
||||||
}
|
}
|
||||||
fn item_generics_cloned(&self, def: DefId) -> ty::Generics
|
fn item_generics_cloned(&self, def: DefId) -> ty::Generics
|
||||||
{ bug!("item_generics_cloned") }
|
{ bug!("item_generics_cloned") }
|
||||||
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
|
fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]> { bug!("item_attrs") }
|
||||||
fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name> { bug!("fn_arg_names") }
|
fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name> { bug!("fn_arg_names") }
|
||||||
|
|
||||||
// trait info
|
// trait info
|
||||||
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }
|
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }
|
||||||
|
|
||||||
// impl info
|
// impl info
|
||||||
fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity { bug!("impl_polarity") }
|
|
||||||
fn impl_parent(&self, def: DefId) -> Option<DefId> { bug!("impl_parent") }
|
fn impl_parent(&self, def: DefId) -> Option<DefId> { bug!("impl_parent") }
|
||||||
|
|
||||||
// trait/impl-item info
|
// trait/impl-item info
|
||||||
|
|
|
@ -426,7 +426,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
hir::ExprMatch(ref discr, ref arms, _) => {
|
hir::ExprMatch(ref discr, ref arms, _) => {
|
||||||
let discr_cmt = return_if_err!(self.mc.cat_expr(&discr));
|
let discr_cmt = return_if_err!(self.mc.cat_expr(&discr));
|
||||||
let r = self.tcx().mk_region(ty::ReEmpty);
|
let r = self.tcx().types.re_empty;
|
||||||
self.borrow_expr(&discr, r, ty::ImmBorrow, MatchDiscriminant);
|
self.borrow_expr(&discr, r, ty::ImmBorrow, MatchDiscriminant);
|
||||||
|
|
||||||
// treatment of the discriminant is handled while walking the arms.
|
// treatment of the discriminant is handled while walking the arms.
|
||||||
|
|
|
@ -223,9 +223,10 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
|
||||||
|
|
||||||
pub fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
|
pub fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
|
||||||
for attribute in attrs {
|
for attribute in attrs {
|
||||||
match attribute.value_str() {
|
if attribute.check_name("lang") {
|
||||||
Some(value) if attribute.check_name("lang") => return Some(value),
|
if let Some(value) = attribute.value_str() {
|
||||||
_ => {}
|
return Some(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -871,8 +871,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
// we can promote to a constant, otherwise equal to enclosing temp
|
// we can promote to a constant, otherwise equal to enclosing temp
|
||||||
// lifetime.
|
// lifetime.
|
||||||
let (re, old_re) = if promotable {
|
let (re, old_re) = if promotable {
|
||||||
(self.tcx().mk_region(ty::ReStatic),
|
(self.tcx().types.re_static,
|
||||||
self.tcx().mk_region(ty::ReStatic))
|
self.tcx().types.re_static)
|
||||||
} else {
|
} else {
|
||||||
self.temporary_scope(id)
|
self.temporary_scope(id)
|
||||||
};
|
};
|
||||||
|
|
|
@ -443,7 +443,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
|
||||||
// Otherwise, we have something of the form
|
// Otherwise, we have something of the form
|
||||||
// `for<'a> T: 'a where 'a not in T`, which we can treat as `T: 'static`.
|
// `for<'a> T: 'a where 'a not in T`, which we can treat as `T: 'static`.
|
||||||
Some(t_a) => {
|
Some(t_a) => {
|
||||||
let r_static = selcx.tcx().mk_region(ty::ReStatic);
|
let r_static = selcx.tcx().types.re_static;
|
||||||
register_region_obligation(t_a, r_static,
|
register_region_obligation(t_a, r_static,
|
||||||
obligation.cause.clone(),
|
obligation.cause.clone(),
|
||||||
region_obligations);
|
region_obligations);
|
||||||
|
|
|
@ -629,7 +629,7 @@ pub fn get_vtable_methods<'a, 'tcx>(
|
||||||
// the method may have some early-bound lifetimes, add
|
// the method may have some early-bound lifetimes, add
|
||||||
// regions for those
|
// regions for those
|
||||||
let substs = Substs::for_item(tcx, def_id,
|
let substs = Substs::for_item(tcx, def_id,
|
||||||
|_, _| tcx.mk_region(ty::ReErased),
|
|_, _| tcx.types.re_erased,
|
||||||
|def, _| trait_ref.substs().type_for_def(def));
|
|def, _| trait_ref.substs().type_for_def(def));
|
||||||
|
|
||||||
// the trait type may have higher-ranked lifetimes in it;
|
// the trait type may have higher-ranked lifetimes in it;
|
||||||
|
|
|
@ -943,17 +943,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
debug!("Retaining candidate #{}/{}: {:?}",
|
debug!("Retaining candidate #{}/{}: {:?}",
|
||||||
i, candidates.len(), candidates[i]);
|
i, candidates.len(), candidates[i]);
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
||||||
|
// If there are *STILL* multiple candidates, give up
|
||||||
|
// and report ambiguity.
|
||||||
|
if i > 1 {
|
||||||
|
debug!("multiple matches, ambig");
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are *STILL* multiple candidates, give up and
|
|
||||||
// report ambiguity.
|
|
||||||
if candidates.len() > 1 {
|
|
||||||
debug!("multiple matches, ambig");
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are *NO* candidates, then there are no impls --
|
// If there are *NO* candidates, then there are no impls --
|
||||||
// that we know of, anyway. Note that in the case where there
|
// that we know of, anyway. Note that in the case where there
|
||||||
// are unbound type variables within the obligation, it might
|
// are unbound type variables within the obligation, it might
|
||||||
|
|
|
@ -190,6 +190,10 @@ pub struct CommonTypes<'tcx> {
|
||||||
pub f64: Ty<'tcx>,
|
pub f64: Ty<'tcx>,
|
||||||
pub never: Ty<'tcx>,
|
pub never: Ty<'tcx>,
|
||||||
pub err: Ty<'tcx>,
|
pub err: Ty<'tcx>,
|
||||||
|
|
||||||
|
pub re_empty: &'tcx Region,
|
||||||
|
pub re_static: &'tcx Region,
|
||||||
|
pub re_erased: &'tcx Region,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
|
@ -360,6 +364,14 @@ impl<'tcx> TypeckTables<'tcx> {
|
||||||
impl<'tcx> CommonTypes<'tcx> {
|
impl<'tcx> CommonTypes<'tcx> {
|
||||||
fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
|
fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
|
||||||
let mk = |sty| interners.intern_ty(sty, None);
|
let mk = |sty| interners.intern_ty(sty, None);
|
||||||
|
let mk_region = |r| {
|
||||||
|
if let Some(r) = interners.region.borrow().get(&r) {
|
||||||
|
return r.0;
|
||||||
|
}
|
||||||
|
let r = interners.arena.alloc(r);
|
||||||
|
interners.region.borrow_mut().insert(Interned(r));
|
||||||
|
&*r
|
||||||
|
};
|
||||||
CommonTypes {
|
CommonTypes {
|
||||||
bool: mk(TyBool),
|
bool: mk(TyBool),
|
||||||
char: mk(TyChar),
|
char: mk(TyChar),
|
||||||
|
@ -379,6 +391,10 @@ impl<'tcx> CommonTypes<'tcx> {
|
||||||
u128: mk(TyUint(ast::UintTy::U128)),
|
u128: mk(TyUint(ast::UintTy::U128)),
|
||||||
f32: mk(TyFloat(ast::FloatTy::F32)),
|
f32: mk(TyFloat(ast::FloatTy::F32)),
|
||||||
f64: mk(TyFloat(ast::FloatTy::F64)),
|
f64: mk(TyFloat(ast::FloatTy::F64)),
|
||||||
|
|
||||||
|
re_empty: mk_region(Region::ReEmpty),
|
||||||
|
re_static: mk_region(Region::ReStatic),
|
||||||
|
re_erased: mk_region(Region::ReErased),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1232,7 +1248,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_static_str(self) -> Ty<'tcx> {
|
pub fn mk_static_str(self) -> Ty<'tcx> {
|
||||||
self.mk_imm_ref(self.mk_region(ty::ReStatic), self.mk_str())
|
self.mk_imm_ref(self.types.re_static, self.mk_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_adt(self, def: &'tcx AdtDef, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
|
pub fn mk_adt(self, def: &'tcx AdtDef, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
|
||||||
|
|
|
@ -410,7 +410,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn erase_late_bound_regions<T>(self, value: &Binder<T>) -> T
|
pub fn erase_late_bound_regions<T>(self, value: &Binder<T>) -> T
|
||||||
where T : TypeFoldable<'tcx>
|
where T : TypeFoldable<'tcx>
|
||||||
{
|
{
|
||||||
self.replace_late_bound_regions(value, |_| self.mk_region(ty::ReErased)).0
|
self.replace_late_bound_regions(value, |_| self.types.re_erased).0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rewrite any late-bound regions so that they are anonymous. Region numbers are
|
/// Rewrite any late-bound regions so that they are anonymous. Region numbers are
|
||||||
|
@ -538,7 +538,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
// whenever a substitution occurs.
|
// whenever a substitution occurs.
|
||||||
match *r {
|
match *r {
|
||||||
ty::ReLateBound(..) => r,
|
ty::ReLateBound(..) => r,
|
||||||
_ => self.tcx().mk_region(ty::ReErased)
|
_ => self.tcx().types.re_erased
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -565,6 +565,22 @@ pub fn shift_region(region: ty::Region, amount: u32) -> ty::Region {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn shift_region_ref<'a, 'gcx, 'tcx>(
|
||||||
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
region: &'tcx ty::Region,
|
||||||
|
amount: u32)
|
||||||
|
-> &'tcx ty::Region
|
||||||
|
{
|
||||||
|
match region {
|
||||||
|
&ty::ReLateBound(debruijn, br) if amount > 0 => {
|
||||||
|
tcx.mk_region(ty::ReLateBound(debruijn.shifted(amount), br))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
region
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
amount: u32, value: &T) -> T
|
amount: u32, value: &T) -> T
|
||||||
where T: TypeFoldable<'tcx>
|
where T: TypeFoldable<'tcx>
|
||||||
|
@ -573,7 +589,7 @@ pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
value, amount);
|
value, amount);
|
||||||
|
|
||||||
value.fold_with(&mut RegionFolder::new(tcx, &mut false, &mut |region, _current_depth| {
|
value.fold_with(&mut RegionFolder::new(tcx, &mut false, &mut |region, _current_depth| {
|
||||||
tcx.mk_region(shift_region(*region, amount))
|
shift_region_ref(tcx, region, amount)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,10 +13,7 @@ use hir::def_id::DefId;
|
||||||
use ty::{self, Ty, TypeFoldable, Substs};
|
use ty::{self, Ty, TypeFoldable, Substs};
|
||||||
use util::ppaux;
|
use util::ppaux;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use syntax::ast;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct Instance<'tcx> {
|
pub struct Instance<'tcx> {
|
||||||
|
@ -59,7 +56,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn attrs<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> Cow<'tcx, [ast::Attribute]> {
|
pub fn attrs<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> ty::Attributes<'tcx> {
|
||||||
tcx.get_attrs(self.def_id())
|
tcx.get_attrs(self.def_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -822,7 +822,7 @@ impl<'a, 'gcx, 'tcx> Struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
(_, &ty::TyProjection(_)) | (_, &ty::TyAnon(..)) => {
|
(_, &ty::TyProjection(_)) | (_, &ty::TyAnon(..)) => {
|
||||||
let normalized = normalize_associated_type(infcx, ty);
|
let normalized = infcx.normalize_projections(ty);
|
||||||
if ty == normalized {
|
if ty == normalized {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
@ -1067,28 +1067,6 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function for normalizing associated types in an inference context.
|
|
||||||
fn normalize_associated_type<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
|
||||||
ty: Ty<'gcx>)
|
|
||||||
-> Ty<'gcx> {
|
|
||||||
if !ty.has_projection_types() {
|
|
||||||
return ty;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut selcx = traits::SelectionContext::new(infcx);
|
|
||||||
let cause = traits::ObligationCause::dummy();
|
|
||||||
let traits::Normalized { value: result, obligations } =
|
|
||||||
traits::normalize(&mut selcx, cause, &ty);
|
|
||||||
|
|
||||||
let mut fulfill_cx = traits::FulfillmentContext::new();
|
|
||||||
|
|
||||||
for obligation in obligations {
|
|
||||||
fulfill_cx.register_predicate_obligation(infcx, obligation);
|
|
||||||
}
|
|
||||||
|
|
||||||
infcx.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> Layout {
|
impl<'a, 'gcx, 'tcx> Layout {
|
||||||
pub fn compute_uncached(ty: Ty<'gcx>,
|
pub fn compute_uncached(ty: Ty<'gcx>,
|
||||||
infcx: &InferCtxt<'a, 'gcx, 'tcx>)
|
infcx: &InferCtxt<'a, 'gcx, 'tcx>)
|
||||||
|
@ -1100,7 +1078,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
|
|
||||||
let ptr_layout = |pointee: Ty<'gcx>| {
|
let ptr_layout = |pointee: Ty<'gcx>| {
|
||||||
let non_zero = !ty.is_unsafe_ptr();
|
let non_zero = !ty.is_unsafe_ptr();
|
||||||
let pointee = normalize_associated_type(infcx, pointee);
|
let pointee = infcx.normalize_projections(pointee);
|
||||||
if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) {
|
if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) {
|
||||||
Ok(Scalar { value: Pointer, non_zero: non_zero })
|
Ok(Scalar { value: Pointer, non_zero: non_zero })
|
||||||
} else {
|
} else {
|
||||||
|
@ -1494,7 +1472,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
|
|
||||||
// Types with no meaningful known layout.
|
// Types with no meaningful known layout.
|
||||||
ty::TyProjection(_) | ty::TyAnon(..) => {
|
ty::TyProjection(_) | ty::TyAnon(..) => {
|
||||||
let normalized = normalize_associated_type(infcx, ty);
|
let normalized = infcx.normalize_projections(ty);
|
||||||
if ty == normalized {
|
if ty == normalized {
|
||||||
return Err(LayoutError::Unknown(ty));
|
return Err(LayoutError::Unknown(ty));
|
||||||
}
|
}
|
||||||
|
@ -1812,7 +1790,7 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::TyProjection(_) | ty::TyAnon(..) => {
|
ty::TyProjection(_) | ty::TyAnon(..) => {
|
||||||
let normalized = normalize_associated_type(infcx, ty);
|
let normalized = infcx.normalize_projections(ty);
|
||||||
if ty == normalized {
|
if ty == normalized {
|
||||||
Err(err)
|
Err(err)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1882,13 +1860,14 @@ pub trait LayoutTyper<'tcx>: HasTyCtxt<'tcx> {
|
||||||
type TyLayout;
|
type TyLayout;
|
||||||
|
|
||||||
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout;
|
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout;
|
||||||
|
fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> LayoutTyper<'gcx> for &'a InferCtxt<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> LayoutTyper<'gcx> for &'a InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
type TyLayout = Result<TyLayout<'gcx>, LayoutError<'gcx>>;
|
type TyLayout = Result<TyLayout<'gcx>, LayoutError<'gcx>>;
|
||||||
|
|
||||||
fn layout_of(self, ty: Ty<'gcx>) -> Self::TyLayout {
|
fn layout_of(self, ty: Ty<'gcx>) -> Self::TyLayout {
|
||||||
let ty = normalize_associated_type(self, ty);
|
let ty = self.normalize_projections(ty);
|
||||||
|
|
||||||
Ok(TyLayout {
|
Ok(TyLayout {
|
||||||
ty: ty,
|
ty: ty,
|
||||||
|
@ -1896,6 +1875,25 @@ impl<'a, 'gcx, 'tcx> LayoutTyper<'gcx> for &'a InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
variant_index: None
|
variant_index: None
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn normalize_projections(self, ty: Ty<'gcx>) -> Ty<'gcx> {
|
||||||
|
if !ty.has_projection_types() {
|
||||||
|
return ty;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut selcx = traits::SelectionContext::new(self);
|
||||||
|
let cause = traits::ObligationCause::dummy();
|
||||||
|
let traits::Normalized { value: result, obligations } =
|
||||||
|
traits::normalize(&mut selcx, cause, &ty);
|
||||||
|
|
||||||
|
let mut fulfill_cx = traits::FulfillmentContext::new();
|
||||||
|
|
||||||
|
for obligation in obligations {
|
||||||
|
fulfill_cx.register_predicate_obligation(self, obligation);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> TyLayout<'tcx> {
|
impl<'a, 'tcx> TyLayout<'tcx> {
|
||||||
|
@ -2019,6 +2017,6 @@ impl<'a, 'tcx> TyLayout<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn field<C: LayoutTyper<'tcx>>(&self, cx: C, i: usize) -> C::TyLayout {
|
pub fn field<C: LayoutTyper<'tcx>>(&self, cx: C, i: usize) -> C::TyLayout {
|
||||||
cx.layout_of(self.field_type(cx, i))
|
cx.layout_of(cx.normalize_projections(self.field_type(cx, i)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
|
use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
|
||||||
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||||
|
use hir;
|
||||||
use middle::const_val;
|
use middle::const_val;
|
||||||
use middle::privacy::AccessLevels;
|
use middle::privacy::AccessLevels;
|
||||||
use mir;
|
use mir;
|
||||||
|
@ -394,6 +395,7 @@ define_maps! { <'tcx>
|
||||||
pub associated_item: AssociatedItems(DefId) -> ty::AssociatedItem,
|
pub associated_item: AssociatedItems(DefId) -> ty::AssociatedItem,
|
||||||
|
|
||||||
pub impl_trait_ref: ItemSignature(DefId) -> Option<ty::TraitRef<'tcx>>,
|
pub impl_trait_ref: ItemSignature(DefId) -> Option<ty::TraitRef<'tcx>>,
|
||||||
|
pub impl_polarity: ItemSignature(DefId) -> hir::ImplPolarity,
|
||||||
|
|
||||||
/// Maps a DefId of a type to a list of its inherent impls.
|
/// Maps a DefId of a type to a list of its inherent impls.
|
||||||
/// Contains implementations of methods that are inherent to a type.
|
/// Contains implementations of methods that are inherent to a type.
|
||||||
|
|
|
@ -34,7 +34,6 @@ use ty::walk::TypeWalker;
|
||||||
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
|
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
|
||||||
|
|
||||||
use serialize::{self, Encodable, Encoder};
|
use serialize::{self, Encodable, Encoder};
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::cell::{Cell, RefCell, Ref};
|
use std::cell::{Cell, RefCell, Ref};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
@ -2036,6 +2035,23 @@ impl BorrowKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Attributes<'gcx> {
|
||||||
|
Owned(Rc<[ast::Attribute]>),
|
||||||
|
Borrowed(&'gcx [ast::Attribute])
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'gcx> ::std::ops::Deref for Attributes<'gcx> {
|
||||||
|
type Target = [ast::Attribute];
|
||||||
|
|
||||||
|
fn deref(&self) -> &[ast::Attribute] {
|
||||||
|
match self {
|
||||||
|
&Attributes::Owned(ref data) => &data,
|
||||||
|
&Attributes::Borrowed(data) => data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> {
|
pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> {
|
||||||
self.item_tables(self.hir.body_owner_def_id(body))
|
self.item_tables(self.hir.body_owner_def_id(body))
|
||||||
|
@ -2133,14 +2149,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trait_impl_polarity(self, id: DefId) -> hir::ImplPolarity {
|
pub fn trait_impl_polarity(self, id: DefId) -> hir::ImplPolarity {
|
||||||
if let Some(id) = self.hir.as_local_node_id(id) {
|
queries::impl_polarity::get(self, DUMMY_SP, id)
|
||||||
match self.hir.expect_item(id).node {
|
|
||||||
hir::ItemImpl(_, polarity, ..) => polarity,
|
|
||||||
ref item => bug!("trait_impl_polarity: {:?} not an impl", item)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.sess.cstore.impl_polarity(id)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trait_relevant_for_never(self, did: DefId) -> bool {
|
pub fn trait_relevant_for_never(self, did: DefId) -> bool {
|
||||||
|
@ -2389,11 +2398,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the attributes of a definition.
|
/// Get the attributes of a definition.
|
||||||
pub fn get_attrs(self, did: DefId) -> Cow<'gcx, [ast::Attribute]> {
|
pub fn get_attrs(self, did: DefId) -> Attributes<'gcx> {
|
||||||
if let Some(id) = self.hir.as_local_node_id(did) {
|
if let Some(id) = self.hir.as_local_node_id(did) {
|
||||||
Cow::Borrowed(self.hir.attrs(id))
|
Attributes::Borrowed(self.hir.attrs(id))
|
||||||
} else {
|
} else {
|
||||||
Cow::Owned(self.sess.cstore.item_attrs(did))
|
Attributes::Owned(self.sess.cstore.item_attrs(did))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2499,15 +2508,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
/// Construct a parameter environment suitable for static contexts or other contexts where there
|
/// Construct a parameter environment suitable for static contexts or other contexts where there
|
||||||
/// are no free type/lifetime parameters in scope.
|
/// are no free type/lifetime parameters in scope.
|
||||||
pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
|
pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
|
||||||
|
|
||||||
// for an empty parameter environment, there ARE no free
|
|
||||||
// regions, so it shouldn't matter what we use for the free id
|
|
||||||
let free_id_outlive = self.region_maps.node_extent(ast::DUMMY_NODE_ID);
|
|
||||||
ty::ParameterEnvironment {
|
ty::ParameterEnvironment {
|
||||||
free_substs: self.intern_substs(&[]),
|
free_substs: self.intern_substs(&[]),
|
||||||
caller_bounds: Vec::new(),
|
caller_bounds: Vec::new(),
|
||||||
implicit_region_bound: self.mk_region(ty::ReEmpty),
|
implicit_region_bound: self.types.re_empty,
|
||||||
free_id_outlive: free_id_outlive,
|
// for an empty parameter environment, there ARE no free
|
||||||
|
// regions, so it shouldn't matter what we use for the free id
|
||||||
|
free_id_outlive: ROOT_CODE_EXTENT,
|
||||||
is_copy_cache: RefCell::new(FxHashMap()),
|
is_copy_cache: RefCell::new(FxHashMap()),
|
||||||
is_sized_cache: RefCell::new(FxHashMap()),
|
is_sized_cache: RefCell::new(FxHashMap()),
|
||||||
is_freeze_cache: RefCell::new(FxHashMap()),
|
is_freeze_cache: RefCell::new(FxHashMap()),
|
||||||
|
@ -2760,4 +2767,3 @@ pub fn provide_extern(providers: &mut ty::maps::Providers) {
|
||||||
pub struct CrateInherentImpls {
|
pub struct CrateInherentImpls {
|
||||||
pub inherent_impls: DefIdMap<Rc<Vec<DefId>>>,
|
pub inherent_impls: DefIdMap<Rc<Vec<DefId>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -539,6 +539,9 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shift_region_through_binders(&self, region: &'tcx ty::Region) -> &'tcx ty::Region {
|
fn shift_region_through_binders(&self, region: &'tcx ty::Region) -> &'tcx ty::Region {
|
||||||
|
if self.region_binders_passed == 0 || !region.has_escaping_regions() {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
self.tcx().mk_region(ty::fold::shift_region(*region, self.region_binders_passed))
|
self.tcx().mk_region(ty::fold::shift_region(*region, self.region_binders_passed))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -412,7 +412,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
/// a suitable "empty substs" for it.
|
/// a suitable "empty substs" for it.
|
||||||
pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx ty::Substs<'tcx> {
|
pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx ty::Substs<'tcx> {
|
||||||
ty::Substs::for_item(self, item_def_id,
|
ty::Substs::for_item(self, item_def_id,
|
||||||
|_, _| self.mk_region(ty::ReErased),
|
|_, _| self.types.re_erased,
|
||||||
|_, _| {
|
|_, _| {
|
||||||
bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
|
bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
|
||||||
})
|
})
|
||||||
|
|
|
@ -120,7 +120,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
Categorization::StaticItem |
|
Categorization::StaticItem |
|
||||||
Categorization::Deref(.., mc::UnsafePtr(..)) => {
|
Categorization::Deref(.., mc::UnsafePtr(..)) => {
|
||||||
self.bccx.tcx.mk_region(ty::ReStatic)
|
self.bccx.tcx.types.re_static
|
||||||
}
|
}
|
||||||
Categorization::Deref(.., mc::BorrowedPtr(_, r)) |
|
Categorization::Deref(.., mc::BorrowedPtr(_, r)) |
|
||||||
Categorization::Deref(.., mc::Implicit(_, r)) => {
|
Categorization::Deref(.., mc::Implicit(_, r)) => {
|
||||||
|
|
|
@ -225,6 +225,8 @@ pub fn compile_input(sess: &Session,
|
||||||
sess.code_stats.borrow().print_type_sizes();
|
sess.code_stats.borrow().print_type_sizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ::std::env::var("SKIP_LLVM").is_ok() { ::std::process::exit(0); }
|
||||||
|
|
||||||
let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs);
|
let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs);
|
||||||
|
|
||||||
controller_entry_point!(after_llvm,
|
controller_entry_point!(after_llvm,
|
||||||
|
|
|
@ -343,12 +343,12 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn t_rptr_static(&self) -> Ty<'tcx> {
|
pub fn t_rptr_static(&self) -> Ty<'tcx> {
|
||||||
self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(ty::ReStatic),
|
self.infcx.tcx.mk_imm_ref(self.infcx.tcx.types.re_static,
|
||||||
self.tcx().types.isize)
|
self.tcx().types.isize)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn t_rptr_empty(&self) -> Ty<'tcx> {
|
pub fn t_rptr_empty(&self) -> Ty<'tcx> {
|
||||||
self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(ty::ReEmpty),
|
self.infcx.tcx.mk_imm_ref(self.infcx.tcx.types.re_empty,
|
||||||
self.tcx().types.isize)
|
self.tcx().types.isize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -326,6 +326,7 @@ impl<'a> CrateLoader<'a> {
|
||||||
cnum_map: RefCell::new(cnum_map),
|
cnum_map: RefCell::new(cnum_map),
|
||||||
cnum: cnum,
|
cnum: cnum,
|
||||||
codemap_import_info: RefCell::new(vec![]),
|
codemap_import_info: RefCell::new(vec![]),
|
||||||
|
attribute_cache: RefCell::new([Vec::new(), Vec::new()]),
|
||||||
dep_kind: Cell::new(dep_kind),
|
dep_kind: Cell::new(dep_kind),
|
||||||
source: cstore::CrateSource {
|
source: cstore::CrateSource {
|
||||||
dylib: dylib,
|
dylib: dylib,
|
||||||
|
|
|
@ -72,6 +72,7 @@ pub struct CrateMetadata {
|
||||||
pub cnum_map: RefCell<CrateNumMap>,
|
pub cnum_map: RefCell<CrateNumMap>,
|
||||||
pub cnum: CrateNum,
|
pub cnum: CrateNum,
|
||||||
pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
|
pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
|
||||||
|
pub attribute_cache: RefCell<[Vec<Option<Rc<[ast::Attribute]>>>; 2]>,
|
||||||
|
|
||||||
pub root: schema::CrateRoot,
|
pub root: schema::CrateRoot,
|
||||||
|
|
||||||
|
@ -269,7 +270,7 @@ impl CrateMetadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_staged_api(&self) -> bool {
|
pub fn is_staged_api(&self) -> bool {
|
||||||
for attr in self.get_item_attrs(CRATE_DEF_INDEX) {
|
for attr in self.get_item_attrs(CRATE_DEF_INDEX).iter() {
|
||||||
if attr.path == "stable" || attr.path == "unstable" {
|
if attr.path == "stable" || attr.path == "unstable" {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,7 @@ provide! { <'tcx> tcx, def_id, cdata
|
||||||
}
|
}
|
||||||
associated_item => { cdata.get_associated_item(def_id.index) }
|
associated_item => { cdata.get_associated_item(def_id.index) }
|
||||||
impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) }
|
impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) }
|
||||||
|
impl_polarity => { cdata.get_impl_polarity(def_id.index) }
|
||||||
coerce_unsized_info => {
|
coerce_unsized_info => {
|
||||||
cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| {
|
cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| {
|
||||||
bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
|
bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
|
||||||
|
@ -149,7 +150,7 @@ impl CrateStore for cstore::CStore {
|
||||||
self.get_crate_data(def.krate).get_generics(def.index)
|
self.get_crate_data(def.krate).get_generics(def.index)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>
|
fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]>
|
||||||
{
|
{
|
||||||
self.dep_graph.read(DepNode::MetaData(def_id));
|
self.dep_graph.read(DepNode::MetaData(def_id));
|
||||||
self.get_crate_data(def_id.krate).get_item_attrs(def_id.index)
|
self.get_crate_data(def_id.krate).get_item_attrs(def_id.index)
|
||||||
|
@ -177,12 +178,6 @@ impl CrateStore for cstore::CStore {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity
|
|
||||||
{
|
|
||||||
self.dep_graph.read(DepNode::MetaData(def));
|
|
||||||
self.get_crate_data(def.krate).get_impl_polarity(def.index)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn impl_parent(&self, impl_def: DefId) -> Option<DefId> {
|
fn impl_parent(&self, impl_def: DefId) -> Option<DefId> {
|
||||||
self.dep_graph.read(DepNode::MetaData(impl_def));
|
self.dep_graph.read(DepNode::MetaData(impl_def));
|
||||||
self.get_crate_data(impl_def.krate).get_parent_impl(impl_def.index)
|
self.get_crate_data(impl_def.krate).get_parent_impl(impl_def.index)
|
||||||
|
@ -406,7 +401,7 @@ impl CrateStore for cstore::CStore {
|
||||||
|
|
||||||
// Mark the attrs as used
|
// Mark the attrs as used
|
||||||
let attrs = data.get_item_attrs(id.index);
|
let attrs = data.get_item_attrs(id.index);
|
||||||
for attr in &attrs {
|
for attr in attrs.iter() {
|
||||||
attr::mark_used(attr);
|
attr::mark_used(attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +414,7 @@ impl CrateStore for cstore::CStore {
|
||||||
ident: ast::Ident::with_empty_ctxt(name),
|
ident: ast::Ident::with_empty_ctxt(name),
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
span: local_span,
|
span: local_span,
|
||||||
attrs: attrs,
|
attrs: attrs.iter().cloned().collect(),
|
||||||
node: ast::ItemKind::MacroDef(body.into()),
|
node: ast::ItemKind::MacroDef(body.into()),
|
||||||
vis: ast::Visibility::Inherited,
|
vis: ast::Visibility::Inherited,
|
||||||
})
|
})
|
||||||
|
|
|
@ -31,6 +31,7 @@ use std::cell::Ref;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::u32;
|
use std::u32;
|
||||||
|
|
||||||
|
@ -859,10 +860,18 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_item_attrs(&self, node_id: DefIndex) -> Vec<ast::Attribute> {
|
pub fn get_item_attrs(&self, node_id: DefIndex) -> Rc<[ast::Attribute]> {
|
||||||
|
let (node_as, node_index) =
|
||||||
|
(node_id.address_space().index(), node_id.as_array_index());
|
||||||
if self.is_proc_macro(node_id) {
|
if self.is_proc_macro(node_id) {
|
||||||
return Vec::new();
|
return Rc::new([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(&Some(ref val)) =
|
||||||
|
self.attribute_cache.borrow()[node_as].get(node_index) {
|
||||||
|
return val.clone();
|
||||||
|
}
|
||||||
|
|
||||||
// The attributes for a tuple struct are attached to the definition, not the ctor;
|
// The attributes for a tuple struct are attached to the definition, not the ctor;
|
||||||
// we assume that someone passing in a tuple struct ctor is actually wanting to
|
// we assume that someone passing in a tuple struct ctor is actually wanting to
|
||||||
// look at the definition
|
// look at the definition
|
||||||
|
@ -871,7 +880,13 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
if def_key.disambiguated_data.data == DefPathData::StructCtor {
|
if def_key.disambiguated_data.data == DefPathData::StructCtor {
|
||||||
item = self.entry(def_key.parent.unwrap());
|
item = self.entry(def_key.parent.unwrap());
|
||||||
}
|
}
|
||||||
self.get_attributes(&item)
|
let result = Rc::__from_array(self.get_attributes(&item).into_boxed_slice());
|
||||||
|
let vec_ = &mut self.attribute_cache.borrow_mut()[node_as];
|
||||||
|
if vec_.len() < node_index + 1 {
|
||||||
|
vec_.resize(node_index + 1, None);
|
||||||
|
}
|
||||||
|
vec_[node_index] = Some(result.clone());
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_struct_field_names(&self, id: DefIndex) -> Vec<ast::Name> {
|
pub fn get_struct_field_names(&self, id: DefIndex) -> Vec<ast::Name> {
|
||||||
|
|
|
@ -280,7 +280,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
assert!(ty.is_slice());
|
assert!(ty.is_slice());
|
||||||
|
|
||||||
let array_ty = tcx.mk_array(tcx.types.u8, bytes.len());
|
let array_ty = tcx.mk_array(tcx.types.u8, bytes.len());
|
||||||
let array_ref = tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic), array_ty);
|
let array_ref = tcx.mk_imm_ref(tcx.types.re_static, array_ty);
|
||||||
let array = self.literal_operand(test.span, array_ref, Literal::Value {
|
let array = self.literal_operand(test.span, array_ref, Literal::Value {
|
||||||
value: value.clone()
|
value: value.clone()
|
||||||
});
|
});
|
||||||
|
|
|
@ -308,10 +308,9 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
Adjustment::Deref => Operand::Consume(rcvr_l.deref()),
|
Adjustment::Deref => Operand::Consume(rcvr_l.deref()),
|
||||||
Adjustment::RefMut => {
|
Adjustment::RefMut => {
|
||||||
// let rcvr = &mut rcvr;
|
// let rcvr = &mut rcvr;
|
||||||
let re_erased = tcx.mk_region(ty::ReErased);
|
|
||||||
let ref_rcvr = local_decls.push(temp_decl(
|
let ref_rcvr = local_decls.push(temp_decl(
|
||||||
Mutability::Not,
|
Mutability::Not,
|
||||||
tcx.mk_ref(re_erased, ty::TypeAndMut {
|
tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
|
||||||
ty: sig.inputs()[0],
|
ty: sig.inputs()[0],
|
||||||
mutbl: hir::Mutability::MutMutable
|
mutbl: hir::Mutability::MutMutable
|
||||||
}),
|
}),
|
||||||
|
@ -321,7 +320,7 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
source_info: source_info,
|
source_info: source_info,
|
||||||
kind: StatementKind::Assign(
|
kind: StatementKind::Assign(
|
||||||
Lvalue::Local(ref_rcvr),
|
Lvalue::Local(ref_rcvr),
|
||||||
Rvalue::Ref(re_erased, BorrowKind::Mut, rcvr_l)
|
Rvalue::Ref(tcx.types.re_erased, BorrowKind::Mut, rcvr_l)
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
Operand::Consume(Lvalue::Local(ref_rcvr))
|
Operand::Consume(Lvalue::Local(ref_rcvr))
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//! care erasing regions all over the place.
|
//! care erasing regions all over the place.
|
||||||
|
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
use rustc::ty::{Ty, TyCtxt, ReErased, ClosureSubsts};
|
use rustc::ty::{Ty, TyCtxt, ClosureSubsts};
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc::mir::visit::MutVisitor;
|
use rustc::mir::visit::MutVisitor;
|
||||||
use rustc::mir::transform::{MirPass, MirSource, Pass};
|
use rustc::mir::transform::{MirPass, MirSource, Pass};
|
||||||
|
@ -43,7 +43,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
|
||||||
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
|
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
|
||||||
match *rvalue {
|
match *rvalue {
|
||||||
Rvalue::Ref(ref mut r, _, _) => {
|
Rvalue::Ref(ref mut r, _, _) => {
|
||||||
*r = self.tcx.mk_region(ReErased);
|
*r = self.tcx.types.re_erased;
|
||||||
}
|
}
|
||||||
Rvalue::Use(..) |
|
Rvalue::Use(..) |
|
||||||
Rvalue::Repeat(..) |
|
Rvalue::Repeat(..) |
|
||||||
|
|
|
@ -497,7 +497,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
||||||
let dest = if dest_needs_borrow(&destination.0) {
|
let dest = if dest_needs_borrow(&destination.0) {
|
||||||
debug!("Creating temp for return destination");
|
debug!("Creating temp for return destination");
|
||||||
let dest = Rvalue::Ref(
|
let dest = Rvalue::Ref(
|
||||||
self.tcx.mk_region(ty::ReErased),
|
self.tcx.types.re_erased,
|
||||||
BorrowKind::Mut,
|
BorrowKind::Mut,
|
||||||
destination.0);
|
destination.0);
|
||||||
|
|
||||||
|
@ -582,7 +582,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
||||||
fn cast_box_free_arg(&self, arg: Lvalue<'tcx>, ptr_ty: Ty<'tcx>,
|
fn cast_box_free_arg(&self, arg: Lvalue<'tcx>, ptr_ty: Ty<'tcx>,
|
||||||
callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Operand<'tcx> {
|
callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Operand<'tcx> {
|
||||||
let arg = Rvalue::Ref(
|
let arg = Rvalue::Ref(
|
||||||
self.tcx.mk_region(ty::ReErased),
|
self.tcx.types.re_erased,
|
||||||
BorrowKind::Mut,
|
BorrowKind::Mut,
|
||||||
arg.deref());
|
arg.deref());
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,8 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
|
||||||
self.collapse_goto_chain(successor, &mut changed);
|
self.collapse_goto_chain(successor, &mut changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changed |= self.simplify_unwind(&mut terminator);
|
||||||
|
|
||||||
let mut new_stmts = vec![];
|
let mut new_stmts = vec![];
|
||||||
let mut inner_changed = true;
|
let mut inner_changed = true;
|
||||||
while inner_changed {
|
while inner_changed {
|
||||||
|
@ -238,6 +240,38 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// turn an unwind branch to a resume block into a None
|
||||||
|
fn simplify_unwind(&mut self, terminator: &mut Terminator<'tcx>) -> bool {
|
||||||
|
let unwind = match terminator.kind {
|
||||||
|
TerminatorKind::Drop { ref mut unwind, .. } |
|
||||||
|
TerminatorKind::DropAndReplace { ref mut unwind, .. } |
|
||||||
|
TerminatorKind::Call { cleanup: ref mut unwind, .. } |
|
||||||
|
TerminatorKind::Assert { cleanup: ref mut unwind, .. } =>
|
||||||
|
unwind,
|
||||||
|
_ => return false
|
||||||
|
};
|
||||||
|
|
||||||
|
if let &mut Some(unwind_block) = unwind {
|
||||||
|
let is_resume_block = match self.basic_blocks[unwind_block] {
|
||||||
|
BasicBlockData {
|
||||||
|
ref statements,
|
||||||
|
terminator: Some(Terminator {
|
||||||
|
kind: TerminatorKind::Resume, ..
|
||||||
|
}), ..
|
||||||
|
} if statements.is_empty() => true,
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
|
if is_resume_block {
|
||||||
|
debug!("simplifying unwind to {:?} from {:?}",
|
||||||
|
unwind_block, terminator.source_info);
|
||||||
|
*unwind = None;
|
||||||
|
}
|
||||||
|
return is_resume_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn strip_nops(&mut self) {
|
fn strip_nops(&mut self) {
|
||||||
for blk in self.basic_blocks.iter_mut() {
|
for blk in self.basic_blocks.iter_mut() {
|
||||||
blk.statements.retain(|stmt| if let StatementKind::Nop = stmt.kind {
|
blk.statements.retain(|stmt| if let StatementKind::Nop = stmt.kind {
|
||||||
|
|
|
@ -506,8 +506,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
let ty = self.lvalue_ty(self.lvalue);
|
let ty = self.lvalue_ty(self.lvalue);
|
||||||
let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
|
let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
|
||||||
|
|
||||||
let re_erased = tcx.mk_region(ty::ReErased);
|
let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
|
||||||
let ref_ty = tcx.mk_ref(re_erased, ty::TypeAndMut {
|
|
||||||
ty: ty,
|
ty: ty,
|
||||||
mutbl: hir::Mutability::MutMutable
|
mutbl: hir::Mutability::MutMutable
|
||||||
});
|
});
|
||||||
|
@ -519,7 +518,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
|
||||||
source_info: self.source_info,
|
source_info: self.source_info,
|
||||||
kind: StatementKind::Assign(
|
kind: StatementKind::Assign(
|
||||||
Lvalue::Local(ref_lvalue),
|
Lvalue::Local(ref_lvalue),
|
||||||
Rvalue::Ref(re_erased, BorrowKind::Mut, self.lvalue.clone())
|
Rvalue::Ref(tcx.types.re_erased, BorrowKind::Mut, self.lvalue.clone())
|
||||||
)
|
)
|
||||||
}],
|
}],
|
||||||
terminator: Some(Terminator {
|
terminator: Some(Terminator {
|
||||||
|
|
|
@ -110,7 +110,8 @@ use rustc::hir::map::definitions::DefPathData;
|
||||||
use rustc::util::common::record_time;
|
use rustc::util::common::record_time;
|
||||||
|
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::symbol::{Symbol, InternedString};
|
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
|
@ -252,19 +253,47 @@ pub fn symbol_name<'a, 'tcx>(instance: Instance<'tcx>,
|
||||||
|
|
||||||
let hash = get_symbol_hash(tcx, Some(def_id), instance_ty, Some(substs));
|
let hash = get_symbol_hash(tcx, Some(def_id), instance_ty, Some(substs));
|
||||||
|
|
||||||
let mut buffer = SymbolPathBuffer {
|
let mut buffer = SymbolPathBuffer::new();
|
||||||
names: Vec::new()
|
|
||||||
};
|
|
||||||
|
|
||||||
item_path::with_forced_absolute_paths(|| {
|
item_path::with_forced_absolute_paths(|| {
|
||||||
tcx.push_item_path(&mut buffer, def_id);
|
tcx.push_item_path(&mut buffer, def_id);
|
||||||
});
|
});
|
||||||
|
buffer.finish(&hash)
|
||||||
mangle(buffer.names.into_iter(), &hash)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Follow C++ namespace-mangling style, see
|
||||||
|
// http://en.wikipedia.org/wiki/Name_mangling for more info.
|
||||||
|
//
|
||||||
|
// It turns out that on macOS you can actually have arbitrary symbols in
|
||||||
|
// function names (at least when given to LLVM), but this is not possible
|
||||||
|
// when using unix's linker. Perhaps one day when we just use a linker from LLVM
|
||||||
|
// we won't need to do this name mangling. The problem with name mangling is
|
||||||
|
// that it seriously limits the available characters. For example we can't
|
||||||
|
// have things like &T in symbol names when one would theoretically
|
||||||
|
// want them for things like impls of traits on that type.
|
||||||
|
//
|
||||||
|
// To be able to work on all platforms and get *some* reasonable output, we
|
||||||
|
// use C++ name-mangling.
|
||||||
struct SymbolPathBuffer {
|
struct SymbolPathBuffer {
|
||||||
names: Vec<InternedString>,
|
result: String,
|
||||||
|
temp_buf: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SymbolPathBuffer {
|
||||||
|
fn new() -> Self {
|
||||||
|
let mut result = SymbolPathBuffer {
|
||||||
|
result: String::with_capacity(64),
|
||||||
|
temp_buf: String::with_capacity(16)
|
||||||
|
};
|
||||||
|
result.result.push_str("_ZN"); // _Z == Begin name-sequence, N == nested
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(mut self, hash: &str) -> String {
|
||||||
|
// end name-sequence
|
||||||
|
self.push(hash);
|
||||||
|
self.result.push('E');
|
||||||
|
self.result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemPathBuffer for SymbolPathBuffer {
|
impl ItemPathBuffer for SymbolPathBuffer {
|
||||||
|
@ -274,7 +303,13 @@ impl ItemPathBuffer for SymbolPathBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, text: &str) {
|
fn push(&mut self, text: &str) {
|
||||||
self.names.push(Symbol::intern(text).as_str());
|
self.temp_buf.clear();
|
||||||
|
let need_underscore = sanitize(&mut self.temp_buf, text);
|
||||||
|
let _ = write!(self.result, "{}", self.temp_buf.len() + (need_underscore as usize));
|
||||||
|
if need_underscore {
|
||||||
|
self.result.push('_');
|
||||||
|
}
|
||||||
|
self.result.push_str(&self.temp_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,15 +318,17 @@ pub fn exported_name_from_type_and_prefix<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
prefix: &str)
|
prefix: &str)
|
||||||
-> String {
|
-> String {
|
||||||
let hash = get_symbol_hash(tcx, None, t, None);
|
let hash = get_symbol_hash(tcx, None, t, None);
|
||||||
let path = [Symbol::intern(prefix).as_str()];
|
let mut buffer = SymbolPathBuffer::new();
|
||||||
mangle(path.iter().cloned(), &hash)
|
buffer.push(prefix);
|
||||||
|
buffer.finish(&hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name sanitation. LLVM will happily accept identifiers with weird names, but
|
// Name sanitation. LLVM will happily accept identifiers with weird names, but
|
||||||
// gas doesn't!
|
// gas doesn't!
|
||||||
// gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
|
// gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
|
||||||
pub fn sanitize(s: &str) -> String {
|
//
|
||||||
let mut result = String::new();
|
// returns true if an underscore must be added at the start
|
||||||
|
pub fn sanitize(result: &mut String, s: &str) -> bool {
|
||||||
for c in s.chars() {
|
for c in s.chars() {
|
||||||
match c {
|
match c {
|
||||||
// Escape these with $ sequences
|
// Escape these with $ sequences
|
||||||
|
@ -328,44 +365,7 @@ pub fn sanitize(s: &str) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Underscore-qualify anything that didn't start as an ident.
|
// Underscore-qualify anything that didn't start as an ident.
|
||||||
if !result.is_empty() &&
|
!result.is_empty() &&
|
||||||
result.as_bytes()[0] != '_' as u8 &&
|
result.as_bytes()[0] != '_' as u8 &&
|
||||||
! (result.as_bytes()[0] as char).is_xid_start() {
|
! (result.as_bytes()[0] as char).is_xid_start()
|
||||||
return format!("_{}", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mangle<PI: Iterator<Item=InternedString>>(path: PI, hash: &str) -> String {
|
|
||||||
// Follow C++ namespace-mangling style, see
|
|
||||||
// http://en.wikipedia.org/wiki/Name_mangling for more info.
|
|
||||||
//
|
|
||||||
// It turns out that on macOS you can actually have arbitrary symbols in
|
|
||||||
// function names (at least when given to LLVM), but this is not possible
|
|
||||||
// when using unix's linker. Perhaps one day when we just use a linker from LLVM
|
|
||||||
// we won't need to do this name mangling. The problem with name mangling is
|
|
||||||
// that it seriously limits the available characters. For example we can't
|
|
||||||
// have things like &T in symbol names when one would theoretically
|
|
||||||
// want them for things like impls of traits on that type.
|
|
||||||
//
|
|
||||||
// To be able to work on all platforms and get *some* reasonable output, we
|
|
||||||
// use C++ name-mangling.
|
|
||||||
|
|
||||||
let mut n = String::from("_ZN"); // _Z == Begin name-sequence, N == nested
|
|
||||||
|
|
||||||
fn push(n: &mut String, s: &str) {
|
|
||||||
let sani = sanitize(s);
|
|
||||||
n.push_str(&format!("{}{}", sani.len(), sani));
|
|
||||||
}
|
|
||||||
|
|
||||||
// First, connect each component with <len, name> pairs.
|
|
||||||
for data in path {
|
|
||||||
push(&mut n, &data);
|
|
||||||
}
|
|
||||||
|
|
||||||
push(&mut n, hash);
|
|
||||||
|
|
||||||
n.push('E'); // End name-sequence.
|
|
||||||
n
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -771,6 +771,10 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
|
||||||
type TyLayout = TyLayout<'tcx>;
|
type TyLayout = TyLayout<'tcx>;
|
||||||
|
|
||||||
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
|
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
|
||||||
|
if let Some(&layout) = self.tcx().layout_cache.borrow().get(&ty) {
|
||||||
|
return TyLayout { ty: ty, layout: layout, variant_index: None };
|
||||||
|
}
|
||||||
|
|
||||||
self.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| {
|
self.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| {
|
||||||
infcx.layout_of(ty).unwrap_or_else(|e| {
|
infcx.layout_of(ty).unwrap_or_else(|e| {
|
||||||
match e {
|
match e {
|
||||||
|
@ -781,6 +785,10 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
|
self.tcx().normalize_associated_type(&ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> {
|
impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> {
|
||||||
|
@ -789,6 +797,10 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> {
|
||||||
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
|
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
|
||||||
self.shared.layout_of(ty)
|
self.shared.layout_of(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
|
self.shared.normalize_projections(ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'a, 'tcx>);
|
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'a, 'tcx>);
|
||||||
|
|
|
@ -708,7 +708,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||||
let tr_lvalue = self.const_lvalue(lvalue, span)?;
|
let tr_lvalue = self.const_lvalue(lvalue, span)?;
|
||||||
|
|
||||||
let ty = tr_lvalue.ty;
|
let ty = tr_lvalue.ty;
|
||||||
let ref_ty = tcx.mk_ref(tcx.mk_region(ty::ReErased),
|
let ref_ty = tcx.mk_ref(tcx.types.re_erased,
|
||||||
ty::TypeAndMut { ty: ty, mutbl: bk.to_mutbl_lossy() });
|
ty::TypeAndMut { ty: ty, mutbl: bk.to_mutbl_lossy() });
|
||||||
|
|
||||||
let base = match tr_lvalue.base {
|
let base = match tr_lvalue.base {
|
||||||
|
|
|
@ -329,7 +329,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
|
|
||||||
let ty = tr_lvalue.ty.to_ty(bcx.tcx());
|
let ty = tr_lvalue.ty.to_ty(bcx.tcx());
|
||||||
let ref_ty = bcx.tcx().mk_ref(
|
let ref_ty = bcx.tcx().mk_ref(
|
||||||
bcx.tcx().mk_region(ty::ReErased),
|
bcx.tcx().types.re_erased,
|
||||||
ty::TypeAndMut { ty: ty, mutbl: bk.to_mutbl_lossy() }
|
ty::TypeAndMut { ty: ty, mutbl: bk.to_mutbl_lossy() }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let r = match tcx.named_region_map.defs.get(&lifetime.id) {
|
let r = match tcx.named_region_map.defs.get(&lifetime.id) {
|
||||||
Some(&rl::Region::Static) => {
|
Some(&rl::Region::Static) => {
|
||||||
tcx.mk_region(ty::ReStatic)
|
tcx.types.re_static
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(&rl::Region::LateBound(debruijn, id)) => {
|
Some(&rl::Region::LateBound(debruijn, id)) => {
|
||||||
|
@ -171,7 +171,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
.emit();
|
.emit();
|
||||||
|
|
||||||
return Substs::for_item(tcx, def_id, |_, _| {
|
return Substs::for_item(tcx, def_id, |_, _| {
|
||||||
tcx.mk_region(ty::ReStatic)
|
tcx.types.re_static
|
||||||
}, |_, _| {
|
}, |_, _| {
|
||||||
tcx.types.err
|
tcx.types.err
|
||||||
});
|
});
|
||||||
|
@ -254,7 +254,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
if let Some(lifetime) = lifetimes.get(i) {
|
if let Some(lifetime) = lifetimes.get(i) {
|
||||||
self.ast_region_to_region(lifetime, Some(def))
|
self.ast_region_to_region(lifetime, Some(def))
|
||||||
} else {
|
} else {
|
||||||
tcx.mk_region(ty::ReStatic)
|
tcx.types.re_static
|
||||||
}
|
}
|
||||||
}, |def, substs| {
|
}, |def, substs| {
|
||||||
let i = def.index as usize;
|
let i = def.index as usize;
|
||||||
|
@ -715,7 +715,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
span_err!(tcx.sess, span, E0228,
|
span_err!(tcx.sess, span, E0228,
|
||||||
"the lifetime bound for this object type cannot be deduced \
|
"the lifetime bound for this object type cannot be deduced \
|
||||||
from context; please supply an explicit bound");
|
from context; please supply an explicit bound");
|
||||||
tcx.mk_region(ty::ReStatic)
|
tcx.types.re_static
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1357,7 +1357,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
// If any of the derived region bounds are 'static, that is always
|
// If any of the derived region bounds are 'static, that is always
|
||||||
// the best choice.
|
// the best choice.
|
||||||
if derived_region_bounds.iter().any(|&r| ty::ReStatic == *r) {
|
if derived_region_bounds.iter().any(|&r| ty::ReStatic == *r) {
|
||||||
return Some(tcx.mk_region(ty::ReStatic));
|
return Some(tcx.types.re_static);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine whether there is exactly one unique region in the set
|
// Determine whether there is exactly one unique region in the set
|
||||||
|
|
|
@ -55,7 +55,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
let expected_ty = self.structurally_resolved_type(pat.span, expected);
|
let expected_ty = self.structurally_resolved_type(pat.span, expected);
|
||||||
if let ty::TyRef(_, mt) = expected_ty.sty {
|
if let ty::TyRef(_, mt) = expected_ty.sty {
|
||||||
if let ty::TySlice(_) = mt.ty.sty {
|
if let ty::TySlice(_) = mt.ty.sty {
|
||||||
pat_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic),
|
pat_ty = tcx.mk_imm_ref(tcx.types.re_static,
|
||||||
tcx.mk_slice(tcx.types.u8))
|
tcx.mk_slice(tcx.types.u8))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -626,7 +626,7 @@ fn revise_self_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
let impl_self_orig = self_substs.region_for_def(def);
|
let impl_self_orig = self_substs.region_for_def(def);
|
||||||
let r = if let ty::Region::ReEarlyBound(ref ebr) = *impl_self_orig {
|
let r = if let ty::Region::ReEarlyBound(ref ebr) = *impl_self_orig {
|
||||||
if impl_bindings.region_param(ebr).pure_wrt_drop {
|
if impl_bindings.region_param(ebr).pure_wrt_drop {
|
||||||
tcx.mk_region(ty::ReStatic)
|
tcx.types.re_static
|
||||||
} else {
|
} else {
|
||||||
r_orig
|
r_orig
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let def_id = tcx.hir.local_def_id(it.id);
|
let def_id = tcx.hir.local_def_id(it.id);
|
||||||
|
|
||||||
let substs = Substs::for_item(tcx, def_id,
|
let substs = Substs::for_item(tcx, def_id,
|
||||||
|_, _| tcx.mk_region(ty::ReErased),
|
|_, _| tcx.types.re_erased,
|
||||||
|def, _| tcx.mk_param_from_def(def));
|
|def, _| tcx.mk_param_from_def(def));
|
||||||
|
|
||||||
let fty = tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig(
|
let fty = tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig(
|
||||||
|
|
|
@ -1063,7 +1063,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// In general, during probing we erase regions. See
|
// In general, during probing we erase regions. See
|
||||||
// `impl_self_ty()` for an explanation.
|
// `impl_self_ty()` for an explanation.
|
||||||
let region = tcx.mk_region(ty::ReErased);
|
let region = tcx.types.re_erased;
|
||||||
|
|
||||||
// Search through mutabilities in order to find one where pick works:
|
// Search through mutabilities in order to find one where pick works:
|
||||||
[hir::MutImmutable, hir::MutMutable]
|
[hir::MutImmutable, hir::MutMutable]
|
||||||
|
@ -1325,7 +1325,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
// In general, during probe we erase regions. See
|
// In general, during probe we erase regions. See
|
||||||
// `impl_self_ty()` for an explanation.
|
// `impl_self_ty()` for an explanation.
|
||||||
self.tcx.mk_region(ty::ReErased)
|
self.tcx.types.re_erased
|
||||||
}
|
}
|
||||||
}, |def, cur_substs| {
|
}, |def, cur_substs| {
|
||||||
let i = def.index as usize;
|
let i = def.index as usize;
|
||||||
|
@ -1345,7 +1345,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let substs = Substs::for_item(self.tcx,
|
let substs = Substs::for_item(self.tcx,
|
||||||
impl_def_id,
|
impl_def_id,
|
||||||
|_, _| self.tcx.mk_region(ty::ReErased),
|
|_, _| self.tcx.types.re_erased,
|
||||||
|_, _| self.next_ty_var(
|
|_, _| self.next_ty_var(
|
||||||
TypeVariableOrigin::SubstitutionPlaceholder(
|
TypeVariableOrigin::SubstitutionPlaceholder(
|
||||||
self.tcx.def_span(impl_def_id))));
|
self.tcx.def_span(impl_def_id))));
|
||||||
|
|
|
@ -1954,7 +1954,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
//
|
//
|
||||||
// FIXME(#27579) all uses of this should be migrated to register_wf_obligation eventually
|
// FIXME(#27579) all uses of this should be migrated to register_wf_obligation eventually
|
||||||
let cause = traits::ObligationCause::new(span, self.body_id, code);
|
let cause = traits::ObligationCause::new(span, self.body_id, code);
|
||||||
self.register_region_obligation(ty, self.tcx.mk_region(ty::ReEmpty), cause);
|
self.register_region_obligation(ty, self.tcx.types.re_empty, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Registers obligations that all types appearing in `substs` are well-formed.
|
/// Registers obligations that all types appearing in `substs` are well-formed.
|
||||||
|
@ -2513,7 +2513,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
match lit.node {
|
match lit.node {
|
||||||
ast::LitKind::Str(..) => tcx.mk_static_str(),
|
ast::LitKind::Str(..) => tcx.mk_static_str(),
|
||||||
ast::LitKind::ByteStr(ref v) => {
|
ast::LitKind::ByteStr(ref v) => {
|
||||||
tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic),
|
tcx.mk_imm_ref(tcx.types.re_static,
|
||||||
tcx.mk_array(tcx.types.u8, v.len()))
|
tcx.mk_array(tcx.types.u8, v.len()))
|
||||||
}
|
}
|
||||||
ast::LitKind::Byte(_) => tcx.types.u8,
|
ast::LitKind::Byte(_) => tcx.types.u8,
|
||||||
|
|
|
@ -288,8 +288,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
let outside_ty = gcx.fold_regions(&inside_ty, &mut false, |r, _| {
|
let outside_ty = gcx.fold_regions(&inside_ty, &mut false, |r, _| {
|
||||||
match *r {
|
match *r {
|
||||||
// 'static is valid everywhere.
|
// 'static is valid everywhere.
|
||||||
ty::ReStatic |
|
ty::ReStatic => gcx.types.re_static,
|
||||||
ty::ReEmpty => gcx.mk_region(*r),
|
ty::ReEmpty => gcx.types.re_empty,
|
||||||
|
|
||||||
// Free regions that come from early-bound regions are valid.
|
// Free regions that come from early-bound regions are valid.
|
||||||
ty::ReFree(ty::FreeRegion {
|
ty::ReFree(ty::FreeRegion {
|
||||||
|
@ -307,7 +307,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||||
span_err!(self.tcx().sess, span, E0564,
|
span_err!(self.tcx().sess, span, E0564,
|
||||||
"only named lifetimes are allowed in `impl Trait`, \
|
"only named lifetimes are allowed in `impl Trait`, \
|
||||||
but `{}` was found in the type `{}`", r, inside_ty);
|
but `{}` was found in the type `{}`", r, inside_ty);
|
||||||
gcx.mk_region(ty::ReStatic)
|
gcx.types.re_static
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ReVar(_) |
|
ty::ReVar(_) |
|
||||||
|
@ -526,7 +526,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Resolver<'cx, 'gcx, 'tcx> {
|
||||||
match self.infcx.fully_resolve(&r) {
|
match self.infcx.fully_resolve(&r) {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
self.tcx.mk_region(ty::ReStatic)
|
self.tcx.types.re_static
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,7 @@ pub fn provide(providers: &mut Providers) {
|
||||||
trait_def,
|
trait_def,
|
||||||
adt_def,
|
adt_def,
|
||||||
impl_trait_ref,
|
impl_trait_ref,
|
||||||
|
impl_polarity,
|
||||||
is_foreign_item,
|
is_foreign_item,
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
|
@ -1133,6 +1134,16 @@ fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn impl_polarity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
def_id: DefId)
|
||||||
|
-> hir::ImplPolarity {
|
||||||
|
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
|
||||||
|
match tcx.hir.expect_item(node_id).node {
|
||||||
|
hir::ItemImpl(_, polarity, ..) => polarity,
|
||||||
|
ref item => bug!("trait_impl_polarity: {:?} not an impl", item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Is it marked with ?Sized
|
// Is it marked with ?Sized
|
||||||
fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
|
fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
|
||||||
ast_bounds: &[hir::TyParamBound],
|
ast_bounds: &[hir::TyParamBound],
|
||||||
|
|
|
@ -36,7 +36,7 @@ pub fn droppy() {
|
||||||
// CHECK-NOT: call{{.*}}drop{{.*}}SomeUniqueName
|
// CHECK-NOT: call{{.*}}drop{{.*}}SomeUniqueName
|
||||||
// CHECK: invoke{{.*}}drop{{.*}}SomeUniqueName
|
// CHECK: invoke{{.*}}drop{{.*}}SomeUniqueName
|
||||||
// CHECK: invoke{{.*}}drop{{.*}}SomeUniqueName
|
// CHECK: invoke{{.*}}drop{{.*}}SomeUniqueName
|
||||||
// CHECK: invoke{{.*}}drop{{.*}}SomeUniqueName
|
// CHECK: call{{.*}}drop{{.*}}SomeUniqueName
|
||||||
// CHECK-NOT: {{(call|invoke).*}}drop{{.*}}SomeUniqueName
|
// CHECK-NOT: {{(call|invoke).*}}drop{{.*}}SomeUniqueName
|
||||||
// The next line checks for the } that ends the function definition
|
// The next line checks for the } that ends the function definition
|
||||||
// CHECK-LABEL: {{^[}]}}
|
// CHECK-LABEL: {{^[}]}}
|
||||||
|
|
|
@ -37,5 +37,6 @@ pub fn test() {
|
||||||
// CHECK: bitcast{{.*}}personalityslot
|
// CHECK: bitcast{{.*}}personalityslot
|
||||||
// CHECK-NEXT: call void @llvm.lifetime.start
|
// CHECK-NEXT: call void @llvm.lifetime.start
|
||||||
might_unwind();
|
might_unwind();
|
||||||
|
let _t = S;
|
||||||
might_unwind();
|
might_unwind();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue