Skip to content

Commit

Permalink
Auto merge of #63471 - Mark-Simulacrum:rollup-m756lnx, r=Mark-Simulacrum
Browse files Browse the repository at this point in the history
Rollup of 8 pull requests

Successful merges:

 - #61969 (Add #[repr(transparent)] for several types)
 - #63346 (Lint on some incorrect uses of mem::zeroed / mem::uninitialized)
 - #63433 (Miri shouldn't look at types)
 - #63440 (rename RUST_CTFE_BACKTRACE to RUSTC_CTFE_BACKTRACE)
 - #63441 (Derive Debug for CrateInfo)
 - #63442 (Add an example to show how to insert item to a sorted vec)
 - #63453 (rustdoc: general cleanup)
 - #63464 (Copy ty::Instance instead of passing by reference)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Aug 11, 2019
2 parents 8a06869 + 4229dc3 commit 00ee1b4
Show file tree
Hide file tree
Showing 50 changed files with 795 additions and 387 deletions.
1 change: 0 additions & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3252,7 +3252,6 @@ name = "rustdoc"
version = "0.0.0"
dependencies = [
"minifier 0.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"pulldown-cmark 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
Expand Down
3 changes: 3 additions & 0 deletions src/libcore/mem/maybe_uninit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::mem::ManuallyDrop;
/// ever gets used to access memory:
///
/// ```rust,no_run
/// # #![allow(invalid_value)]
/// use std::mem::{self, MaybeUninit};
///
/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
Expand All @@ -27,6 +28,7 @@ use crate::mem::ManuallyDrop;
/// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior:
///
/// ```rust,no_run
/// # #![allow(invalid_value)]
/// use std::mem::{self, MaybeUninit};
///
/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior!
Expand All @@ -40,6 +42,7 @@ use crate::mem::ManuallyDrop;
/// which otherwise can hold any *fixed* bit pattern:
///
/// ```rust,no_run
/// # #![allow(invalid_value)]
/// use std::mem::{self, MaybeUninit};
///
/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior!
Expand Down
3 changes: 2 additions & 1 deletion src/libcore/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,8 @@ pub const fn needs_drop<T>() -> bool {
///
/// *Incorrect* usage of this function: initializing a reference with zero.
///
/// ```no_run
/// ```rust,no_run
/// # #![allow(invalid_value)]
/// use std::mem;
///
/// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior!
Expand Down
11 changes: 11 additions & 0 deletions src/libcore/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1364,6 +1364,17 @@ impl<T> [T] {
/// let r = s.binary_search(&1);
/// assert!(match r { Ok(1..=4) => true, _ => false, });
/// ```
///
/// If you want to insert an item to a sorted vector, while maintaining
/// sort order:
///
/// ```
/// let mut s = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
/// let num = 42;
/// let idx = s.binary_search(&num).unwrap_or_else(|x| x);
/// s.insert(idx, num);
/// assert_eq!(s, [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn binary_search(&self, x: &T) -> Result<usize, usize>
where T: Ord
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ pub enum LinkagePreference {
RequireStatic,
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash,
RustcEncodable, RustcDecodable, HashStable)]
pub enum NativeLibraryKind {
/// native static library (.a archive)
Expand All @@ -100,7 +100,7 @@ pub enum NativeLibraryKind {
NativeUnknown,
}

#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
pub struct NativeLibrary {
pub kind: NativeLibraryKind,
pub name: Option<Symbol>,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ fn print_backtrace(backtrace: &mut Backtrace) {

impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
fn from(kind: InterpError<'tcx>) -> Self {
let backtrace = match env::var("RUST_CTFE_BACKTRACE") {
let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") {
// Matching `RUST_BACKTRACE` -- we treat "0" the same as "not present".
Ok(ref val) if val != "0" => {
let mut backtrace = Backtrace::new_unresolved();
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2518,7 +2518,7 @@ where
+ HasTyCtxt<'tcx>
+ HasParamEnv<'tcx>,
{
fn of_instance(cx: &C, instance: &ty::Instance<'tcx>) -> Self;
fn of_instance(cx: &C, instance: ty::Instance<'tcx>) -> Self;
fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
fn new_vtable(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
fn new_internal(
Expand All @@ -2538,7 +2538,7 @@ where
+ HasTyCtxt<'tcx>
+ HasParamEnv<'tcx>,
{
fn of_instance(cx: &C, instance: &ty::Instance<'tcx>) -> Self {
fn of_instance(cx: &C, instance: ty::Instance<'tcx>) -> Self {
let sig = instance.fn_sig(cx.tcx());
let sig = cx
.tcx()
Expand Down
7 changes: 5 additions & 2 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1842,7 +1842,8 @@ pub struct VariantDef {
pub ctor_kind: CtorKind,
/// Flags of the variant (e.g. is field list non-exhaustive)?
flags: VariantFlags,
/// Recovered?
/// Variant is obtained as part of recovering from a syntactic error.
/// May be incomplete or bogus.
pub recovered: bool,
}

Expand Down Expand Up @@ -1949,7 +1950,7 @@ pub struct FieldDef {
pub struct AdtDef {
/// `DefId` of the struct, enum or union item.
pub did: DefId,
/// Variants of the ADT. If this is a struct or enum, then there will be a single variant.
/// Variants of the ADT. If this is a struct or union, then there will be a single variant.
pub variants: IndexVec<self::layout::VariantIdx, VariantDef>,
/// Flags of the ADT (e.g. is this a struct? is this non-exhaustive?)
flags: AdtFlags,
Expand Down Expand Up @@ -2565,6 +2566,8 @@ impl<'tcx> AdtDef {
}

impl<'tcx> FieldDef {
/// Returns the type of this field. The `subst` is typically obtained
/// via the second field of `TyKind::AdtDef`.
pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
tcx.type_of(self.did).subst(tcx, subst)
}
Expand Down
14 changes: 12 additions & 2 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ pub enum TyKind<'tcx> {
Never,

/// A tuple type. For example, `(i32, bool)`.
/// Use `TyS::tuple_fields` to iterate over the field types.
Tuple(SubstsRef<'tcx>),

/// The projection of an associated type. For example,
Expand Down Expand Up @@ -1723,8 +1724,8 @@ impl<'tcx> TyS<'tcx> {
})
})
}
ty::Tuple(tys) => tys.iter().any(|ty| {
ty.expect_ty().conservative_is_privately_uninhabited(tcx)
ty::Tuple(..) => self.tuple_fields().any(|ty| {
ty.conservative_is_privately_uninhabited(tcx)
}),
ty::Array(ty, len) => {
match len.try_eval_usize(tcx, ParamEnv::empty()) {
Expand Down Expand Up @@ -2103,6 +2104,15 @@ impl<'tcx> TyS<'tcx> {
}
}

/// Iterates over tuple fields.
/// Panics when called on anything but a tuple.
pub fn tuple_fields(&self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> {
match self.sty {
Tuple(substs) => substs.iter().map(|field| field.expect_ty()),
_ => bug!("tuple_fields called on non-tuple"),
}
}

/// If the type contains variants, returns the valid range of variant indices.
/// FIXME This requires the optimized MIR in the case of generators.
#[inline]
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,15 +845,15 @@ impl<'tcx> ty::TyS<'tcx> {
ty: Ty<'tcx>,
) -> Representability {
match ty.sty {
Tuple(ref ts) => {
Tuple(..) => {
// Find non representable
fold_repr(ts.iter().map(|ty| {
fold_repr(ty.tuple_fields().map(|ty| {
is_type_structurally_recursive(
tcx,
sp,
seen,
representable_cache,
ty.expect_ty(),
ty,
)
}))
}
Expand Down Expand Up @@ -1095,7 +1095,7 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
// state transformation pass
ty::Generator(..) => true,

ty::Tuple(ref tys) => tys.iter().map(|k| k.expect_ty()).any(needs_drop),
ty::Tuple(..) => ty.tuple_fields().any(needs_drop),

// unions don't have destructors because of the child types,
// only if they manually implement `Drop` (handled above).
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
ty::GeneratorWitness(ts) => {
stack.extend(ts.skip_binder().iter().cloned().rev());
}
ty::Tuple(ts) => {
stack.extend(ts.iter().map(|k| k.expect_ty()).rev());
ty::Tuple(..) => {
stack.extend(parent_ty.tuple_fields().rev());
}
ty::FnDef(_, substs) => {
stack.extend(substs.types().rev());
Expand Down
1 change: 1 addition & 0 deletions src/librustc_codegen_ssa/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ bitflags::bitflags! {
}

/// Misc info we load from metadata to persist beyond the tcx.
#[derive(Debug)]
pub struct CrateInfo {
pub panic_runtime: Option<CrateNum>,
pub compiler_builtins: Option<CrateNum>,
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_codegen_ssa/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
_ => {
(bx.get_fn(drop_fn),
FnType::of_instance(&bx, &drop_fn))
FnType::of_instance(&bx, drop_fn))
}
};
helper.do_call(self, &mut bx, fn_ty, drop_fn, args,
Expand Down Expand Up @@ -435,7 +435,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// Obtain the panic entry point.
let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
let instance = ty::Instance::mono(bx.tcx(), def_id);
let fn_ty = FnType::of_instance(&bx, &instance);
let fn_ty = FnType::of_instance(&bx, instance);
let llfn = bx.get_fn(instance);

// Codegen the actual panic invoke/call.
Expand Down Expand Up @@ -552,7 +552,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let def_id =
common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
let instance = ty::Instance::mono(bx.tcx(), def_id);
let fn_ty = FnType::of_instance(&bx, &instance);
let fn_ty = FnType::of_instance(&bx, instance);
let llfn = bx.get_fn(instance);

// Codegen the actual panic invoke/call.
Expand Down
91 changes: 90 additions & 1 deletion src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

use rustc::hir::def::{Res, DefKind};
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::{self, Ty, TyCtxt, layout::VariantIdx};
use rustc::{lint, util};
use hir::Node;
use util::nodemap::HirIdSet;
Expand Down Expand Up @@ -1862,3 +1862,92 @@ impl EarlyLintPass for IncompleteFeatures {
});
}
}

declare_lint! {
pub INVALID_VALUE,
Warn,
"an invalid value is being created (such as a NULL reference)"
}

declare_lint_pass!(InvalidValue => [INVALID_VALUE]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &hir::Expr) {

const ZEROED_PATH: &[Symbol] = &[sym::core, sym::mem, sym::zeroed];
const UININIT_PATH: &[Symbol] = &[sym::core, sym::mem, sym::uninitialized];

/// Return `false` only if we are sure this type does *not*
/// allow zero initialization.
fn ty_maybe_allows_zero_init<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
use rustc::ty::TyKind::*;
match ty.sty {
// Primitive types that don't like 0 as a value.
Ref(..) | FnPtr(..) | Never => false,
Adt(..) if ty.is_box() => false,
// Recurse for some compound types.
Adt(adt_def, substs) if !adt_def.is_union() => {
match adt_def.variants.len() {
0 => false, // Uninhabited enum!
1 => {
// Struct, or enum with exactly one variant.
// Proceed recursively, check all fields.
let variant = &adt_def.variants[VariantIdx::from_u32(0)];
variant.fields.iter().all(|field| {
ty_maybe_allows_zero_init(
tcx,
field.ty(tcx, substs),
)
})
}
_ => true, // Conservative fallback for multi-variant enum.
}
}
Tuple(..) => {
// Proceed recursively, check all fields.
ty.tuple_fields().all(|field| ty_maybe_allows_zero_init(tcx, field))
}
// FIXME: Would be nice to also warn for `NonNull`/`NonZero*`.
// FIXME: *Only for `mem::uninitialized`*, we could also warn for `bool`,
// `char`, and any multivariant enum.
// Conservative fallback.
_ => true,
}
}

if let hir::ExprKind::Call(ref path_expr, ref _args) = expr.node {
if let hir::ExprKind::Path(ref qpath) = path_expr.node {
if let Some(def_id) = cx.tables.qpath_res(qpath, path_expr.hir_id).opt_def_id() {
if cx.match_def_path(def_id, &ZEROED_PATH) ||
cx.match_def_path(def_id, &UININIT_PATH)
{
// This conjures an instance of a type out of nothing,
// using zeroed or uninitialized memory.
// We are extremely conservative with what we warn about.
let conjured_ty = cx.tables.expr_ty(expr);

if !ty_maybe_allows_zero_init(cx.tcx, conjured_ty) {
cx.struct_span_lint(
INVALID_VALUE,
expr.span,
&format!(
"the type `{}` does not permit {}",
conjured_ty,
if cx.match_def_path(def_id, &ZEROED_PATH) {
"zero-initialization"
} else {
"being left uninitialized"
}
),
)
.note("this means that this code causes undefined behavior \
when executed")
.help("use `MaybeUninit` instead")
.emit();
}
}
}
}
}
}
}
1 change: 1 addition & 0 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ macro_rules! late_lint_mod_passes {
UnreachablePub: UnreachablePub,

ExplicitOutlivesRequirements: ExplicitOutlivesRequirements,
InvalidValue: InvalidValue,
]);
)
}
Expand Down
10 changes: 7 additions & 3 deletions src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,15 +385,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
local: mir::Local,
layout: Option<TyLayout<'tcx>>,
) -> InterpResult<'tcx, TyLayout<'tcx>> {
match frame.locals[local].layout.get() {
// `const_prop` runs into this with an invalid (empty) frame, so we
// have to support that case (mostly by skipping all caching).
match frame.locals.get(local).and_then(|state| state.layout.get()) {
None => {
let layout = crate::interpret::operand::from_known_layout(layout, || {
let local_ty = frame.body.local_decls[local].ty;
let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs)?;
self.layout_of(local_ty)
})?;
// Layouts of locals are requested a lot, so we cache them.
frame.locals[local].layout.set(Some(layout));
if let Some(state) = frame.locals.get(local) {
// Layouts of locals are requested a lot, so we cache them.
state.layout.set(Some(layout));
}
Ok(layout)
}
Some(layout) => Ok(layout),
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/interpret/snapshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ impl_stable_hash_for!(enum crate::interpret::eval_context::StackPopCleanup {

#[derive(Eq, PartialEq)]
struct FrameSnapshot<'a, 'tcx> {
instance: &'a ty::Instance<'tcx>,
instance: ty::Instance<'tcx>,
span: Span,
return_to_block: &'a StackPopCleanup,
return_place: Option<Place<(), AllocIdSnapshot<'a>>>,
Expand Down Expand Up @@ -344,7 +344,7 @@ impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
} = self;

FrameSnapshot {
instance,
instance: *instance,
span: *span,
return_to_block,
block,
Expand Down
Loading

0 comments on commit 00ee1b4

Please sign in to comment.