Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #57898

Merged
merged 14 commits into from
Jan 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2937,16 +2937,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
}

/// Given the DefId of an item, returns its MIR, borrowed immutably.
/// Returns None if there is no MIR for the DefId
pub fn maybe_optimized_mir(self, did: DefId) -> Option<&'gcx Mir<'gcx>> {
if self.is_mir_available(did) {
Some(self.optimized_mir(did))
} else {
None
}
}

/// Get the attributes of a definition.
pub fn get_attrs(self, did: DefId) -> Attributes<'gcx> {
if let Some(id) = self.hir().as_local_node_id(did) {
Expand Down
5 changes: 4 additions & 1 deletion src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use rustc_incremental;
use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::{self, CStore};
use rustc_mir as mir;
use rustc_passes::{self, ast_validation, hir_stats, loops, rvalue_promotion};
use rustc_passes::{self, ast_validation, hir_stats, loops, rvalue_promotion, layout_test};
use rustc_plugin as plugin;
use rustc_plugin::registry::Registry;
use rustc_privacy;
Expand Down Expand Up @@ -1287,6 +1287,9 @@ where
mir::transform::check_unsafety::check_unsafety(tcx, def_id)
}
});

time(sess, "layout testing", || layout_test::test_layout(tcx));

// Avoid overwhelming user with errors if type checking failed.
// I'm not sure how helpful this is, to be honest, but it avoids
// a
Expand Down
10 changes: 6 additions & 4 deletions src/librustc_lint/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use syntax::source_map;

use rustc::hir;

use rustc::mir::interpret::{sign_extend, truncate};

declare_lint! {
UNUSED_COMPARISONS,
Warn,
Expand Down Expand Up @@ -368,14 +370,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
let (t, actually) = match ty {
ty::Int(t) => {
let ity = attr::IntType::SignedInt(t);
let bits = layout::Integer::from_attr(&cx.tcx, ity).size().bits();
let actually = (val << (128 - bits)) as i128 >> (128 - bits);
let size = layout::Integer::from_attr(&cx.tcx, ity).size();
let actually = sign_extend(val, size) as i128;
(format!("{:?}", t), actually.to_string())
}
ty::Uint(t) => {
let ity = attr::IntType::UnsignedInt(t);
let bits = layout::Integer::from_attr(&cx.tcx, ity).size().bits();
let actually = (val << (128 - bits)) >> (128 - bits);
let size = layout::Integer::from_attr(&cx.tcx, ity).size();
let actually = truncate(val, size);
(format!("{:?}", t), actually.to_string())
}
_ => bug!(),
Expand Down
29 changes: 16 additions & 13 deletions src/librustc_mir/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,19 +340,22 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
ret: Option<mir::BasicBlock>,
) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>> {
debug!("eval_fn_call: {:?}", instance);
// Execution might have wandered off into other crates, so we cannot to a stability-
// sensitive check here. But we can at least rule out functions that are not const
// at all.
if !ecx.tcx.is_const_fn_raw(instance.def_id()) {
// Some functions we support even if they are non-const -- but avoid testing
// that for const fn! We certainly do *not* want to actually call the fn
// though, so be sure we return here.
return if ecx.hook_fn(instance, args, dest)? {
ecx.goto_block(ret)?; // fully evaluated and done
Ok(None)
} else {
err!(MachineError(format!("calling non-const function `{}`", instance)))
};
// Only check non-glue functions
if let ty::InstanceDef::Item(def_id) = instance.def {
// Execution might have wandered off into other crates, so we cannot to a stability-
// sensitive check here. But we can at least rule out functions that are not const
// at all.
if !ecx.tcx.is_const_fn_raw(def_id) {
// Some functions we support even if they are non-const -- but avoid testing
// that for const fn! We certainly do *not* want to actually call the fn
// though, so be sure we return here.
return if ecx.hook_fn(instance, args, dest)? {
ecx.goto_block(ret)?; // fully evaluated and done
Ok(None)
} else {
err!(MachineError(format!("calling non-const function `{}`", instance)))
};
}
}
// This is a const fn. Call it.
Ok(Some(match ecx.load_mir(instance.def) {
Expand Down
10 changes: 5 additions & 5 deletions src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
}
trace!("load mir {:?}", instance);
match instance {
ty::InstanceDef::Item(def_id) => {
self.tcx.maybe_optimized_mir(def_id).ok_or_else(||
EvalErrorKind::NoMirFor(self.tcx.item_path_str(def_id)).into()
)
}
ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) {
Ok(self.tcx.optimized_mir(did))
} else {
err!(NoMirFor(self.tcx.item_path_str(def_id)))
},
_ => Ok(self.tcx.instance_mir(instance)),
}
}
Expand Down
132 changes: 132 additions & 0 deletions src/librustc_passes/layout_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir::ItemKind;
use rustc::ty::layout::HasDataLayout;
use rustc::ty::layout::HasTyCtxt;
use rustc::ty::layout::LayoutOf;
use rustc::ty::layout::TargetDataLayout;
use rustc::ty::layout::TyLayout;
use rustc::ty::ParamEnv;
use rustc::ty::Ty;
use rustc::ty::TyCtxt;
use syntax::ast::Attribute;

pub fn test_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
if tcx.features().rustc_attrs {
// if the `rustc_attrs` feature is not enabled, don't bother testing layout
tcx.hir()
.krate()
.visit_all_item_likes(&mut VarianceTest { tcx });
}
}

struct VarianceTest<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
}

impl<'a, 'tcx> ItemLikeVisitor<'tcx> for VarianceTest<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
let item_def_id = self.tcx.hir().local_def_id(item.id);

if let ItemKind::Ty(..) = item.node {
for attr in self.tcx.get_attrs(item_def_id).iter() {
if attr.check_name("rustc_layout") {
self.dump_layout_of(item_def_id, item, attr);
}
}
}
}

fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) {}
fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) {}
}

impl<'a, 'tcx> VarianceTest<'a, 'tcx> {
fn dump_layout_of(&self, item_def_id: DefId, item: &hir::Item, attr: &Attribute) {
let tcx = self.tcx;
let param_env = self.tcx.param_env(item_def_id);
let ty = self.tcx.type_of(item_def_id);
match self.tcx.layout_of(param_env.and(ty)) {
Ok(ty_layout) => {
// Check out the `#[rustc_layout(..)]` attribute to tell what to dump.
// The `..` are the names of fields to dump.
let meta_items = attr.meta_item_list().unwrap_or_default();
for meta_item in meta_items {
let name = meta_item.word().map(|mi| mi.name().as_str());
let name = name.as_ref().map(|s| &s[..]).unwrap_or("");

match name {
"abi" => {
self.tcx
.sess
.span_err(item.span, &format!("abi: {:?}", ty_layout.abi));
}

"align" => {
self.tcx
.sess
.span_err(item.span, &format!("align: {:?}", ty_layout.align));
}

"size" => {
self.tcx
.sess
.span_err(item.span, &format!("size: {:?}", ty_layout.size));
}

"homogeneous_aggregate" => {
self.tcx.sess.span_err(
item.span,
&format!(
"homogeneous_aggregate: {:?}",
ty_layout
.homogeneous_aggregate(&UnwrapLayoutCx { tcx, param_env }),
),
);
}

_ => {
self.tcx.sess.span_err(
meta_item.span,
&format!("unrecognized field name `{}`", name),
);
}
}
}
}

Err(layout_error) => {
self.tcx
.sess
.span_err(item.span, &format!("layout error: {:?}", layout_error));
}
}
}
}

struct UnwrapLayoutCx<'me, 'tcx> {
tcx: TyCtxt<'me, 'tcx, 'tcx>,
param_env: ParamEnv<'tcx>,
}

impl<'me, 'tcx> LayoutOf for UnwrapLayoutCx<'me, 'tcx> {
type Ty = Ty<'tcx>;
type TyLayout = TyLayout<'tcx>;

fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
self.tcx.layout_of(self.param_env.and(ty)).unwrap()
}
}

impl<'me, 'tcx> HasTyCtxt<'tcx> for UnwrapLayoutCx<'me, 'tcx> {
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
self.tcx
}
}

impl<'me, 'tcx> HasDataLayout for UnwrapLayoutCx<'me, 'tcx> {
fn data_layout(&self) -> &TargetDataLayout {
self.tcx.data_layout()
}
}
1 change: 1 addition & 0 deletions src/librustc_passes/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ mod diagnostics;
pub mod ast_validation;
pub mod rvalue_promotion;
pub mod hir_stats;
pub mod layout_test;
pub mod loops;

__build_diagnostic_array! { librustc_passes, DIAGNOSTICS }
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_target/abi/call/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>)
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
{
arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
arg.layout.homogeneous_aggregate(cx).unit().and_then(|unit| {
let size = arg.layout.size;

// Ensure we have at most four uniquely addressable members.
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_target/abi/call/arm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>)
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
{
arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
arg.layout.homogeneous_aggregate(cx).unit().and_then(|unit| {
let size = arg.layout.size;

// Ensure we have at most four uniquely addressable members.
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_target/abi/call/asmjs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn classify_ret_ty<'a, Ty, C>(cx: &C, ret: &mut ArgType<'a, Ty>)
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
{
if ret.layout.is_aggregate() {
if let Some(unit) = ret.layout.homogeneous_aggregate(cx) {
if let Some(unit) = ret.layout.homogeneous_aggregate(cx).unit() {
let size = ret.layout.size;
if unit.size == size {
ret.cast_to(Uniform {
Expand Down
Loading