Skip to content

Commit

Permalink
Auto merge of #55665 - eddyb:by-ref-layout-of, r=oli-obk
Browse files Browse the repository at this point in the history
rustc_target: pass contexts by reference, not value.

`LayoutOf` now takes `&self` instead of `self`, and so does every method generic over a context that implements `LayoutOf` and/or other traits, like `HasDataLayout`, `HasTyCtxt`, etc.

Originally using by-value `Copy` types was relevant because `TyCtxt` was one of those types, but now `TyCtxt::layout_of` is separate from `LayoutOf`, and `TyCtxt` is not an often used layout context.

Passing these context by reference is a lot nicer for miri, which has `self: &mut EvalContext`, and needed `f(&self)` (that is, creating `&&mut EvalContext` references) for layout purposes.
Now, the `&mut EvalContext` can be passed to a function expecting `&C`, directly.

This should help with #54012 / #55627 (to not need `where &'a T::Cx: LayoutOf` bounds).

r? @nikomatsakis or @oli-obk or @nagisa cc @sunfishcode
  • Loading branch information
bors committed Nov 4, 2018
2 parents ca4fa6f + d00d42d commit e6c5cf9
Show file tree
Hide file tree
Showing 38 changed files with 175 additions and 214 deletions.
4 changes: 2 additions & 2 deletions src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,11 +783,11 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
}
}

impl<'a, 'tcx> LayoutOf for &'a LateContext<'a, 'tcx> {
impl<'a, 'tcx> LayoutOf for LateContext<'a, 'tcx> {
type Ty = Ty<'tcx>;
type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;

fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
self.tcx.layout_of(self.param_env.and(ty))
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl<'a, 'tcx> ExprVisitor<'a, 'tcx> {
// `Option<typeof(function)>` to present a clearer error.
let from = unpack_option_like(self.tcx.global_tcx(), from);
if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (&from.sty, sk_to) {
if size_to == Pointer.size(self.tcx) {
if size_to == Pointer.size(&self.tcx) {
struct_span_err!(self.tcx.sess, span, E0591,
"can't transmute zero-sized type")
.note(&format!("source type: {}", from))
Expand Down
24 changes: 12 additions & 12 deletions src/librustc/mir/interpret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,18 +86,18 @@ pub trait PointerArithmetic: layout::HasDataLayout {
// These are not supposed to be overridden.

#[inline(always)]
fn pointer_size(self) -> Size {
fn pointer_size(&self) -> Size {
self.data_layout().pointer_size
}

//// Trunace the given value to the pointer size; also return whether there was an overflow
fn truncate_to_ptr(self, val: u128) -> (u64, bool) {
fn truncate_to_ptr(&self, val: u128) -> (u64, bool) {
let max_ptr_plus_1 = 1u128 << self.pointer_size().bits();
((val % max_ptr_plus_1) as u64, val >= max_ptr_plus_1)
}

// Overflow checking only works properly on the range from -u64 to +u64.
fn overflowing_signed_offset(self, val: u64, i: i128) -> (u64, bool) {
fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) {
// FIXME: is it possible to over/underflow here?
if i < 0 {
// trickery to ensure that i64::min_value() works fine
Expand All @@ -109,23 +109,23 @@ pub trait PointerArithmetic: layout::HasDataLayout {
}
}

fn overflowing_offset(self, val: u64, i: u64) -> (u64, bool) {
fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool) {
let (res, over1) = val.overflowing_add(i);
let (res, over2) = self.truncate_to_ptr(res as u128);
(res, over1 || over2)
}

fn signed_offset<'tcx>(self, val: u64, i: i64) -> EvalResult<'tcx, u64> {
fn signed_offset<'tcx>(&self, val: u64, i: i64) -> EvalResult<'tcx, u64> {
let (res, over) = self.overflowing_signed_offset(val, i as i128);
if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
}

fn offset<'tcx>(self, val: u64, i: u64) -> EvalResult<'tcx, u64> {
fn offset<'tcx>(&self, val: u64, i: u64) -> EvalResult<'tcx, u64> {
let (res, over) = self.overflowing_offset(val, i);
if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
}

fn wrapping_signed_offset(self, val: u64, i: i64) -> u64 {
fn wrapping_signed_offset(&self, val: u64, i: i64) -> u64 {
self.overflowing_signed_offset(val, i as i128).0
}
}
Expand Down Expand Up @@ -176,33 +176,33 @@ impl<'tcx, Tag> Pointer<Tag> {
Pointer { alloc_id, offset, tag }
}

pub fn wrapping_signed_offset(self, i: i64, cx: impl HasDataLayout) -> Self {
pub fn wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self {
Pointer::new_with_tag(
self.alloc_id,
Size::from_bytes(cx.data_layout().wrapping_signed_offset(self.offset.bytes(), i)),
self.tag,
)
}

pub fn overflowing_signed_offset(self, i: i128, cx: impl HasDataLayout) -> (Self, bool) {
pub fn overflowing_signed_offset(self, i: i128, cx: &impl HasDataLayout) -> (Self, bool) {
let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i);
(Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
}

pub fn signed_offset(self, i: i64, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
pub fn signed_offset(self, i: i64, cx: &impl HasDataLayout) -> EvalResult<'tcx, Self> {
Ok(Pointer::new_with_tag(
self.alloc_id,
Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?),
self.tag,
))
}

pub fn overflowing_offset(self, i: Size, cx: impl HasDataLayout) -> (Self, bool) {
pub fn overflowing_offset(self, i: Size, cx: &impl HasDataLayout) -> (Self, bool) {
let (res, over) = cx.data_layout().overflowing_offset(self.offset.bytes(), i.bytes());
(Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
}

pub fn offset(self, i: Size, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
pub fn offset(self, i: Size, cx: &impl HasDataLayout) -> EvalResult<'tcx, Self> {
Ok(Pointer::new_with_tag(
self.alloc_id,
Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?),
Expand Down
40 changes: 20 additions & 20 deletions src/librustc/mir/interpret/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl<'tcx> ConstValue<'tcx> {
pub fn new_slice(
val: Scalar,
len: u64,
cx: impl HasDataLayout
cx: &impl HasDataLayout
) -> Self {
ConstValue::ScalarPair(val, Scalar::Bits {
bits: len as u128,
Expand Down Expand Up @@ -121,7 +121,7 @@ impl<'tcx, Tag> Scalar<Tag> {
}

#[inline]
pub fn ptr_null(cx: impl HasDataLayout) -> Self {
pub fn ptr_null(cx: &impl HasDataLayout) -> Self {
Scalar::Bits {
bits: 0,
size: cx.data_layout().pointer_size.bytes() as u8,
Expand All @@ -134,52 +134,52 @@ impl<'tcx, Tag> Scalar<Tag> {
}

#[inline]
pub fn ptr_signed_offset(self, i: i64, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
let layout = cx.data_layout();
pub fn ptr_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> EvalResult<'tcx, Self> {
let dl = cx.data_layout();
match self {
Scalar::Bits { bits, size } => {
assert_eq!(size as u64, layout.pointer_size.bytes());
assert_eq!(size as u64, dl.pointer_size.bytes());
Ok(Scalar::Bits {
bits: layout.signed_offset(bits as u64, i)? as u128,
bits: dl.signed_offset(bits as u64, i)? as u128,
size,
})
}
Scalar::Ptr(ptr) => ptr.signed_offset(i, layout).map(Scalar::Ptr),
Scalar::Ptr(ptr) => ptr.signed_offset(i, dl).map(Scalar::Ptr),
}
}

#[inline]
pub fn ptr_offset(self, i: Size, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
let layout = cx.data_layout();
pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> EvalResult<'tcx, Self> {
let dl = cx.data_layout();
match self {
Scalar::Bits { bits, size } => {
assert_eq!(size as u64, layout.pointer_size.bytes());
assert_eq!(size as u64, dl.pointer_size.bytes());
Ok(Scalar::Bits {
bits: layout.offset(bits as u64, i.bytes())? as u128,
bits: dl.offset(bits as u64, i.bytes())? as u128,
size,
})
}
Scalar::Ptr(ptr) => ptr.offset(i, layout).map(Scalar::Ptr),
Scalar::Ptr(ptr) => ptr.offset(i, dl).map(Scalar::Ptr),
}
}

#[inline]
pub fn ptr_wrapping_signed_offset(self, i: i64, cx: impl HasDataLayout) -> Self {
let layout = cx.data_layout();
pub fn ptr_wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self {
let dl = cx.data_layout();
match self {
Scalar::Bits { bits, size } => {
assert_eq!(size as u64, layout.pointer_size.bytes());
assert_eq!(size as u64, dl.pointer_size.bytes());
Scalar::Bits {
bits: layout.wrapping_signed_offset(bits as u64, i) as u128,
bits: dl.wrapping_signed_offset(bits as u64, i) as u128,
size,
}
}
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.wrapping_signed_offset(i, layout)),
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.wrapping_signed_offset(i, dl)),
}
}

#[inline]
pub fn is_null_ptr(self, cx: impl HasDataLayout) -> bool {
pub fn is_null_ptr(self, cx: &impl HasDataLayout) -> bool {
match self {
Scalar::Bits { bits, size } => {
assert_eq!(size as u64, cx.data_layout().pointer_size.bytes());
Expand Down Expand Up @@ -301,7 +301,7 @@ impl<'tcx, Tag> Scalar<Tag> {
Ok(b as u64)
}

pub fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64> {
pub fn to_usize(self, cx: &impl HasDataLayout) -> EvalResult<'static, u64> {
let b = self.to_bits(cx.data_layout().pointer_size)?;
assert_eq!(b as u64 as u128, b);
Ok(b as u64)
Expand Down Expand Up @@ -331,7 +331,7 @@ impl<'tcx, Tag> Scalar<Tag> {
Ok(b as i64)
}

pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64> {
pub fn to_isize(self, cx: &impl HasDataLayout) -> EvalResult<'static, i64> {
let b = self.to_bits(cx.data_layout().pointer_size)?;
let b = sign_extend(b, cx.data_layout().pointer_size) as i128;
assert_eq!(b as i64 as i128, b);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
));
let tcx = self.tcx;
if let Some(len) = len.val.try_to_scalar().and_then(|scalar| {
scalar.to_usize(tcx).ok()
scalar.to_usize(&tcx).ok()
}) {
flags.push((
"_Self".to_owned(),
Expand Down
29 changes: 14 additions & 15 deletions src/librustc/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub use rustc_target::abi::*;

pub trait IntegerExt {
fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, signed: bool) -> Ty<'tcx>;
fn from_attr<C: HasDataLayout>(cx: C, ity: attr::IntType) -> Integer;
fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer;
fn repr_discr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
ty: Ty<'tcx>,
repr: &ReprOptions,
Expand All @@ -56,7 +56,7 @@ impl IntegerExt for Integer {
}

/// Get the Integer type from an attr::IntType.
fn from_attr<C: HasDataLayout>(cx: C, ity: attr::IntType) -> Integer {
fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer {
let dl = cx.data_layout();

match ity {
Expand Down Expand Up @@ -92,7 +92,7 @@ impl IntegerExt for Integer {
let min_default = I8;

if let Some(ity) = repr.int {
let discr = Integer::from_attr(tcx, ity);
let discr = Integer::from_attr(&tcx, ity);
let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
if discr < fit {
bug!("Integer::repr_discr: `#[repr]` hint too small for \
Expand Down Expand Up @@ -202,14 +202,13 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
};
}

#[derive(Copy, Clone)]
pub struct LayoutCx<'tcx, C> {
pub tcx: C,
pub param_env: ty::ParamEnv<'tcx>
}

impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
fn layout_raw_uncached(self, ty: Ty<'tcx>)
fn layout_raw_uncached(&self, ty: Ty<'tcx>)
-> Result<&'tcx LayoutDetails, LayoutError<'tcx>> {
let tcx = self.tcx;
let param_env = self.param_env;
Expand Down Expand Up @@ -899,7 +898,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {

let (mut min, mut max) = (i128::max_value(), i128::min_value());
let discr_type = def.repr.discr_type();
let bits = Integer::from_attr(tcx, discr_type).size().bits();
let bits = Integer::from_attr(self, discr_type).size().bits();
for (i, discr) in def.discriminants(tcx).enumerate() {
if variants[i].iter().any(|f| f.abi.is_uninhabited()) {
continue;
Expand Down Expand Up @@ -1141,7 +1140,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
/// This is invoked by the `layout_raw` query to record the final
/// layout of each type.
#[inline]
fn record_layout_for_printing(self, layout: TyLayout<'tcx>) {
fn record_layout_for_printing(&self, layout: TyLayout<'tcx>) {
// If we are running with `-Zprint-type-sizes`, record layouts for
// dumping later. Ignore layouts that are done with non-empty
// environments or non-monomorphic layouts, as the user only wants
Expand All @@ -1158,7 +1157,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
self.record_layout_for_printing_outlined(layout)
}

fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) {
fn record_layout_for_printing_outlined(&self, layout: TyLayout<'tcx>) {
// (delay format until we actually need it)
let record = |kind, packed, opt_discr_size, variants| {
let type_desc = format!("{:?}", layout.ty);
Expand Down Expand Up @@ -1478,7 +1477,7 @@ impl<'a, 'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {

/// Computes the layout of a type. Note that this implicitly
/// executes in "reveal all" mode.
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
let param_env = self.param_env.with_reveal_all();
let ty = self.tcx.normalize_erasing_regions(param_env, ty);
let details = self.tcx.layout_raw(param_env.and(ty))?;
Expand All @@ -1505,7 +1504,7 @@ impl<'a, 'tcx> LayoutOf for LayoutCx<'tcx, ty::query::TyCtxtAt<'a, 'tcx, 'tcx>>

/// Computes the layout of a type. Note that this implicitly
/// executes in "reveal all" mode.
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
let param_env = self.param_env.with_reveal_all();
let ty = self.tcx.normalize_erasing_regions(param_env, ty);
let details = self.tcx.layout_raw(param_env.and(ty))?;
Expand Down Expand Up @@ -1563,7 +1562,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
where C: LayoutOf<Ty = Ty<'tcx>> + HasTyCtxt<'tcx>,
C::TyLayout: MaybeResult<TyLayout<'tcx>>
{
fn for_variant(this: TyLayout<'tcx>, cx: C, variant_index: usize) -> TyLayout<'tcx> {
fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: usize) -> TyLayout<'tcx> {
let details = match this.variants {
Variants::Single { index } if index == variant_index => this.details,

Expand Down Expand Up @@ -1602,7 +1601,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
}
}

fn field(this: TyLayout<'tcx>, cx: C, i: usize) -> C::TyLayout {
fn field(this: TyLayout<'tcx>, cx: &C, i: usize) -> C::TyLayout {
let tcx = cx.tcx();
cx.layout_of(match this.ty.sty {
ty::Bool |
Expand Down Expand Up @@ -1699,7 +1698,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
Variants::Tagged { tag: ref discr, .. } |
Variants::NicheFilling { niche: ref discr, .. } => {
assert_eq!(i, 0);
let layout = LayoutDetails::scalar(tcx, discr.clone());
let layout = LayoutDetails::scalar(cx, discr.clone());
return MaybeResult::from_ok(TyLayout {
details: tcx.intern_layout(layout),
ty: discr.value.to_ty(tcx)
Expand All @@ -1725,7 +1724,7 @@ struct Niche {
impl Niche {
fn reserve<'a, 'tcx>(
&self,
cx: LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>>,
cx: &LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>>,
count: u128,
) -> Option<(u128, Scalar)> {
if count > self.available {
Expand All @@ -1745,7 +1744,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
/// Find the offset of a niche leaf field, starting from
/// the given type and recursing through aggregates.
// FIXME(eddyb) traverse already optimized enums.
fn find_niche(self, layout: TyLayout<'tcx>) -> Result<Option<Niche>, LayoutError<'tcx>> {
fn find_niche(&self, layout: TyLayout<'tcx>) -> Result<Option<Niche>, LayoutError<'tcx>> {
let scalar_niche = |scalar: &Scalar, offset| {
let Scalar { value, valid_range: ref v } = *scalar;

Expand Down
6 changes: 3 additions & 3 deletions src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
match self.ty.sty {
ty::Int(ity) => {
let bits = ty::tls::with(|tcx| {
Integer::from_attr(tcx, SignedInt(ity)).size().bits()
Integer::from_attr(&tcx, SignedInt(ity)).size().bits()
});
let x = self.val as i128;
// sign extend the raw representation to be an i128
Expand All @@ -62,8 +62,8 @@ impl<'tcx> Discr<'tcx> {
}
pub fn checked_add<'a, 'gcx>(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, n: u128) -> (Self, bool) {
let (int, signed) = match self.ty.sty {
Int(ity) => (Integer::from_attr(tcx, SignedInt(ity)), true),
Uint(uty) => (Integer::from_attr(tcx, UnsignedInt(uty)), false),
Int(ity) => (Integer::from_attr(&tcx, SignedInt(ity)), true),
Uint(uty) => (Integer::from_attr(&tcx, UnsignedInt(uty)), false),
_ => bug!("non integer discriminant"),
};

Expand Down
Loading

0 comments on commit e6c5cf9

Please sign in to comment.