diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index bd1a87c5744d3..138b7f4b26104 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -5,9 +5,6 @@ //! parent directory, and otherwise documentation can be found throughout the `build` //! directory in each respective module. -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - use std::env; use bootstrap::{Config, Build}; diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index ce92ce0269671..8cb48df14bfef 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -15,9 +15,6 @@ //! switching compilers for the bootstrap and for build scripts will probably //! never get replaced. -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - use std::env; use std::ffi::OsString; use std::io; @@ -124,8 +121,9 @@ fn main() { if env::var_os("RUSTC_DENY_WARNINGS").is_some() && env::var_os("RUSTC_EXTERNAL_TOOL").is_none() { - // When extending this list, search for `NO-RUSTC-WRAPPER` and add the new lints - // there as well, some code doesn't go through this `rustc` wrapper. + // When extending this list, add the new lints to the RUSTFLAGS of the + // build_bootstrap function of src/bootstrap/bootstrap.py as well as + // some code doesn't go through this `rustc` wrapper. cmd.arg("-Dwarnings"); cmd.arg("-Drust_2018_idioms"); cmd.arg("-Dunused_lifetimes"); diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index ff38ee8788f56..766a3463ecd8b 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -2,9 +2,6 @@ //! //! See comments in `src/bootstrap/rustc.rs` for more information. -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - use std::env; use std::process::Command; use std::path::PathBuf; diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 86901792d7974..3c56131396f29 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -631,6 +631,8 @@ def build_bootstrap(self): target_linker = self.get_toml("linker", build_section) if target_linker is not None: env["RUSTFLAGS"] += "-C linker=" + target_linker + " " + if self.get_toml("deny-warnings", "rust") != "false": + env["RUSTFLAGS"] += "-Dwarnings -Drust_2018_idioms -Dunused_lifetimes " env["PATH"] = os.path.join(self.bin_root(), "bin") + \ os.pathsep + env["PATH"] diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index e9a9b7881a068..205a80c3a3a9e 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -34,7 +34,7 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("std") + run.all_krates("test") } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 7dad146b48d83..9d57a4f00d780 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -39,7 +39,7 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("std") + run.all_krates("test") } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 6805474aa049f..3d0a175e8206c 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -413,7 +413,7 @@ impl Step for Std { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.all_krates("std").default_condition(builder.config.docs) + run.all_krates("test").default_condition(builder.config.docs) } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index c0e0ad1a857b9..575844028d562 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -103,9 +103,6 @@ //! More documentation can be found in each respective module below, and you can //! also check out the `src/bootstrap/README.md` file for more information. -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - #![feature(core_intrinsics)] #![feature(drain_filter)] diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 131d2034675e3..f035a7119188a 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -1,6 +1,3 @@ -// NO-RUSTC-WRAPPER -#![deny(warnings, rust_2018_idioms, unused_lifetimes)] - use std::fs::File; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 167a9dd1c3620..607427a85d67a 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -1015,8 +1015,8 @@ mod impls { // The order here is important to generate more optimal assembly. // See for more info. if *self < *other { Less } - else if *self > *other { Greater } - else { Equal } + else if *self == *other { Equal } + else { Greater } } } )*) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 8febcfd0754c9..5ec4754c4535b 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -273,14 +273,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { repr: &ReprOptions, kind: StructKind) -> Result> { let dl = self.data_layout(); - let packed = repr.packed(); - if packed && repr.align > 0 { + let pack = repr.pack; + if pack.is_some() && repr.align.is_some() { bug!("struct cannot be packed and aligned"); } - let pack = Align::from_bytes(repr.pack as u64).unwrap(); - - let mut align = if packed { + let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align @@ -303,7 +301,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }; let optimizing = &mut inverse_memory_index[..end]; let field_align = |f: &TyLayout<'_>| { - if packed { f.align.abi.min(pack) } else { f.align.abi } + if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi } }; match kind { StructKind::AlwaysSized | @@ -334,7 +332,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let mut largest_niche_available = 0; if let StructKind::Prefixed(prefix_size, prefix_align) = kind { - let prefix_align = if packed { + let prefix_align = if let Some(pack) = pack { prefix_align.min(pack) } else { prefix_align @@ -355,7 +353,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } // Invariant: offset < dl.obj_size_bound() <= 1<<61 - let field_align = if packed { + let field_align = if let Some(pack) = pack { field.align.min(AbiAndPrefAlign::new(pack)) } else { field.align @@ -379,10 +377,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { .ok_or(LayoutError::SizeOverflow(ty))?; } - if repr.align > 0 { - let repr_align = repr.align as u64; - align = align.max(AbiAndPrefAlign::new(Align::from_bytes(repr_align).unwrap())); - debug!("univariant repr_align: {:?}", repr_align); + if let Some(repr_align) = repr.align { + align = align.max(AbiAndPrefAlign::new(repr_align)); } debug!("univariant min_size: {:?}", offset); @@ -730,23 +726,18 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }).collect::, _>>()?; if def.is_union() { - let packed = def.repr.packed(); - if packed && def.repr.align > 0 { - bug!("Union cannot be packed and aligned"); + if def.repr.pack.is_some() && def.repr.align.is_some() { + bug!("union cannot be packed and aligned"); } - let pack = Align::from_bytes(def.repr.pack as u64).unwrap(); - - let mut align = if packed { + let mut align = if def.repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align }; - if def.repr.align > 0 { - let repr_align = def.repr.align as u64; - align = align.max( - AbiAndPrefAlign::new(Align::from_bytes(repr_align).unwrap())); + if let Some(repr_align) = def.repr.align { + align = align.max(AbiAndPrefAlign::new(repr_align)); } let optimize = !def.repr.inhibit_union_abi_opt(); @@ -755,13 +746,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let index = VariantIdx::new(0); for field in &variants[index] { assert!(!field.is_unsized()); - - let field_align = if packed { - field.align.min(AbiAndPrefAlign::new(pack)) - } else { - field.align - }; - align = align.max(field_align); + align = align.max(field.align); // If all non-ZST fields have the same ABI, forward this ABI if optimize && !field.is_zst() { @@ -796,6 +781,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { size = cmp::max(size, field.size); } + if let Some(pack) = def.repr.pack { + align = align.min(AbiAndPrefAlign::new(pack)); + } + return Ok(tcx.intern_layout(LayoutDetails { variants: Variants::Single { index }, fields: FieldPlacement::Union(variants[index].len()), @@ -1637,7 +1626,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }; let adt_kind = adt_def.adt_kind(); - let adt_packed = adt_def.repr.packed(); + let adt_packed = adt_def.repr.pack.is_some(); let build_variant_info = |n: Option, flds: &[ast::Name], diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 90b3b7ebb0635..eaaaf75f75dd5 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -33,6 +33,7 @@ use arena::SyncDroplessArena; use crate::session::DataTypeKind; use rustc_serialize::{self, Encodable, Encoder}; +use rustc_target::abi::Align; use std::cell::RefCell; use std::cmp::{self, Ordering}; use std::fmt; @@ -2057,8 +2058,8 @@ impl_stable_hash_for!(struct ReprFlags { #[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)] pub struct ReprOptions { pub int: Option, - pub align: u32, - pub pack: u32, + pub align: Option, + pub pack: Option, pub flags: ReprFlags, } @@ -2073,18 +2074,19 @@ impl ReprOptions { pub fn new(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions { let mut flags = ReprFlags::empty(); let mut size = None; - let mut max_align = 0; - let mut min_pack = 0; + let mut max_align: Option = None; + let mut min_pack: Option = None; for attr in tcx.get_attrs(did).iter() { for r in attr::find_repr_attrs(&tcx.sess.parse_sess, attr) { flags.insert(match r { attr::ReprC => ReprFlags::IS_C, attr::ReprPacked(pack) => { - min_pack = if min_pack > 0 { - cmp::min(pack, min_pack) + let pack = Align::from_bytes(pack as u64).unwrap(); + min_pack = Some(if let Some(min_pack) = min_pack { + min_pack.min(pack) } else { pack - }; + }); ReprFlags::empty() }, attr::ReprTransparent => ReprFlags::IS_TRANSPARENT, @@ -2094,7 +2096,7 @@ impl ReprOptions { ReprFlags::empty() }, attr::ReprAlign(align) => { - max_align = cmp::max(align, max_align); + max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap())); ReprFlags::empty() }, }); @@ -2113,7 +2115,7 @@ impl ReprOptions { #[inline] pub fn c(&self) -> bool { self.flags.contains(ReprFlags::IS_C) } #[inline] - pub fn packed(&self) -> bool { self.pack > 0 } + pub fn packed(&self) -> bool { self.pack.is_some() } #[inline] pub fn transparent(&self) -> bool { self.flags.contains(ReprFlags::IS_TRANSPARENT) } #[inline] @@ -2133,8 +2135,12 @@ impl ReprOptions { /// Returns `true` if this `#[repr()]` should inhibit struct field reordering /// optimizations, such as with `repr(C)`, `repr(packed(1))`, or `repr()`. pub fn inhibit_struct_field_reordering_opt(&self) -> bool { - self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.pack == 1 || - self.int.is_some() + if let Some(pack) = self.pack { + if pack.bytes() == 1 { + return true; + } + } + self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some() } /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations. diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 82d6d7db01c8d..c2505547c5b4f 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -11,7 +11,7 @@ use std::hash::Hash; use super::{ GlobalAlloc, InterpResult, - OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy, + Scalar, OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy, }; macro_rules! throw_validation_failure { @@ -250,6 +250,47 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M self.path.truncate(path_len); Ok(()) } + + fn check_wide_ptr_meta( + &mut self, + meta: Option>, + pointee: TyLayout<'tcx>, + ) -> InterpResult<'tcx> { + let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env); + match tail.sty { + ty::Dynamic(..) => { + let vtable = meta.unwrap(); + try_validation!( + self.ecx.memory.check_ptr_access( + vtable, + 3*self.ecx.tcx.data_layout.pointer_size, // drop, size, align + self.ecx.tcx.data_layout.pointer_align.abi, + ), + "dangling or unaligned vtable pointer in wide pointer or too small vtable", + self.path + ); + try_validation!(self.ecx.read_drop_type_from_vtable(vtable), + "invalid drop fn in vtable", self.path); + try_validation!(self.ecx.read_size_and_align_from_vtable(vtable), + "invalid size or align in vtable", self.path); + // FIXME: More checks for the vtable. + } + ty::Slice(..) | ty::Str => { + let _len = try_validation!(meta.unwrap().to_usize(self.ecx), + "non-integer slice length in wide pointer", self.path); + // We do not check that `len * elem_size <= isize::MAX`: + // that is only required for references, and there it falls out of the + // "dereferencable" check performed by Stacked Borrows. + } + ty::Foreign(..) => { + // Unsized, but not wide. + } + _ => + bug!("Unexpected unsized type tail: {:?}", tail), + } + + Ok(()) + } } impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> @@ -341,56 +382,34 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } } ty::RawPtr(..) => { + // Check pointer part. if self.ref_tracking_for_consts.is_some() { // Integers/floats in CTFE: For consistency with integers, we do not // accept undef. let _ptr = try_validation!(value.to_scalar_ptr(), "undefined address in raw pointer", self.path); - let _meta = try_validation!(value.to_meta(), - "uninitialized data in raw fat pointer metadata", self.path); } else { // Remain consistent with `usize`: Accept anything. } + + // Check metadata. + let meta = try_validation!(value.to_meta(), + "uninitialized data in wide pointer metadata", self.path); + let layout = self.ecx.layout_of(value.layout.ty.builtin_deref(true).unwrap().ty)?; + if layout.is_unsized() { + self.check_wide_ptr_meta(meta, layout)?; + } } _ if ty.is_box() || ty.is_region_ptr() => { - // Handle fat pointers. + // Handle wide pointers. // Check metadata early, for better diagnostics let ptr = try_validation!(value.to_scalar_ptr(), "undefined address in pointer", self.path); let meta = try_validation!(value.to_meta(), - "uninitialized data in fat pointer metadata", self.path); + "uninitialized data in wide pointer metadata", self.path); let layout = self.ecx.layout_of(value.layout.ty.builtin_deref(true).unwrap().ty)?; if layout.is_unsized() { - let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(layout.ty, - self.ecx.param_env); - match tail.sty { - ty::Dynamic(..) => { - let vtable = meta.unwrap(); - try_validation!( - self.ecx.memory.check_ptr_access( - vtable, - 3*self.ecx.tcx.data_layout.pointer_size, // drop, size, align - self.ecx.tcx.data_layout.pointer_align.abi, - ), - "dangling or unaligned vtable pointer or too small vtable", - self.path - ); - try_validation!(self.ecx.read_drop_type_from_vtable(vtable), - "invalid drop fn in vtable", self.path); - try_validation!(self.ecx.read_size_and_align_from_vtable(vtable), - "invalid size or align in vtable", self.path); - // FIXME: More checks for the vtable. - } - ty::Slice(..) | ty::Str => { - try_validation!(meta.unwrap().to_usize(self.ecx), - "non-integer slice length in fat pointer", self.path); - } - ty::Foreign(..) => { - // Unsized, but not fat. - } - _ => - bug!("Unexpected unsized type tail: {:?}", tail), - } + self.check_wide_ptr_meta(meta, layout)?; } // Make sure this is dereferencable and all. let (size, align) = self.ecx.size_and_align_of(meta, layout)? diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 01fda54b1eaaa..a80550486d627 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1859,14 +1859,18 @@ fn check_packed(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) { for attr in tcx.get_attrs(def_id).iter() { for r in attr::find_repr_attrs(&tcx.sess.parse_sess, attr) { if let attr::ReprPacked(pack) = r { - if pack != repr.pack { - struct_span_err!(tcx.sess, sp, E0634, - "type has conflicting packed representation hints").emit(); + if let Some(repr_pack) = repr.pack { + if pack as u64 != repr_pack.bytes() { + struct_span_err!( + tcx.sess, sp, E0634, + "type has conflicting packed representation hints" + ).emit(); + } } } } } - if repr.align > 0 { + if repr.align.is_some() { struct_span_err!(tcx.sess, sp, E0587, "type has conflicting packed and align representation hints").emit(); } @@ -1885,7 +1889,7 @@ fn check_packed_inner(tcx: TyCtxt<'_>, def_id: DefId, stack: &mut Vec) -> } if let ty::Adt(def, substs) = t.sty { if def.is_struct() || def.is_union() { - if tcx.adt_def(def.did).repr.align > 0 { + if tcx.adt_def(def.did).repr.align.is_some() { return true; } // push struct def_id before checking fields diff --git a/src/test/codegen/integer-cmp.rs b/src/test/codegen/integer-cmp.rs index 1373b12e3721c..8ada3cf09d073 100644 --- a/src/test/codegen/integer-cmp.rs +++ b/src/test/codegen/integer-cmp.rs @@ -11,7 +11,7 @@ use std::cmp::Ordering; #[no_mangle] pub fn cmp_signed(a: i64, b: i64) -> Ordering { // CHECK: icmp slt -// CHECK: icmp sgt +// CHECK: icmp ne // CHECK: zext i1 // CHECK: select i1 a.cmp(&b) @@ -21,7 +21,7 @@ pub fn cmp_signed(a: i64, b: i64) -> Ordering { #[no_mangle] pub fn cmp_unsigned(a: u32, b: u32) -> Ordering { // CHECK: icmp ult -// CHECK: icmp ugt +// CHECK: icmp ne // CHECK: zext i1 // CHECK: select i1 a.cmp(&b) diff --git a/src/test/ui/consts/const-eval/union-ub-fat-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs similarity index 59% rename from src/test/ui/consts/const-eval/union-ub-fat-ptr.rs rename to src/test/ui/consts/const-eval/ub-wide-ptr.rs index d5405f3441fec..765ed60ee9742 100644 --- a/src/test/ui/consts/const-eval/union-ub-fat-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -1,3 +1,4 @@ +// ignore-tidy-linelength #![allow(unused)] #![allow(const_err)] // make sure we cannot allow away the errors tested here @@ -28,7 +29,9 @@ struct BadSliceRepr { union SliceTransmute { repr: SliceRepr, bad: BadSliceRepr, + addr: usize, slice: &'static [u8], + raw_slice: *const [u8], str: &'static str, my_str: &'static MyStr, my_slice: &'static MySliceBool, @@ -59,7 +62,9 @@ union DynTransmute { repr: DynRepr, repr2: DynRepr2, bad: BadDynRepr, + addr: usize, rust: &'static dyn Trait, + raw_rust: *const dyn Trait, } trait Trait {} @@ -72,39 +77,37 @@ struct MyStr(str); struct MySlice(bool, T); type MySliceBool = MySlice<[bool]>; +// # str // OK -const A: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str}; +const STR_VALID: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str}; // bad str -const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; +const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; //~^ ERROR it is undefined behavior to use this value // bad str -const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; +const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; //~^ ERROR it is undefined behavior to use this value // bad str in user-defined unsized type -const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; +const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; //~^ ERROR it is undefined behavior to use this value -// OK -const A2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice}; -// bad slice -const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; +// invalid UTF-8 +const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; //~^ ERROR it is undefined behavior to use this value -// bad slice -const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; +// invalid UTF-8 in user-defined str-like +const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; //~^ ERROR it is undefined behavior to use this value -// bad trait object -const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; -//~^ ERROR it is undefined behavior to use this value -// bad trait object -const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; +// # slice +// OK +const SLICE_VALID: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice}; +// bad slice: length uninit +const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; //~^ ERROR it is undefined behavior to use this value -// bad trait object -const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; +// bad slice: length too big +const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; //~^ ERROR it is undefined behavior to use this value - -// bad data *inside* the trait object -const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; +// bad slice: length not an int +const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; //~^ ERROR it is undefined behavior to use this value // bad data *inside* the slice @@ -120,12 +123,34 @@ const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); //~^ ERROR it is undefined behavior to use this value -// invalid UTF-8 -const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; +// # raw slice +const RAW_SLICE_VALID: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.raw_slice}; // ok +const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.raw_slice}; // ok because raw +const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: usize::max_value() } }.raw_slice}; // ok because raw +const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; //~^ ERROR it is undefined behavior to use this value -// invalid UTF-8 in user-defined str-like -const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; + +// # trait object +// bad trait object +const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; +//~^ ERROR it is undefined behavior to use this value +// bad trait object +const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; +//~^ ERROR it is undefined behavior to use this value +// bad trait object +const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; +//~^ ERROR it is undefined behavior to use this value + +// bad data *inside* the trait object +const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; +//~^ ERROR it is undefined behavior to use this value + +// # raw trait object +const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; +//~^ ERROR it is undefined behavior to use this value +const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; //~^ ERROR it is undefined behavior to use this value +const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl } as *const _; // ok because raw fn main() { } diff --git a/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr similarity index 60% rename from src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr rename to src/test/ui/consts/const-eval/ub-wide-ptr.stderr index aac32ecc5b747..88d8af8026193 100644 --- a/src/test/ui/consts/const-eval/union-ub-fat-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -1,77 +1,69 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:78:1 + --> $DIR/ub-wide-ptr.rs:84:1 | -LL | const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) +LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:81:1 + --> $DIR/ub-wide-ptr.rs:87:1 | -LL | const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer +LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:84:1 + --> $DIR/ub-wide-ptr.rs:90:1 | -LL | const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer +LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:90:1 + --> $DIR/ub-wide-ptr.rs:94:1 | -LL | const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior - -error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:93:1 - | -LL | const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in fat pointer +LL | const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:97:1 + --> $DIR/ub-wide-ptr.rs:97:1 | -LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable +LL | const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:100:1 + --> $DIR/ub-wide-ptr.rs:104:1 | -LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable +LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:103:1 + --> $DIR/ub-wide-ptr.rs:107:1 | -LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer or too small vtable +LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:107:1 + --> $DIR/ub-wide-ptr.rs:110:1 | -LL | const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 +LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:111:1 + --> $DIR/ub-wide-ptr.rs:114:1 | LL | const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected something less or equal to 1 @@ -79,7 +71,7 @@ LL | const H: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:117:1 + --> $DIR/ub-wide-ptr.rs:120:1 | LL | const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected something less or equal to 1 @@ -87,7 +79,7 @@ LL | const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:120:1 + --> $DIR/ub-wide-ptr.rs:123:1 | LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected something less or equal to 1 @@ -95,21 +87,61 @@ LL | const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }. = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:124:1 + --> $DIR/ub-wide-ptr.rs:130:1 | -LL | const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . +LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in wide pointer metadata | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/union-ub-fat-ptr.rs:127:1 + --> $DIR/ub-wide-ptr.rs:135:1 | -LL | const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 +LL | const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:138:1 + | +LL | const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:141:1 + | +LL | const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:145:1 + | +LL | const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:149:1 + | +LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:151:1 + | +LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior -error: aborting due to 14 previous errors +error: aborting due to 18 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs index e885263aa8084..04d924a9aed20 100644 --- a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs +++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs @@ -1,7 +1,5 @@ // run-pass -// ignore-cloudabi no processes -// ignore-emscripten no processes -// ignore-sgx no processes +// check-run-results // Tests ensuring that `dbg!(expr)` has the expected run-time behavior. // as well as some compile time properties we expect. @@ -18,7 +16,7 @@ struct Point { #[derive(Debug, PartialEq)] struct NoCopy(usize); -fn test() { +fn main() { let a: Unit = dbg!(Unit); let _: Unit = dbg!(a); // We can move `a` because it's Copy. @@ -67,81 +65,3 @@ fn test() { assert_eq!((1u8, 2u32, "Yeah"), dbg!(1u8, 2u32, "Yeah",)); } - -fn validate_stderr(stderr: Vec) { - assert_eq!(stderr, &[ - ":22] Unit = Unit", - - ":23] a = Unit", - - ":29] Point{x: 42, y: 24,} = Point {", - " x: 42,", - " y: 24,", - "}", - - ":30] b = Point {", - " x: 42,", - " y: 24,", - "}", - - ":38]", - - ":42] &a = NoCopy(", - " 1337,", - ")", - - ":42] dbg!(& a) = NoCopy(", - " 1337,", - ")", - ":47] f(&42) = 42", - - "before", - ":52] { foo += 1; eprintln!(\"before\"); 7331 } = 7331", - - ":60] (\"Yeah\",) = (", - " \"Yeah\",", - ")", - - ":63] 1 = 1", - ":63] 2 = 2", - - ":67] 1u8 = 1", - ":67] 2u32 = 2", - ":67] \"Yeah\" = \"Yeah\"", - ]); -} - -fn main() { - // The following is a hack to deal with compiletest's inability - // to check the output (to stdout) of run-pass tests. - use std::env; - use std::process::Command; - - let mut args = env::args(); - let prog = args.next().unwrap(); - let child = args.next(); - if let Some("child") = child.as_ref().map(|s| &**s) { - // Only run the test if we've been spawned as 'child' - test() - } else { - // This essentially spawns as 'child' to run the tests - // and then it collects output of stderr and checks the output - // against what we expect. - let out = Command::new(&prog).arg("child").output().unwrap(); - assert!(out.status.success()); - assert!(out.stdout.is_empty()); - - let stderr = String::from_utf8(out.stderr).unwrap(); - let stderr = stderr.lines().map(|mut s| { - if s.starts_with("[") { - // Strip `[` and file path: - s = s.trim_start_matches("["); - assert!(s.starts_with(file!())); - s = s.trim_start_matches(file!()); - } - s.to_owned() - }).collect(); - - validate_stderr(stderr); - } -} diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr new file mode 100644 index 0000000000000..707b38cf37af0 --- /dev/null +++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr @@ -0,0 +1,28 @@ +[$DIR/dbg-macro-expected-behavior.rs:20] Unit = Unit +[$DIR/dbg-macro-expected-behavior.rs:21] a = Unit +[$DIR/dbg-macro-expected-behavior.rs:27] Point{x: 42, y: 24,} = Point { + x: 42, + y: 24, +} +[$DIR/dbg-macro-expected-behavior.rs:28] b = Point { + x: 42, + y: 24, +} +[$DIR/dbg-macro-expected-behavior.rs:36] +[$DIR/dbg-macro-expected-behavior.rs:40] &a = NoCopy( + 1337, +) +[$DIR/dbg-macro-expected-behavior.rs:40] dbg!(& a) = NoCopy( + 1337, +) +[$DIR/dbg-macro-expected-behavior.rs:45] f(&42) = 42 +before +[$DIR/dbg-macro-expected-behavior.rs:50] { foo += 1; eprintln!("before"); 7331 } = 7331 +[$DIR/dbg-macro-expected-behavior.rs:58] ("Yeah",) = ( + "Yeah", +) +[$DIR/dbg-macro-expected-behavior.rs:61] 1 = 1 +[$DIR/dbg-macro-expected-behavior.rs:61] 2 = 2 +[$DIR/dbg-macro-expected-behavior.rs:65] 1u8 = 1 +[$DIR/dbg-macro-expected-behavior.rs:65] 2u32 = 2 +[$DIR/dbg-macro-expected-behavior.rs:65] "Yeah" = "Yeah" diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 66e030e979355..edb9eb7d860e2 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -333,10 +333,12 @@ pub fn expected_output_path( testpaths.file.with_extension(extension) } -pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT, UI_FIXED]; +pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT, UI_FIXED, UI_RUN_STDERR, UI_RUN_STDOUT]; pub const UI_STDERR: &str = "stderr"; pub const UI_STDOUT: &str = "stdout"; pub const UI_FIXED: &str = "fixed"; +pub const UI_RUN_STDERR: &str = "run.stderr"; +pub const UI_RUN_STDOUT: &str = "run.stdout"; /// Absolute path to the directory where all output for all tests in the given /// `relative_dir` group should reside. Example: diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 076ad87c70fc4..dcd4f14f354d1 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -326,6 +326,8 @@ pub struct TestProps { pub force_host: bool, // Check stdout for error-pattern output as well as stderr pub check_stdout: bool, + // Check stdout & stderr for output of run-pass test + pub check_run_results: bool, // For UI tests, allows compiler to generate arbitrary output to stdout pub dont_check_compiler_stdout: bool, // For UI tests, allows compiler to generate arbitrary output to stderr @@ -388,6 +390,7 @@ impl TestProps { build_aux_docs: false, force_host: false, check_stdout: false, + check_run_results: false, dont_check_compiler_stdout: false, dont_check_compiler_stderr: false, no_prefer_dynamic: false, @@ -468,6 +471,10 @@ impl TestProps { self.check_stdout = config.parse_check_stdout(ln); } + if !self.check_run_results { + self.check_run_results = config.parse_check_run_results(ln); + } + if !self.dont_check_compiler_stdout { self.dont_check_compiler_stdout = config.parse_dont_check_compiler_stdout(ln); } @@ -712,6 +719,10 @@ impl Config { self.parse_name_directive(line, "check-stdout") } + fn parse_check_run_results(&self, line: &str) -> bool { + self.parse_name_directive(line, "check-run-results") + } + fn parse_dont_check_compiler_stdout(&self, line: &str) -> bool { self.parse_name_directive(line, "dont-check-compiler-stdout") } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3da6be74129f4..7b5e0752b3673 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2,6 +2,7 @@ use crate::common::{CompareMode, PassMode}; use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT}; +use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT}; use crate::common::{output_base_dir, output_base_name, output_testname_unique}; use crate::common::{Codegen, CodegenUnits, Rustdoc}; use crate::common::{DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb}; @@ -288,6 +289,11 @@ enum ReadFrom { Stdin(String), } +enum TestOutput { + Compile, + Run, +} + impl<'test> TestCx<'test> { /// Code executed for each revision in turn (or, if there are no /// revisions, exactly once, with revision == None). @@ -2934,44 +2940,64 @@ impl<'test> TestCx<'test> { } } - fn run_ui_test(&self) { - // if the user specified a format in the ui test - // print the output to the stderr file, otherwise extract - // the rendered error messages from json and print them - let explicit = self - .props - .compile_flags - .iter() - .any(|s| s.contains("--error-format")); - let proc_res = self.compile_test(); - self.check_if_test_should_compile(&proc_res); + fn load_compare_outputs(&self, proc_res: &ProcRes, + output_kind: TestOutput, explicit_format: bool) -> usize { - let expected_stderr = self.load_expected_output(UI_STDERR); - let expected_stdout = self.load_expected_output(UI_STDOUT); - let expected_fixed = self.load_expected_output(UI_FIXED); + let (stderr_kind, stdout_kind) = match output_kind { + TestOutput::Compile => (UI_STDERR, UI_STDOUT), + TestOutput::Run => (UI_RUN_STDERR, UI_RUN_STDOUT) + }; + + let expected_stderr = self.load_expected_output(stderr_kind); + let expected_stdout = self.load_expected_output(stdout_kind); let normalized_stdout = self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout); - let stderr = if explicit { + let stderr = if explicit_format { proc_res.stderr.clone() } else { json::extract_rendered(&proc_res.stderr) }; let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr); - let mut errors = 0; - if !self.props.dont_check_compiler_stdout { - errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); - } - if !self.props.dont_check_compiler_stderr { - errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr); + match output_kind { + TestOutput::Compile => { + if !self.props.dont_check_compiler_stdout { + errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); + } + if !self.props.dont_check_compiler_stderr { + errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr); + } + } + TestOutput::Run => { + errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout); + errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr); + } } + errors + } + + fn run_ui_test(&self) { + // if the user specified a format in the ui test + // print the output to the stderr file, otherwise extract + // the rendered error messages from json and print them + let explicit = self + .props + .compile_flags + .iter() + .any(|s| s.contains("--error-format")); + let proc_res = self.compile_test(); + self.check_if_test_should_compile(&proc_res); + + let expected_fixed = self.load_expected_output(UI_FIXED); let modes_to_prune = vec![CompareMode::Nll]; self.prune_duplicate_outputs(&modes_to_prune); + let mut errors = self.load_compare_outputs(&proc_res, TestOutput::Compile, explicit); + if self.config.compare_mode.is_some() { // don't test rustfix with nll right now } else if self.config.rustfix_coverage { @@ -3049,7 +3075,17 @@ impl<'test> TestCx<'test> { if self.should_run_successfully() { let proc_res = self.exec_compiled_test(); - + let run_output_errors = if self.props.check_run_results { + self.load_compare_outputs(&proc_res, TestOutput::Run, explicit) + } else { + 0 + }; + if run_output_errors > 0 { + self.fatal_proc_rec( + &format!("{} errors occured comparing run output.", run_output_errors), + &proc_res, + ); + } if !proc_res.status.success() { self.fatal_proc_rec("test run failed!", &proc_res); } diff --git a/src/tools/rust-installer b/src/tools/rust-installer index 85958b001dbff..9f66c14c3f91a 160000 --- a/src/tools/rust-installer +++ b/src/tools/rust-installer @@ -1 +1 @@ -Subproject commit 85958b001dbff8523396809bfa844fc34a7869a8 +Subproject commit 9f66c14c3f91a48a118c7817f434167b311c3515