Skip to content

Commit

Permalink
Avoid looking at the internals of Interned directly
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Apr 8, 2022
1 parent 2e0ef70 commit 25d6f8e
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 199 deletions.
35 changes: 17 additions & 18 deletions compiler/rustc_infer/src/infer/outlives/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::infer::free_regions::FreeRegionMap;
use crate::infer::{GenericKind, InferCtxt};
use crate::traits::query::OutlivesBound;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::intern::Interned;
use rustc_hir as hir;
use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region};

Expand Down Expand Up @@ -164,12 +163,6 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
for outlives_bound in outlives_bounds {
debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound);
match outlives_bound {
OutlivesBound::RegionSubRegion(
r_a @ (Region(Interned(ReEarlyBound(_), _)) | Region(Interned(ReFree(_), _))),
Region(Interned(ReVar(vid_b), _)),
) => {
infcx.expect("no infcx provided but region vars found").add_given(r_a, *vid_b);
}
OutlivesBound::RegionSubParam(r_a, param_b) => {
self.region_bound_pairs_accum.push((r_a, GenericKind::Param(param_b)));
}
Expand All @@ -178,17 +171,23 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
.push((r_a, GenericKind::Projection(projection_b)));
}
OutlivesBound::RegionSubRegion(r_a, r_b) => {
// In principle, we could record (and take
// advantage of) every relationship here, but
// we are also free not to -- it simply means
// strictly less that we can successfully type
// check. Right now we only look for things
// relationships between free regions. (It may
// also be that we should revise our inference
// system to be more general and to make use
// of *every* relationship that arises here,
// but presently we do not.)
self.free_region_map.relate_regions(r_a, r_b);
if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) {
infcx
.expect("no infcx provided but region vars found")
.add_given(r_a, vid_b);
} else {
// In principle, we could record (and take
// advantage of) every relationship here, but
// we are also free not to -- it simply means
// strictly less that we can successfully type
// check. Right now we only look for things
// relationships between free regions. (It may
// also be that we should revise our inference
// system to be more general and to make use
// of *every* relationship that arises here,
// but presently we do not.)
self.free_region_map.relate_regions(r_a, r_b);
}
}
}
}
Expand Down
68 changes: 28 additions & 40 deletions compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::ty::subst::Subst;
use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable};
use rustc_ast as ast;
use rustc_attr as attr;
use rustc_data_structures::intern::Interned;
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::BitSet;
Expand Down Expand Up @@ -503,42 +502,34 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
}

// Two non-ZST fields, and they're both scalars.
(
Some((
i,
&TyAndLayout {
layout: Layout(Interned(&LayoutS { abi: Abi::Scalar(a), .. }, _)),
..
},
)),
Some((
j,
&TyAndLayout {
layout: Layout(Interned(&LayoutS { abi: Abi::Scalar(b), .. }, _)),
..
},
)),
None,
) => {
// Order by the memory placement, not source order.
let ((i, a), (j, b)) =
if offsets[i] < offsets[j] { ((i, a), (j, b)) } else { ((j, b), (i, a)) };
let pair = self.scalar_pair(a, b);
let pair_offsets = match pair.fields {
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
assert_eq!(memory_index, &[0, 1]);
offsets
(Some((i, a)), Some((j, b)), None) => {
match (a.abi, b.abi) {
(Abi::Scalar(a), Abi::Scalar(b)) => {
// Order by the memory placement, not source order.
let ((i, a), (j, b)) = if offsets[i] < offsets[j] {
((i, a), (j, b))
} else {
((j, b), (i, a))
};
let pair = self.scalar_pair(a, b);
let pair_offsets = match pair.fields {
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
assert_eq!(memory_index, &[0, 1]);
offsets
}
_ => bug!(),
};
if offsets[i] == pair_offsets[0]
&& offsets[j] == pair_offsets[1]
&& align == pair.align
&& size == pair.size
{
// We can use `ScalarPair` only when it matches our
// already computed layout (including `#[repr(C)]`).
abi = pair.abi;
}
}
_ => bug!(),
};
if offsets[i] == pair_offsets[0]
&& offsets[j] == pair_offsets[1]
&& align == pair.align
&& size == pair.size
{
// We can use `ScalarPair` only when it matches our
// already computed layout (including `#[repr(C)]`).
abi = pair.abi;
_ => {}
}
}

Expand Down Expand Up @@ -788,10 +779,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
}

// Extract the number of elements from the layout of the array field:
let Ok(TyAndLayout {
layout: Layout(Interned(LayoutS { fields: FieldsShape::Array { count, .. }, .. }, _)),
..
}) = self.layout_of(f0_ty) else {
let FieldsShape::Array { count, .. } = self.layout_of(f0_ty)?.layout.fields() else {
return Err(LayoutError::Unknown(ty));
};

Expand Down
178 changes: 76 additions & 102 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable};
use rustc_apfloat::ieee::{Double, Single};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::intern::{Interned, WithStableHash};
use rustc_data_structures::sso::SsoHashSet;
use rustc_hir as hir;
use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
Expand Down Expand Up @@ -1263,71 +1262,52 @@ pub trait PrettyPrinter<'tcx>:
let (alloc_id, offset) = ptr.into_parts();
match ty.kind() {
// Byte strings (&[u8; N])
ty::Ref(
_,
Ty(Interned(
WithStableHash {
internee:
ty::TyS {
kind:
ty::Array(
Ty(Interned(
WithStableHash {
internee:
ty::TyS { kind: ty::Uint(ty::UintTy::U8), .. },
..
},
_,
)),
ty::Const(Interned(
ty::ConstS {
val: ty::ConstKind::Value(ConstValue::Scalar(int)),
..
},
_,
)),
),
..
},
..
},
_,
)),
_,
) => match self.tcx().get_global_alloc(alloc_id) {
Some(GlobalAlloc::Memory(alloc)) => {
let len = int.assert_bits(self.tcx().data_layout.pointer_size);
let range = AllocRange { start: offset, size: Size::from_bytes(len) };
if let Ok(byte_str) = alloc.inner().get_bytes(&self.tcx(), range) {
p!(pretty_print_byte_str(byte_str))
} else {
p!("<too short allocation>")
ty::Ref(_, inner, _) => {
if let ty::Array(elem, len) = inner.kind() {
if let ty::Uint(ty::UintTy::U8) = elem.kind() {
if let ty::ConstKind::Value(ConstValue::Scalar(int)) = len.val() {
match self.tcx().get_global_alloc(alloc_id) {
Some(GlobalAlloc::Memory(alloc)) => {
let len = int.assert_bits(self.tcx().data_layout.pointer_size);
let range =
AllocRange { start: offset, size: Size::from_bytes(len) };
if let Ok(byte_str) =
alloc.inner().get_bytes(&self.tcx(), range)
{
p!(pretty_print_byte_str(byte_str))
} else {
p!("<too short allocation>")
}
}
// FIXME: for statics and functions, we could in principle print more detail.
Some(GlobalAlloc::Static(def_id)) => {
p!(write("<static({:?})>", def_id))
}
Some(GlobalAlloc::Function(_)) => p!("<function>"),
None => p!("<dangling pointer>"),
}
return Ok(self);
}
}
}
// FIXME: for statics and functions, we could in principle print more detail.
Some(GlobalAlloc::Static(def_id)) => p!(write("<static({:?})>", def_id)),
Some(GlobalAlloc::Function(_)) => p!("<function>"),
None => p!("<dangling pointer>"),
},
}
ty::FnPtr(_) => {
// FIXME: We should probably have a helper method to share code with the "Byte strings"
// printing above (which also has to handle pointers to all sorts of things).
match self.tcx().get_global_alloc(alloc_id) {
Some(GlobalAlloc::Function(instance)) => {
self = self.typed_value(
|this| this.print_value_path(instance.def_id(), instance.substs),
|this| this.print_type(ty),
" as ",
)?;
}
_ => self = self.pretty_print_const_pointer(ptr, ty, print_ty)?,
if let Some(GlobalAlloc::Function(instance)) = self.tcx().get_global_alloc(alloc_id)
{
self = self.typed_value(
|this| this.print_value_path(instance.def_id(), instance.substs),
|this| this.print_type(ty),
" as ",
)?;
return Ok(self);
}
}
// Any pointer values not covered by a branch above
_ => {
self = self.pretty_print_const_pointer(ptr, ty, print_ty)?;
}
_ => {}
}
// Any pointer values not covered by a branch above
self = self.pretty_print_const_pointer(ptr, ty, print_ty)?;
Ok(self)
}

Expand Down Expand Up @@ -1448,39 +1428,31 @@ pub trait PrettyPrinter<'tcx>:

match (ct, ty.kind()) {
// Byte/string slices, printed as (byte) string literals.
(
ConstValue::Slice { data, start, end },
ty::Ref(
_,
Ty(Interned(
WithStableHash { internee: ty::TyS { kind: ty::Slice(t), .. }, .. },
_,
)),
_,
),
) if *t == u8_type => {
// The `inspect` here is okay since we checked the bounds, and there are
// no relocations (we have an active slice reference here). We don't use
// this result to affect interpreter execution.
let byte_str =
data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end);
self.pretty_print_byte_str(byte_str)
}
(
ConstValue::Slice { data, start, end },
ty::Ref(
_,
Ty(Interned(WithStableHash { internee: ty::TyS { kind: ty::Str, .. }, .. }, _)),
_,
),
) => {
// The `inspect` here is okay since we checked the bounds, and there are no
// relocations (we have an active `str` reference here). We don't use this
// result to affect interpreter execution.
let slice =
data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end);
p!(write("{:?}", String::from_utf8_lossy(slice)));
Ok(self)
(ConstValue::Slice { data, start, end }, ty::Ref(_, inner, _)) => {
match inner.kind() {
ty::Slice(t) => {
if *t == u8_type {
// The `inspect` here is okay since we checked the bounds, and there are
// no relocations (we have an active slice reference here). We don't use
// this result to affect interpreter execution.
let byte_str = data
.inner()
.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
return self.pretty_print_byte_str(byte_str);
}
}
ty::Str => {
// The `inspect` here is okay since we checked the bounds, and there are no
// relocations (we have an active `str` reference here). We don't use this
// result to affect interpreter execution.
let slice = data
.inner()
.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
p!(write("{:?}", String::from_utf8_lossy(slice)));
return Ok(self);
}
_ => {}
}
}
(ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
let n = n.val().try_to_bits(self.tcx().data_layout.pointer_size).unwrap();
Expand All @@ -1490,7 +1462,7 @@ pub trait PrettyPrinter<'tcx>:
let byte_str = alloc.inner().get_bytes(&self.tcx(), range).unwrap();
p!("*");
p!(pretty_print_byte_str(byte_str));
Ok(self)
return Ok(self);
}

// Aggregates, printed as array/tuple/struct/variant construction syntax.
Expand Down Expand Up @@ -1567,22 +1539,24 @@ pub trait PrettyPrinter<'tcx>:
_ => unreachable!(),
}

Ok(self)
return Ok(self);
}

(ConstValue::Scalar(scalar), _) => self.pretty_print_const_scalar(scalar, ty, print_ty),
(ConstValue::Scalar(scalar), _) => {
return self.pretty_print_const_scalar(scalar, ty, print_ty);
}

// FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
// their fields instead of just dumping the memory.
_ => {
// fallback
p!(write("{:?}", ct));
if print_ty {
p!(": ", print(ty));
}
Ok(self)
}
_ => {}
}

// fallback
p!(write("{:?}", ct));
if print_ty {
p!(": ", print(ty));
}
Ok(self)
}
}

Expand Down
Loading

0 comments on commit 25d6f8e

Please sign in to comment.