Skip to content

Commit 37d51aa

Browse files
committed
Auto merge of #57898 - Centril:rollup, r=Centril
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
2 parents bf669d1 + 0ae3d87 commit 37d51aa

30 files changed

+870
-82
lines changed

src/librustc/ty/mod.rs

-10
Original file line numberDiff line numberDiff line change
@@ -2937,16 +2937,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
29372937
}
29382938
}
29392939

2940-
/// Given the DefId of an item, returns its MIR, borrowed immutably.
2941-
/// Returns None if there is no MIR for the DefId
2942-
pub fn maybe_optimized_mir(self, did: DefId) -> Option<&'gcx Mir<'gcx>> {
2943-
if self.is_mir_available(did) {
2944-
Some(self.optimized_mir(did))
2945-
} else {
2946-
None
2947-
}
2948-
}
2949-
29502940
/// Get the attributes of a definition.
29512941
pub fn get_attrs(self, did: DefId) -> Attributes<'gcx> {
29522942
if let Some(id) = self.hir().as_local_node_id(did) {

src/librustc_driver/driver.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustc_incremental;
2222
use rustc_metadata::creader::CrateLoader;
2323
use rustc_metadata::cstore::{self, CStore};
2424
use rustc_mir as mir;
25-
use rustc_passes::{self, ast_validation, hir_stats, loops, rvalue_promotion};
25+
use rustc_passes::{self, ast_validation, hir_stats, loops, rvalue_promotion, layout_test};
2626
use rustc_plugin as plugin;
2727
use rustc_plugin::registry::Registry;
2828
use rustc_privacy;
@@ -1287,6 +1287,9 @@ where
12871287
mir::transform::check_unsafety::check_unsafety(tcx, def_id)
12881288
}
12891289
});
1290+
1291+
time(sess, "layout testing", || layout_test::test_layout(tcx));
1292+
12901293
// Avoid overwhelming user with errors if type checking failed.
12911294
// I'm not sure how helpful this is, to be honest, but it avoids
12921295
// a

src/librustc_lint/types.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ use syntax::source_map;
2121

2222
use rustc::hir;
2323

24+
use rustc::mir::interpret::{sign_extend, truncate};
25+
2426
declare_lint! {
2527
UNUSED_COMPARISONS,
2628
Warn,
@@ -368,14 +370,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
368370
let (t, actually) = match ty {
369371
ty::Int(t) => {
370372
let ity = attr::IntType::SignedInt(t);
371-
let bits = layout::Integer::from_attr(&cx.tcx, ity).size().bits();
372-
let actually = (val << (128 - bits)) as i128 >> (128 - bits);
373+
let size = layout::Integer::from_attr(&cx.tcx, ity).size();
374+
let actually = sign_extend(val, size) as i128;
373375
(format!("{:?}", t), actually.to_string())
374376
}
375377
ty::Uint(t) => {
376378
let ity = attr::IntType::UnsignedInt(t);
377-
let bits = layout::Integer::from_attr(&cx.tcx, ity).size().bits();
378-
let actually = (val << (128 - bits)) >> (128 - bits);
379+
let size = layout::Integer::from_attr(&cx.tcx, ity).size();
380+
let actually = truncate(val, size);
379381
(format!("{:?}", t), actually.to_string())
380382
}
381383
_ => bug!(),

src/librustc_mir/const_eval.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -340,19 +340,22 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
340340
ret: Option<mir::BasicBlock>,
341341
) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>> {
342342
debug!("eval_fn_call: {:?}", instance);
343-
// Execution might have wandered off into other crates, so we cannot to a stability-
344-
// sensitive check here. But we can at least rule out functions that are not const
345-
// at all.
346-
if !ecx.tcx.is_const_fn_raw(instance.def_id()) {
347-
// Some functions we support even if they are non-const -- but avoid testing
348-
// that for const fn! We certainly do *not* want to actually call the fn
349-
// though, so be sure we return here.
350-
return if ecx.hook_fn(instance, args, dest)? {
351-
ecx.goto_block(ret)?; // fully evaluated and done
352-
Ok(None)
353-
} else {
354-
err!(MachineError(format!("calling non-const function `{}`", instance)))
355-
};
343+
// Only check non-glue functions
344+
if let ty::InstanceDef::Item(def_id) = instance.def {
345+
// Execution might have wandered off into other crates, so we cannot to a stability-
346+
// sensitive check here. But we can at least rule out functions that are not const
347+
// at all.
348+
if !ecx.tcx.is_const_fn_raw(def_id) {
349+
// Some functions we support even if they are non-const -- but avoid testing
350+
// that for const fn! We certainly do *not* want to actually call the fn
351+
// though, so be sure we return here.
352+
return if ecx.hook_fn(instance, args, dest)? {
353+
ecx.goto_block(ret)?; // fully evaluated and done
354+
Ok(None)
355+
} else {
356+
err!(MachineError(format!("calling non-const function `{}`", instance)))
357+
};
358+
}
356359
}
357360
// This is a const fn. Call it.
358361
Ok(Some(match ecx.load_mir(instance.def) {

src/librustc_mir/interpret/eval_context.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -273,11 +273,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
273273
}
274274
trace!("load mir {:?}", instance);
275275
match instance {
276-
ty::InstanceDef::Item(def_id) => {
277-
self.tcx.maybe_optimized_mir(def_id).ok_or_else(||
278-
EvalErrorKind::NoMirFor(self.tcx.item_path_str(def_id)).into()
279-
)
280-
}
276+
ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) {
277+
Ok(self.tcx.optimized_mir(did))
278+
} else {
279+
err!(NoMirFor(self.tcx.item_path_str(def_id)))
280+
},
281281
_ => Ok(self.tcx.instance_mir(instance)),
282282
}
283283
}

src/librustc_passes/layout_test.rs

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
use rustc::hir;
2+
use rustc::hir::def_id::DefId;
3+
use rustc::hir::itemlikevisit::ItemLikeVisitor;
4+
use rustc::hir::ItemKind;
5+
use rustc::ty::layout::HasDataLayout;
6+
use rustc::ty::layout::HasTyCtxt;
7+
use rustc::ty::layout::LayoutOf;
8+
use rustc::ty::layout::TargetDataLayout;
9+
use rustc::ty::layout::TyLayout;
10+
use rustc::ty::ParamEnv;
11+
use rustc::ty::Ty;
12+
use rustc::ty::TyCtxt;
13+
use syntax::ast::Attribute;
14+
15+
pub fn test_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
16+
if tcx.features().rustc_attrs {
17+
// if the `rustc_attrs` feature is not enabled, don't bother testing layout
18+
tcx.hir()
19+
.krate()
20+
.visit_all_item_likes(&mut VarianceTest { tcx });
21+
}
22+
}
23+
24+
struct VarianceTest<'a, 'tcx: 'a> {
25+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
26+
}
27+
28+
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for VarianceTest<'a, 'tcx> {
29+
fn visit_item(&mut self, item: &'tcx hir::Item) {
30+
let item_def_id = self.tcx.hir().local_def_id(item.id);
31+
32+
if let ItemKind::Ty(..) = item.node {
33+
for attr in self.tcx.get_attrs(item_def_id).iter() {
34+
if attr.check_name("rustc_layout") {
35+
self.dump_layout_of(item_def_id, item, attr);
36+
}
37+
}
38+
}
39+
}
40+
41+
fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) {}
42+
fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) {}
43+
}
44+
45+
impl<'a, 'tcx> VarianceTest<'a, 'tcx> {
46+
fn dump_layout_of(&self, item_def_id: DefId, item: &hir::Item, attr: &Attribute) {
47+
let tcx = self.tcx;
48+
let param_env = self.tcx.param_env(item_def_id);
49+
let ty = self.tcx.type_of(item_def_id);
50+
match self.tcx.layout_of(param_env.and(ty)) {
51+
Ok(ty_layout) => {
52+
// Check out the `#[rustc_layout(..)]` attribute to tell what to dump.
53+
// The `..` are the names of fields to dump.
54+
let meta_items = attr.meta_item_list().unwrap_or_default();
55+
for meta_item in meta_items {
56+
let name = meta_item.word().map(|mi| mi.name().as_str());
57+
let name = name.as_ref().map(|s| &s[..]).unwrap_or("");
58+
59+
match name {
60+
"abi" => {
61+
self.tcx
62+
.sess
63+
.span_err(item.span, &format!("abi: {:?}", ty_layout.abi));
64+
}
65+
66+
"align" => {
67+
self.tcx
68+
.sess
69+
.span_err(item.span, &format!("align: {:?}", ty_layout.align));
70+
}
71+
72+
"size" => {
73+
self.tcx
74+
.sess
75+
.span_err(item.span, &format!("size: {:?}", ty_layout.size));
76+
}
77+
78+
"homogeneous_aggregate" => {
79+
self.tcx.sess.span_err(
80+
item.span,
81+
&format!(
82+
"homogeneous_aggregate: {:?}",
83+
ty_layout
84+
.homogeneous_aggregate(&UnwrapLayoutCx { tcx, param_env }),
85+
),
86+
);
87+
}
88+
89+
_ => {
90+
self.tcx.sess.span_err(
91+
meta_item.span,
92+
&format!("unrecognized field name `{}`", name),
93+
);
94+
}
95+
}
96+
}
97+
}
98+
99+
Err(layout_error) => {
100+
self.tcx
101+
.sess
102+
.span_err(item.span, &format!("layout error: {:?}", layout_error));
103+
}
104+
}
105+
}
106+
}
107+
108+
struct UnwrapLayoutCx<'me, 'tcx> {
109+
tcx: TyCtxt<'me, 'tcx, 'tcx>,
110+
param_env: ParamEnv<'tcx>,
111+
}
112+
113+
impl<'me, 'tcx> LayoutOf for UnwrapLayoutCx<'me, 'tcx> {
114+
type Ty = Ty<'tcx>;
115+
type TyLayout = TyLayout<'tcx>;
116+
117+
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
118+
self.tcx.layout_of(self.param_env.and(ty)).unwrap()
119+
}
120+
}
121+
122+
impl<'me, 'tcx> HasTyCtxt<'tcx> for UnwrapLayoutCx<'me, 'tcx> {
123+
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
124+
self.tcx
125+
}
126+
}
127+
128+
impl<'me, 'tcx> HasDataLayout for UnwrapLayoutCx<'me, 'tcx> {
129+
fn data_layout(&self) -> &TargetDataLayout {
130+
self.tcx.data_layout()
131+
}
132+
}

src/librustc_passes/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ mod diagnostics;
3232
pub mod ast_validation;
3333
pub mod rvalue_promotion;
3434
pub mod hir_stats;
35+
pub mod layout_test;
3536
pub mod loops;
3637

3738
__build_diagnostic_array! { librustc_passes, DIAGNOSTICS }

src/librustc_target/abi/call/aarch64.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>)
66
where Ty: TyLayoutMethods<'a, C> + Copy,
77
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
88
{
9-
arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
9+
arg.layout.homogeneous_aggregate(cx).unit().and_then(|unit| {
1010
let size = arg.layout.size;
1111

1212
// Ensure we have at most four uniquely addressable members.

src/librustc_target/abi/call/arm.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>)
77
where Ty: TyLayoutMethods<'a, C> + Copy,
88
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
99
{
10-
arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
10+
arg.layout.homogeneous_aggregate(cx).unit().and_then(|unit| {
1111
let size = arg.layout.size;
1212

1313
// Ensure we have at most four uniquely addressable members.

src/librustc_target/abi/call/asmjs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn classify_ret_ty<'a, Ty, C>(cx: &C, ret: &mut ArgType<'a, Ty>)
1111
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
1212
{
1313
if ret.layout.is_aggregate() {
14-
if let Some(unit) = ret.layout.homogeneous_aggregate(cx) {
14+
if let Some(unit) = ret.layout.homogeneous_aggregate(cx).unit() {
1515
let size = ret.layout.size;
1616
if unit.size == size {
1717
ret.cast_to(Uniform {

0 commit comments

Comments
 (0)