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 8 pull requests #63471

Merged
merged 40 commits into from
Aug 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
740f8db
Add FIXME-s that some types should be transparent
MikailBag Jun 19, 2019
03e95ae
Miri shouldn't look at types
RalfJung Aug 10, 2019
62f1e8a
fix test
RalfJung Aug 10, 2019
440a5c8
rename RUST_CTFE_BACKTRACE to RUSTC_CTFE_BACKTRACE
RalfJung Aug 10, 2019
d809d6e
Derive Debug for CrateInfo
bjorn3 Aug 10, 2019
93839c3
Add an example to show how to insert item to a sorted vec
tesuji Aug 10, 2019
30ba4bd
Use Result::unwrap_or_else instead of matching
tesuji Aug 10, 2019
da6fbb1
add basic lint testing for misuse of mem::zeroed and mem::uninitialized
RalfJung Aug 6, 2019
ca1e94b
warn for more cases
RalfJung Aug 7, 2019
fbd5613
fix a comment
RalfJung Aug 7, 2019
8e6fbbe
add tuple_fields convenience method and use it in a few places
RalfJung Aug 7, 2019
4b062a1
note a FIXME
RalfJung Aug 7, 2019
3972d05
proper doc comment for 'recovered' field of variant
RalfJung Aug 7, 2019
c5a6356
allow the lint if a few UB-demonstrating doc tests
RalfJung Aug 7, 2019
5c77a17
note down some more future plans
RalfJung Aug 7, 2019
0930747
update clippy
RalfJung Aug 11, 2019
65ea7b7
rustdoc: Replace HirVec with slices in doctree
Mark-Simulacrum Aug 10, 2019
19c85a8
Move def_id_to_path to use site in visit_ast
Mark-Simulacrum Aug 10, 2019
00d7bc7
Remove crate_name from DocContext
Mark-Simulacrum Aug 10, 2019
8f80a8d
Use entry API in store_path
Mark-Simulacrum Aug 10, 2019
c574810
Remove ReentrantMutex
Mark-Simulacrum Aug 10, 2019
6be2857
Replace Arc with Rc around external_traits
Mark-Simulacrum Aug 10, 2019
0031951
Store typed Passes
Mark-Simulacrum Aug 10, 2019
0347480
Don't store all traits in DocContext
Mark-Simulacrum Aug 10, 2019
eea2f87
Use a HashSet instead of Vec
Mark-Simulacrum Aug 10, 2019
ade8b02
Remove unnecessary channel
Mark-Simulacrum Aug 10, 2019
dbad77f
Remove thread-local for playground config
Mark-Simulacrum Aug 10, 2019
c250b5f
Remove fmt::Display impls on Markdown structs
Mark-Simulacrum Aug 10, 2019
1aa0964
Drop RefCell from IdMap in markdown rendering
Mark-Simulacrum Aug 10, 2019
3b8a24d
Reduce nesting in externalfiles implementation
Mark-Simulacrum Aug 10, 2019
b204232
Derive Debug for NativeLibrary and NativeLibraryKind
bjorn3 Aug 11, 2019
43de341
Copy ty::Instance instead of passing by reference
Mark-Simulacrum Aug 11, 2019
8862977
Rollup merge of #61969 - MikailBag:master, r=Centril
Mark-Simulacrum Aug 11, 2019
061245e
Rollup merge of #63346 - RalfJung:zeroed-lint, r=eddyb
Mark-Simulacrum Aug 11, 2019
24a8337
Rollup merge of #63433 - RalfJung:miri-call, r=oli-obk
Mark-Simulacrum Aug 11, 2019
8122a01
Rollup merge of #63440 - RalfJung:ctfe-backtrace, r=oli-obk
Mark-Simulacrum Aug 11, 2019
c805a38
Rollup merge of #63441 - bjorn3:patch-1, r=Mark-Simulacrum
Mark-Simulacrum Aug 11, 2019
e16b12f
Rollup merge of #63442 - lzutao:vec-bin-search-insert, r=Mark-Simulacrum
Mark-Simulacrum Aug 11, 2019
86ceab4
Rollup merge of #63453 - Mark-Simulacrum:rustdoc-clean-2, r=Guillaume…
Mark-Simulacrum Aug 11, 2019
4229dc3
Rollup merge of #63464 - Mark-Simulacrum:deref-instance, r=eddyb
Mark-Simulacrum Aug 11, 2019
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
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