Skip to content

Commit

Permalink
Auto merge of #57898 - Centril:rollup, r=Centril
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - #56233 (Miri and miri-related code contains repetitions of `(n << amt) >> amt`)
 - #57645 (distinguish "no data" from "heterogeneous" in ABI)
 - #57734 (Fix evaluating trivial drop glue in constants)
 - #57886 (Add suggestion for moving type declaration before associated type bindings in generic arguments.)
 - #57890 (Fix wording in diagnostics page)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Jan 25, 2019
2 parents bf669d1 + 0ae3d87 commit 37d51aa
Show file tree
Hide file tree
Showing 30 changed files with 870 additions and 82 deletions.
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

0 comments on commit 37d51aa

Please sign in to comment.