Skip to content

Commit 00ee1b4

Browse files
committed
Auto merge of #63471 - Mark-Simulacrum:rollup-m756lnx, r=Mark-Simulacrum
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
2 parents 8a06869 + 4229dc3 commit 00ee1b4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+795
-387
lines changed

Cargo.lock

-1
Original file line numberDiff line numberDiff line change
@@ -3252,7 +3252,6 @@ name = "rustdoc"
32523252
version = "0.0.0"
32533253
dependencies = [
32543254
"minifier 0.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
3255-
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
32563255
"pulldown-cmark 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
32573256
"rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
32583257
"tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",

src/libcore/mem/maybe_uninit.rs

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::mem::ManuallyDrop;
1313
/// ever gets used to access memory:
1414
///
1515
/// ```rust,no_run
16+
/// # #![allow(invalid_value)]
1617
/// use std::mem::{self, MaybeUninit};
1718
///
1819
/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
@@ -27,6 +28,7 @@ use crate::mem::ManuallyDrop;
2728
/// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior:
2829
///
2930
/// ```rust,no_run
31+
/// # #![allow(invalid_value)]
3032
/// use std::mem::{self, MaybeUninit};
3133
///
3234
/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior!
@@ -40,6 +42,7 @@ use crate::mem::ManuallyDrop;
4042
/// which otherwise can hold any *fixed* bit pattern:
4143
///
4244
/// ```rust,no_run
45+
/// # #![allow(invalid_value)]
4346
/// use std::mem::{self, MaybeUninit};
4447
///
4548
/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior!

src/libcore/mem/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,8 @@ pub const fn needs_drop<T>() -> bool {
445445
///
446446
/// *Incorrect* usage of this function: initializing a reference with zero.
447447
///
448-
/// ```no_run
448+
/// ```rust,no_run
449+
/// # #![allow(invalid_value)]
449450
/// use std::mem;
450451
///
451452
/// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior!

src/libcore/slice/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1364,6 +1364,17 @@ impl<T> [T] {
13641364
/// let r = s.binary_search(&1);
13651365
/// assert!(match r { Ok(1..=4) => true, _ => false, });
13661366
/// ```
1367+
///
1368+
/// If you want to insert an item to a sorted vector, while maintaining
1369+
/// sort order:
1370+
///
1371+
/// ```
1372+
/// let mut s = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
1373+
/// let num = 42;
1374+
/// let idx = s.binary_search(&num).unwrap_or_else(|x| x);
1375+
/// s.insert(idx, num);
1376+
/// assert_eq!(s, [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]);
1377+
/// ```
13671378
#[stable(feature = "rust1", since = "1.0.0")]
13681379
pub fn binary_search(&self, x: &T) -> Result<usize, usize>
13691380
where T: Ord

src/librustc/middle/cstore.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ pub enum LinkagePreference {
8787
RequireStatic,
8888
}
8989

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

103-
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
103+
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
104104
pub struct NativeLibrary {
105105
pub kind: NativeLibraryKind,
106106
pub name: Option<Symbol>,

src/librustc/mir/interpret/error.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ fn print_backtrace(backtrace: &mut Backtrace) {
217217

218218
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
219219
fn from(kind: InterpError<'tcx>) -> Self {
220-
let backtrace = match env::var("RUST_CTFE_BACKTRACE") {
220+
let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") {
221221
// Matching `RUST_BACKTRACE` -- we treat "0" the same as "not present".
222222
Ok(ref val) if val != "0" => {
223223
let mut backtrace = Backtrace::new_unresolved();

src/librustc/ty/layout.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2518,7 +2518,7 @@ where
25182518
+ HasTyCtxt<'tcx>
25192519
+ HasParamEnv<'tcx>,
25202520
{
2521-
fn of_instance(cx: &C, instance: &ty::Instance<'tcx>) -> Self;
2521+
fn of_instance(cx: &C, instance: ty::Instance<'tcx>) -> Self;
25222522
fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
25232523
fn new_vtable(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
25242524
fn new_internal(
@@ -2538,7 +2538,7 @@ where
25382538
+ HasTyCtxt<'tcx>
25392539
+ HasParamEnv<'tcx>,
25402540
{
2541-
fn of_instance(cx: &C, instance: &ty::Instance<'tcx>) -> Self {
2541+
fn of_instance(cx: &C, instance: ty::Instance<'tcx>) -> Self {
25422542
let sig = instance.fn_sig(cx.tcx());
25432543
let sig = cx
25442544
.tcx()

src/librustc/ty/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1842,7 +1842,8 @@ pub struct VariantDef {
18421842
pub ctor_kind: CtorKind,
18431843
/// Flags of the variant (e.g. is field list non-exhaustive)?
18441844
flags: VariantFlags,
1845-
/// Recovered?
1845+
/// Variant is obtained as part of recovering from a syntactic error.
1846+
/// May be incomplete or bogus.
18461847
pub recovered: bool,
18471848
}
18481849

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

25672568
impl<'tcx> FieldDef {
2569+
/// Returns the type of this field. The `subst` is typically obtained
2570+
/// via the second field of `TyKind::AdtDef`.
25682571
pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
25692572
tcx.type_of(self.did).subst(tcx, subst)
25702573
}

src/librustc/ty/sty.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ pub enum TyKind<'tcx> {
171171
Never,
172172

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

176177
/// The projection of an associated type. For example,
@@ -1723,8 +1724,8 @@ impl<'tcx> TyS<'tcx> {
17231724
})
17241725
})
17251726
}
1726-
ty::Tuple(tys) => tys.iter().any(|ty| {
1727-
ty.expect_ty().conservative_is_privately_uninhabited(tcx)
1727+
ty::Tuple(..) => self.tuple_fields().any(|ty| {
1728+
ty.conservative_is_privately_uninhabited(tcx)
17281729
}),
17291730
ty::Array(ty, len) => {
17301731
match len.try_eval_usize(tcx, ParamEnv::empty()) {
@@ -2103,6 +2104,15 @@ impl<'tcx> TyS<'tcx> {
21032104
}
21042105
}
21052106

2107+
/// Iterates over tuple fields.
2108+
/// Panics when called on anything but a tuple.
2109+
pub fn tuple_fields(&self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> {
2110+
match self.sty {
2111+
Tuple(substs) => substs.iter().map(|field| field.expect_ty()),
2112+
_ => bug!("tuple_fields called on non-tuple"),
2113+
}
2114+
}
2115+
21062116
/// If the type contains variants, returns the valid range of variant indices.
21072117
/// FIXME This requires the optimized MIR in the case of generators.
21082118
#[inline]

src/librustc/ty/util.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -845,15 +845,15 @@ impl<'tcx> ty::TyS<'tcx> {
845845
ty: Ty<'tcx>,
846846
) -> Representability {
847847
match ty.sty {
848-
Tuple(ref ts) => {
848+
Tuple(..) => {
849849
// Find non representable
850-
fold_repr(ts.iter().map(|ty| {
850+
fold_repr(ty.tuple_fields().map(|ty| {
851851
is_type_structurally_recursive(
852852
tcx,
853853
sp,
854854
seen,
855855
representable_cache,
856-
ty.expect_ty(),
856+
ty,
857857
)
858858
}))
859859
}
@@ -1095,7 +1095,7 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
10951095
// state transformation pass
10961096
ty::Generator(..) => true,
10971097

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

11001100
// unions don't have destructors because of the child types,
11011101
// only if they manually implement `Drop` (handled above).

src/librustc/ty/walk.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
119119
ty::GeneratorWitness(ts) => {
120120
stack.extend(ts.skip_binder().iter().cloned().rev());
121121
}
122-
ty::Tuple(ts) => {
123-
stack.extend(ts.iter().map(|k| k.expect_ty()).rev());
122+
ty::Tuple(..) => {
123+
stack.extend(parent_ty.tuple_fields().rev());
124124
}
125125
ty::FnDef(_, substs) => {
126126
stack.extend(substs.types().rev());

src/librustc_codegen_ssa/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ bitflags::bitflags! {
128128
}
129129

130130
/// Misc info we load from metadata to persist beyond the tcx.
131+
#[derive(Debug)]
131132
pub struct CrateInfo {
132133
pub panic_runtime: Option<CrateNum>,
133134
pub compiler_builtins: Option<CrateNum>,

src/librustc_codegen_ssa/mir/block.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
337337
}
338338
_ => {
339339
(bx.get_fn(drop_fn),
340-
FnType::of_instance(&bx, &drop_fn))
340+
FnType::of_instance(&bx, drop_fn))
341341
}
342342
};
343343
helper.do_call(self, &mut bx, fn_ty, drop_fn, args,
@@ -435,7 +435,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
435435
// Obtain the panic entry point.
436436
let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
437437
let instance = ty::Instance::mono(bx.tcx(), def_id);
438-
let fn_ty = FnType::of_instance(&bx, &instance);
438+
let fn_ty = FnType::of_instance(&bx, instance);
439439
let llfn = bx.get_fn(instance);
440440

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

558558
// Codegen the actual panic invoke/call.

src/librustc_lint/builtin.rs

+90-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
2424
use rustc::hir::def::{Res, DefKind};
2525
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
26-
use rustc::ty::{self, Ty, TyCtxt};
26+
use rustc::ty::{self, Ty, TyCtxt, layout::VariantIdx};
2727
use rustc::{lint, util};
2828
use hir::Node;
2929
use util::nodemap::HirIdSet;
@@ -1862,3 +1862,92 @@ impl EarlyLintPass for IncompleteFeatures {
18621862
});
18631863
}
18641864
}
1865+
1866+
declare_lint! {
1867+
pub INVALID_VALUE,
1868+
Warn,
1869+
"an invalid value is being created (such as a NULL reference)"
1870+
}
1871+
1872+
declare_lint_pass!(InvalidValue => [INVALID_VALUE]);
1873+
1874+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
1875+
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &hir::Expr) {
1876+
1877+
const ZEROED_PATH: &[Symbol] = &[sym::core, sym::mem, sym::zeroed];
1878+
const UININIT_PATH: &[Symbol] = &[sym::core, sym::mem, sym::uninitialized];
1879+
1880+
/// Return `false` only if we are sure this type does *not*
1881+
/// allow zero initialization.
1882+
fn ty_maybe_allows_zero_init<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
1883+
use rustc::ty::TyKind::*;
1884+
match ty.sty {
1885+
// Primitive types that don't like 0 as a value.
1886+
Ref(..) | FnPtr(..) | Never => false,
1887+
Adt(..) if ty.is_box() => false,
1888+
// Recurse for some compound types.
1889+
Adt(adt_def, substs) if !adt_def.is_union() => {
1890+
match adt_def.variants.len() {
1891+
0 => false, // Uninhabited enum!
1892+
1 => {
1893+
// Struct, or enum with exactly one variant.
1894+
// Proceed recursively, check all fields.
1895+
let variant = &adt_def.variants[VariantIdx::from_u32(0)];
1896+
variant.fields.iter().all(|field| {
1897+
ty_maybe_allows_zero_init(
1898+
tcx,
1899+
field.ty(tcx, substs),
1900+
)
1901+
})
1902+
}
1903+
_ => true, // Conservative fallback for multi-variant enum.
1904+
}
1905+
}
1906+
Tuple(..) => {
1907+
// Proceed recursively, check all fields.
1908+
ty.tuple_fields().all(|field| ty_maybe_allows_zero_init(tcx, field))
1909+
}
1910+
// FIXME: Would be nice to also warn for `NonNull`/`NonZero*`.
1911+
// FIXME: *Only for `mem::uninitialized`*, we could also warn for `bool`,
1912+
// `char`, and any multivariant enum.
1913+
// Conservative fallback.
1914+
_ => true,
1915+
}
1916+
}
1917+
1918+
if let hir::ExprKind::Call(ref path_expr, ref _args) = expr.node {
1919+
if let hir::ExprKind::Path(ref qpath) = path_expr.node {
1920+
if let Some(def_id) = cx.tables.qpath_res(qpath, path_expr.hir_id).opt_def_id() {
1921+
if cx.match_def_path(def_id, &ZEROED_PATH) ||
1922+
cx.match_def_path(def_id, &UININIT_PATH)
1923+
{
1924+
// This conjures an instance of a type out of nothing,
1925+
// using zeroed or uninitialized memory.
1926+
// We are extremely conservative with what we warn about.
1927+
let conjured_ty = cx.tables.expr_ty(expr);
1928+
1929+
if !ty_maybe_allows_zero_init(cx.tcx, conjured_ty) {
1930+
cx.struct_span_lint(
1931+
INVALID_VALUE,
1932+
expr.span,
1933+
&format!(
1934+
"the type `{}` does not permit {}",
1935+
conjured_ty,
1936+
if cx.match_def_path(def_id, &ZEROED_PATH) {
1937+
"zero-initialization"
1938+
} else {
1939+
"being left uninitialized"
1940+
}
1941+
),
1942+
)
1943+
.note("this means that this code causes undefined behavior \
1944+
when executed")
1945+
.help("use `MaybeUninit` instead")
1946+
.emit();
1947+
}
1948+
}
1949+
}
1950+
}
1951+
}
1952+
}
1953+
}

src/librustc_lint/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ macro_rules! late_lint_mod_passes {
177177
UnreachablePub: UnreachablePub,
178178

179179
ExplicitOutlivesRequirements: ExplicitOutlivesRequirements,
180+
InvalidValue: InvalidValue,
180181
]);
181182
)
182183
}

src/librustc_mir/interpret/eval_context.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -385,15 +385,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
385385
local: mir::Local,
386386
layout: Option<TyLayout<'tcx>>,
387387
) -> InterpResult<'tcx, TyLayout<'tcx>> {
388-
match frame.locals[local].layout.get() {
388+
// `const_prop` runs into this with an invalid (empty) frame, so we
389+
// have to support that case (mostly by skipping all caching).
390+
match frame.locals.get(local).and_then(|state| state.layout.get()) {
389391
None => {
390392
let layout = crate::interpret::operand::from_known_layout(layout, || {
391393
let local_ty = frame.body.local_decls[local].ty;
392394
let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs)?;
393395
self.layout_of(local_ty)
394396
})?;
395-
// Layouts of locals are requested a lot, so we cache them.
396-
frame.locals[local].layout.set(Some(layout));
397+
if let Some(state) = frame.locals.get(local) {
398+
// Layouts of locals are requested a lot, so we cache them.
399+
state.layout.set(Some(layout));
400+
}
397401
Ok(layout)
398402
}
399403
Some(layout) => Ok(layout),

src/librustc_mir/interpret/snapshot.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ impl_stable_hash_for!(enum crate::interpret::eval_context::StackPopCleanup {
304304

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

346346
FrameSnapshot {
347-
instance,
347+
instance: *instance,
348348
span: *span,
349349
return_to_block,
350350
block,

0 commit comments

Comments
 (0)