From 56ebd57960efd1d96c142b456add67b5257c21fb Mon Sep 17 00:00:00 2001 From: sd234678 Date: Fri, 9 Aug 2019 15:14:05 +0100 Subject: [PATCH 01/30] Remove meaningless comments in src/test --- src/test/pretty/stmt_expr_attributes.rs | 2 -- .../associated-type-projection-from-supertrait.rs | 8 -------- ...ciated-types-binding-to-type-defined-in-supertrait.rs | 6 ------ .../associated-types/associated-types-ref-from-struct.rs | 4 ---- .../ui/higher-rank-trait-bounds/hrtb-type-outlives.rs | 2 -- src/test/ui/hrtb/hrtb-conflate-regions.rs | 1 - src/test/ui/impl-trait/bound-normalization-fail.rs | 2 -- src/test/ui/impl-trait/bound-normalization-pass.rs | 4 ---- src/test/ui/issues/issue-12028.rs | 2 -- src/test/ui/issues/issue-16739.rs | 4 ---- src/test/ui/methods/method-projection.rs | 9 --------- .../regions-outlives-projection-container-hrtb.rs | 7 ------- .../regions/regions-outlives-projection-container-wc.rs | 4 ---- .../ui/regions/regions-outlives-projection-container.rs | 4 ---- .../defaultimpl/specialization-no-default.rs | 8 -------- src/test/ui/specialization/specialization-no-default.rs | 8 -------- src/test/ui/traits/traits-conditional-model-fn.rs | 6 ------ 17 files changed, 81 deletions(-) diff --git a/src/test/pretty/stmt_expr_attributes.rs b/src/test/pretty/stmt_expr_attributes.rs index 02d93238dd643..619cce685d75f 100644 --- a/src/test/pretty/stmt_expr_attributes.rs +++ b/src/test/pretty/stmt_expr_attributes.rs @@ -259,8 +259,6 @@ fn _12() { } } -///////////////// - fn foo() { } fn foo3(_: i32, _: (), _: ()) { } fn qux(_: i32) { } diff --git a/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs b/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs index 06dfe490b8bd3..7e05bcd309a4f 100644 --- a/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs +++ b/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs @@ -12,30 +12,22 @@ pub trait Car : Vehicle { fn chip_paint(&self, c: Self::Color) { } } -/////////////////////////////////////////////////////////////////////////// - struct Black; struct ModelT; impl Vehicle for ModelT { type Color = Black; } impl Car for ModelT { } -/////////////////////////////////////////////////////////////////////////// - struct Blue; struct ModelU; impl Vehicle for ModelU { type Color = Blue; } impl Car for ModelU { } -/////////////////////////////////////////////////////////////////////////// - fn dent(c: C, color: C::Color) { c.chip_paint(color) } fn a() { dent(ModelT, Black); } fn b() { dent(ModelT, Blue); } //~ ERROR mismatched types fn c() { dent(ModelU, Black); } //~ ERROR mismatched types fn d() { dent(ModelU, Blue); } -/////////////////////////////////////////////////////////////////////////// - fn e() { ModelT.chip_paint(Black); } fn f() { ModelT.chip_paint(Blue); } //~ ERROR mismatched types fn g() { ModelU.chip_paint(Black); } //~ ERROR mismatched types diff --git a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs index 653130843c8de..6b2bbbe2e4fb9 100644 --- a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs +++ b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs @@ -11,22 +11,16 @@ pub trait Car : Vehicle { fn honk(&self) { } } -/////////////////////////////////////////////////////////////////////////// - struct Black; struct ModelT; impl Vehicle for ModelT { type Color = Black; } impl Car for ModelT { } -/////////////////////////////////////////////////////////////////////////// - struct Blue; struct ModelU; impl Vehicle for ModelU { type Color = Blue; } impl Car for ModelU { } -/////////////////////////////////////////////////////////////////////////// - fn black_car>(c: C) { } diff --git a/src/test/ui/associated-types/associated-types-ref-from-struct.rs b/src/test/ui/associated-types/associated-types-ref-from-struct.rs index 3ccba289e4b0a..c89f6046e6bf2 100644 --- a/src/test/ui/associated-types/associated-types-ref-from-struct.rs +++ b/src/test/ui/associated-types/associated-types-ref-from-struct.rs @@ -9,8 +9,6 @@ trait Test { fn test(&self, value: &Self::V) -> bool; } -/////////////////////////////////////////////////////////////////////////// - struct TesterPair { tester: T, value: T::V, @@ -26,8 +24,6 @@ impl TesterPair { } } -/////////////////////////////////////////////////////////////////////////// - struct EqU32(u32); impl Test for EqU32 { type V = u32; diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs index a8f38180cc29d..88d396101dba2 100644 --- a/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs +++ b/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs @@ -14,7 +14,6 @@ fn want_foo() { } -/////////////////////////////////////////////////////////////////////////// // Expressed as a where clause struct SomeStruct { @@ -30,7 +29,6 @@ fn one() { want_foo::>(); } -/////////////////////////////////////////////////////////////////////////// // Expressed as shorthand struct AnotherStruct { diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.rs b/src/test/ui/hrtb/hrtb-conflate-regions.rs index 391303676d784..004d62ac513ff 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.rs +++ b/src/test/ui/hrtb/hrtb-conflate-regions.rs @@ -15,7 +15,6 @@ fn want_foo1() { } -/////////////////////////////////////////////////////////////////////////// // Expressed as a where clause struct SomeStruct; diff --git a/src/test/ui/impl-trait/bound-normalization-fail.rs b/src/test/ui/impl-trait/bound-normalization-fail.rs index 9ba7c91fc7201..ce1550568c19d 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.rs +++ b/src/test/ui/impl-trait/bound-normalization-fail.rs @@ -8,7 +8,6 @@ // See issue 60414 -///////////////////////////////////////////// // Reduction to `impl Trait` struct Foo(T); @@ -33,7 +32,6 @@ mod impl_trait { } } -///////////////////////////////////////////// // Same with lifetimes in the trait mod lifetimes { diff --git a/src/test/ui/impl-trait/bound-normalization-pass.rs b/src/test/ui/impl-trait/bound-normalization-pass.rs index 5b634e3106e3b..b0ed4be54b899 100644 --- a/src/test/ui/impl-trait/bound-normalization-pass.rs +++ b/src/test/ui/impl-trait/bound-normalization-pass.rs @@ -8,7 +8,6 @@ // See issue 60414 -///////////////////////////////////////////// // Reduction to `impl Trait` struct Foo(T); @@ -32,7 +31,6 @@ mod impl_trait { } } -///////////////////////////////////////////// // Same with lifetimes in the trait mod lifetimes { @@ -59,7 +57,6 @@ mod lifetimes { } } -///////////////////////////////////////////// // Reduction using `impl Trait` in bindings mod impl_trait_in_bindings { @@ -80,7 +77,6 @@ mod impl_trait_in_bindings { } } -///////////////////////////////////////////// // The same applied to `type Foo = impl Bar`s mod opaque_types { diff --git a/src/test/ui/issues/issue-12028.rs b/src/test/ui/issues/issue-12028.rs index d55354529a9b4..7c2b0d69c8b25 100644 --- a/src/test/ui/issues/issue-12028.rs +++ b/src/test/ui/issues/issue-12028.rs @@ -17,8 +17,6 @@ trait StreamHasher { fn stream(&self) -> Self::S; } -////////////////////////////////////////////////////////////////////////////// - trait StreamHash: Hash { fn input_stream(&self, stream: &mut H::S); } diff --git a/src/test/ui/issues/issue-16739.rs b/src/test/ui/issues/issue-16739.rs index 54ad8fd076e4e..94da2ca5cab81 100644 --- a/src/test/ui/issues/issue-16739.rs +++ b/src/test/ui/issues/issue-16739.rs @@ -16,8 +16,6 @@ impl FnOnce<()> for Foo { extern "rust-call" fn call_once(mut self, _: ()) -> u32 { self.call_mut(()) } } -///////////////////////////////////////////////////////////////////////// - impl FnMut<(u32,)> for Foo { extern "rust-call" fn call_mut(&mut self, (x,): (u32,)) -> u32 { self.foo + x } } @@ -27,8 +25,6 @@ impl FnOnce<(u32,)> for Foo { extern "rust-call" fn call_once(mut self, args: (u32,)) -> u32 { self.call_mut(args) } } -///////////////////////////////////////////////////////////////////////// - impl FnMut<(u32,u32)> for Foo { extern "rust-call" fn call_mut(&mut self, (x, y): (u32, u32)) -> u32 { self.foo + x + y } } diff --git a/src/test/ui/methods/method-projection.rs b/src/test/ui/methods/method-projection.rs index cf33d53968b72..21d983f192ab6 100644 --- a/src/test/ui/methods/method-projection.rs +++ b/src/test/ui/methods/method-projection.rs @@ -2,9 +2,6 @@ // Test that we can use method notation to call methods based on a // projection bound from a trait. Issue #20469. -/////////////////////////////////////////////////////////////////////////// - - trait MakeString { fn make_string(&self) -> String; } @@ -21,8 +18,6 @@ impl MakeString for usize { } } -/////////////////////////////////////////////////////////////////////////// - trait Foo { type F: MakeString; @@ -33,8 +28,6 @@ fn foo(f: &F) -> String { f.get().make_string() } -/////////////////////////////////////////////////////////////////////////// - struct SomeStruct { field: isize, } @@ -47,8 +40,6 @@ impl Foo for SomeStruct { } } -/////////////////////////////////////////////////////////////////////////// - struct SomeOtherStruct { field: usize, } diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs b/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs index 407a4fdf59bb7..cee741184ca2a 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs @@ -6,9 +6,6 @@ #![allow(dead_code)] - -/////////////////////////////////////////////////////////////////////////// - pub trait TheTrait<'b> { type TheAssocType; } @@ -21,8 +18,6 @@ impl<'a,'b> TheTrait<'a> for TheType<'b> { type TheAssocType = &'b (); } -/////////////////////////////////////////////////////////////////////////// - pub struct WithHrAssoc where for<'a> T : TheTrait<'a> { @@ -37,8 +32,6 @@ fn with_assoc<'a,'b>() { //[nll]~^^ ERROR lifetime may not live long enough } -/////////////////////////////////////////////////////////////////////////// - pub trait TheSubTrait : for<'a> TheTrait<'a> { } diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.rs b/src/test/ui/regions/regions-outlives-projection-container-wc.rs index 5037ea536dae9..99965f333907b 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.rs +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.rs @@ -8,8 +8,6 @@ #![allow(dead_code)] -/////////////////////////////////////////////////////////////////////////// - pub trait TheTrait { type TheAssocType; } @@ -22,8 +20,6 @@ impl<'b> TheTrait for TheType<'b> { type TheAssocType = &'b (); } -/////////////////////////////////////////////////////////////////////////// - pub struct WithAssoc where T : TheTrait { m: [T; 0] } diff --git a/src/test/ui/regions/regions-outlives-projection-container.rs b/src/test/ui/regions/regions-outlives-projection-container.rs index 78305c0693905..3afc600becb6e 100644 --- a/src/test/ui/regions/regions-outlives-projection-container.rs +++ b/src/test/ui/regions/regions-outlives-projection-container.rs @@ -5,8 +5,6 @@ #![allow(dead_code)] #![feature(rustc_attrs)] -/////////////////////////////////////////////////////////////////////////// - pub trait TheTrait { type TheAssocType; } @@ -19,8 +17,6 @@ impl<'b> TheTrait for TheType<'b> { type TheAssocType = &'b (); } -/////////////////////////////////////////////////////////////////////////// - pub struct WithAssoc { m: [T; 0] } diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.rs b/src/test/ui/specialization/defaultimpl/specialization-no-default.rs index 7ea79a9a7bf82..37005f839d488 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-no-default.rs +++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.rs @@ -3,9 +3,7 @@ // Check a number of scenarios in which one impl tries to override another, // without correctly using `default`. -//////////////////////////////////////////////////////////////////////////////// // Test 1: one layer of specialization, multiple methods, missing `default` -//////////////////////////////////////////////////////////////////////////////// trait Foo { fn foo(&self); @@ -25,9 +23,7 @@ impl Foo for u32 { fn bar(&self) {} //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 2: one layer of specialization, missing `default` on associated type -//////////////////////////////////////////////////////////////////////////////// trait Bar { type T; @@ -41,9 +37,7 @@ impl Bar for u8 { type T = (); //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 3a: multiple layers of specialization, missing interior `default` -//////////////////////////////////////////////////////////////////////////////// trait Baz { fn baz(&self); @@ -61,10 +55,8 @@ impl Baz for i32 { fn baz(&self) {} //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 3b: multiple layers of specialization, missing interior `default`, // redundant `default` in bottom layer. -//////////////////////////////////////////////////////////////////////////////// trait Redundant { fn redundant(&self); diff --git a/src/test/ui/specialization/specialization-no-default.rs b/src/test/ui/specialization/specialization-no-default.rs index 29afbbd9bf267..57346b26d24ec 100644 --- a/src/test/ui/specialization/specialization-no-default.rs +++ b/src/test/ui/specialization/specialization-no-default.rs @@ -3,9 +3,7 @@ // Check a number of scenarios in which one impl tries to override another, // without correctly using `default`. -//////////////////////////////////////////////////////////////////////////////// // Test 1: one layer of specialization, multiple methods, missing `default` -//////////////////////////////////////////////////////////////////////////////// trait Foo { fn foo(&self); @@ -25,9 +23,7 @@ impl Foo for u32 { fn bar(&self) {} //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 2: one layer of specialization, missing `default` on associated type -//////////////////////////////////////////////////////////////////////////////// trait Bar { type T; @@ -41,9 +37,7 @@ impl Bar for u8 { type T = (); //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 3a: multiple layers of specialization, missing interior `default` -//////////////////////////////////////////////////////////////////////////////// trait Baz { fn baz(&self); @@ -61,10 +55,8 @@ impl Baz for i32 { fn baz(&self) {} //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 3b: multiple layers of specialization, missing interior `default`, // redundant `default` in bottom layer. -//////////////////////////////////////////////////////////////////////////////// trait Redundant { fn redundant(&self); diff --git a/src/test/ui/traits/traits-conditional-model-fn.rs b/src/test/ui/traits/traits-conditional-model-fn.rs index 27ce6d93a8195..afdfb96394bd0 100644 --- a/src/test/ui/traits/traits-conditional-model-fn.rs +++ b/src/test/ui/traits/traits-conditional-model-fn.rs @@ -14,8 +14,6 @@ use go_trait::{Go, GoMut, GoOnce, go, go_mut, go_once}; use std::rc::Rc; use std::cell::Cell; -/////////////////////////////////////////////////////////////////////////// - struct SomeGoableThing { counter: Rc> } @@ -26,8 +24,6 @@ impl Go for SomeGoableThing { } } -/////////////////////////////////////////////////////////////////////////// - struct SomeGoOnceableThing { counter: Rc> } @@ -38,8 +34,6 @@ impl GoOnce for SomeGoOnceableThing { } } -/////////////////////////////////////////////////////////////////////////// - fn main() { let counter = Rc::new(Cell::new(0)); let mut x = SomeGoableThing { counter: counter.clone() }; From b7b4c3a9aafd1f5f19371f046b5c867826c64224 Mon Sep 17 00:00:00 2001 From: sd234678 Date: Fri, 9 Aug 2019 18:43:30 +0100 Subject: [PATCH 02/30] Update stderr files with --bless --- ...ted-type-projection-from-supertrait.stderr | 8 ++-- ...nding-to-type-defined-in-supertrait.stderr | 8 ++-- src/test/ui/hrtb/hrtb-conflate-regions.stderr | 2 +- .../bound-normalization-fail.stderr | 6 +-- src/test/ui/issues/issue-12028.stderr | 2 +- ...s-projection-container-hrtb.migrate.stderr | 20 +++++----- ...lives-projection-container-hrtb.nll.stderr | 4 +- ...ves-projection-container-wc.migrate.stderr | 10 ++--- ...utlives-projection-container-wc.nll.stderr | 2 +- ...gions-outlives-projection-container.stderr | 40 +++++++++---------- .../specialization-no-default.stderr | 10 ++--- .../specialization-no-default.stderr | 10 ++--- 12 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr b/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr index 06f1a1cc64c42..4ba4925ef1b37 100644 --- a/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr +++ b/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/associated-type-projection-from-supertrait.rs:33:23 + --> $DIR/associated-type-projection-from-supertrait.rs:27:23 | LL | fn b() { dent(ModelT, Blue); } | ^^^^ expected struct `Black`, found struct `Blue` @@ -8,7 +8,7 @@ LL | fn b() { dent(ModelT, Blue); } found type `Blue` error[E0308]: mismatched types - --> $DIR/associated-type-projection-from-supertrait.rs:34:23 + --> $DIR/associated-type-projection-from-supertrait.rs:28:23 | LL | fn c() { dent(ModelU, Black); } | ^^^^^ expected struct `Blue`, found struct `Black` @@ -17,7 +17,7 @@ LL | fn c() { dent(ModelU, Black); } found type `Black` error[E0308]: mismatched types - --> $DIR/associated-type-projection-from-supertrait.rs:40:28 + --> $DIR/associated-type-projection-from-supertrait.rs:32:28 | LL | fn f() { ModelT.chip_paint(Blue); } | ^^^^ expected struct `Black`, found struct `Blue` @@ -26,7 +26,7 @@ LL | fn f() { ModelT.chip_paint(Blue); } found type `Blue` error[E0308]: mismatched types - --> $DIR/associated-type-projection-from-supertrait.rs:41:28 + --> $DIR/associated-type-projection-from-supertrait.rs:33:28 | LL | fn g() { ModelU.chip_paint(Black); } | ^^^^^ expected struct `Blue`, found struct `Black` diff --git a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr index 4b548604983df..89c48d50cdb65 100644 --- a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving `::Color == Blue` - --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:37:10 + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:31:10 | LL | fn b() { blue_car(ModelT); } | ^^^^^^^^ expected struct `Black`, found struct `Blue` @@ -7,13 +7,13 @@ LL | fn b() { blue_car(ModelT); } = note: expected type `Black` found type `Blue` note: required by `blue_car` - --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:33:1 + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:27:1 | LL | fn blue_car>(c: C) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving `::Color == Black` - --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:38:10 + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:32:10 | LL | fn c() { black_car(ModelU); } | ^^^^^^^^^ expected struct `Blue`, found struct `Black` @@ -21,7 +21,7 @@ LL | fn c() { black_car(ModelU); } = note: expected type `Blue` found type `Black` note: required by `black_car` - --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:30:1 + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:24:1 | LL | fn black_car>(c: C) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 3fb6baa35e144..20265d66c6f43 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied - --> $DIR/hrtb-conflate-regions.rs:28:10 + --> $DIR/hrtb-conflate-regions.rs:27:10 | LL | fn b() { want_foo2::(); } | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct` diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index b5c8e078f0f13..4811b1e0ff39e 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -7,7 +7,7 @@ LL | #![feature(impl_trait_in_bindings)] = note: `#[warn(incomplete_features)]` on by default error[E0271]: type mismatch resolving ` as FooLike>::Output == ::Assoc` - --> $DIR/bound-normalization-fail.rs:30:32 + --> $DIR/bound-normalization-fail.rs:29:32 | LL | fn foo_fail() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found associated type @@ -17,13 +17,13 @@ LL | fn foo_fail() -> impl FooLike { = note: the return type of a function must have a statically known size error: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope - --> $DIR/bound-normalization-fail.rs:47:41 + --> $DIR/bound-normalization-fail.rs:45:41 | LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving ` as FooLike>::Output == >::Assoc` - --> $DIR/bound-normalization-fail.rs:47:41 + --> $DIR/bound-normalization-fail.rs:45:41 | LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found associated type diff --git a/src/test/ui/issues/issue-12028.stderr b/src/test/ui/issues/issue-12028.stderr index 64694c7a8d0b6..24aa88c3fa379 100644 --- a/src/test/ui/issues/issue-12028.stderr +++ b/src/test/ui/issues/issue-12028.stderr @@ -1,5 +1,5 @@ error[E0284]: type annotations required: cannot resolve `<_ as StreamHasher>::S == ::S` - --> $DIR/issue-12028.rs:29:14 + --> $DIR/issue-12028.rs:27:14 | LL | self.input_stream(&mut stream); | ^^^^^^^^^^^^ diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr index d83301840088d..ed5800940ee31 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr @@ -1,33 +1,33 @@ error[E0491]: in type `&'a WithHrAssoc>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12 | LL | let _: &'a WithHrAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 32:15 - --> $DIR/regions-outlives-projection-container-hrtb.rs:32:15 +note: the pointer is valid for the lifetime 'a as defined on the function body at 27:15 + --> $DIR/regions-outlives-projection-container-hrtb.rs:27:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 32:18 - --> $DIR/regions-outlives-projection-container-hrtb.rs:32:18 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 27:18 + --> $DIR/regions-outlives-projection-container-hrtb.rs:27:18 | LL | fn with_assoc<'a,'b>() { | ^^ error[E0491]: in type `&'a WithHrAssocSub>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12 | LL | let _: &'a WithHrAssocSub> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 53:19 - --> $DIR/regions-outlives-projection-container-hrtb.rs:53:19 +note: the pointer is valid for the lifetime 'a as defined on the function body at 46:19 + --> $DIR/regions-outlives-projection-container-hrtb.rs:46:19 | LL | fn with_assoc_sub<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 53:22 - --> $DIR/regions-outlives-projection-container-hrtb.rs:53:22 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 46:22 + --> $DIR/regions-outlives-projection-container-hrtb.rs:46:22 | LL | fn with_assoc_sub<'a,'b>() { | ^^ diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr index 5028663ba6d04..eed9934be121d 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -10,7 +10,7 @@ LL | let _: &'a WithHrAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12 | LL | fn with_assoc_sub<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr index 9e31065ca4eec..152e6c5600c4e 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr @@ -1,16 +1,16 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container-wc.rs:37:12 + --> $DIR/regions-outlives-projection-container-wc.rs:33:12 | LL | let _: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 31:15 - --> $DIR/regions-outlives-projection-container-wc.rs:31:15 +note: the pointer is valid for the lifetime 'a as defined on the function body at 27:15 + --> $DIR/regions-outlives-projection-container-wc.rs:27:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 31:18 - --> $DIR/regions-outlives-projection-container-wc.rs:31:18 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 27:18 + --> $DIR/regions-outlives-projection-container-wc.rs:27:18 | LL | fn with_assoc<'a,'b>() { | ^^ diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr index 880fe17b740e4..8c54d8da0a063 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-wc.rs:37:12 + --> $DIR/regions-outlives-projection-container-wc.rs:33:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-outlives-projection-container.stderr b/src/test/ui/regions/regions-outlives-projection-container.stderr index b50347ac96427..3c1a98a3c018f 100644 --- a/src/test/ui/regions/regions-outlives-projection-container.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container.stderr @@ -1,67 +1,67 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container.rs:40:13 + --> $DIR/regions-outlives-projection-container.rs:36:13 | LL | let _x: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 32:15 - --> $DIR/regions-outlives-projection-container.rs:32:15 +note: the pointer is valid for the lifetime 'a as defined on the function body at 28:15 + --> $DIR/regions-outlives-projection-container.rs:28:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 32:18 - --> $DIR/regions-outlives-projection-container.rs:32:18 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 28:18 + --> $DIR/regions-outlives-projection-container.rs:28:18 | LL | fn with_assoc<'a,'b>() { | ^^ error[E0491]: in type `&'a WithoutAssoc>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container.rs:58:13 + --> $DIR/regions-outlives-projection-container.rs:54:13 | LL | let _x: &'a WithoutAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 54:18 - --> $DIR/regions-outlives-projection-container.rs:54:18 +note: the pointer is valid for the lifetime 'a as defined on the function body at 50:18 + --> $DIR/regions-outlives-projection-container.rs:50:18 | LL | fn without_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 54:21 - --> $DIR/regions-outlives-projection-container.rs:54:21 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 50:21 + --> $DIR/regions-outlives-projection-container.rs:50:21 | LL | fn without_assoc<'a,'b>() { | ^^ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container.rs:67:12 + --> $DIR/regions-outlives-projection-container.rs:63:12 | LL | call::<&'a WithAssoc>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 62:20 - --> $DIR/regions-outlives-projection-container.rs:62:20 +note: the pointer is valid for the lifetime 'a as defined on the function body at 58:20 + --> $DIR/regions-outlives-projection-container.rs:58:20 | LL | fn call_with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 62:23 - --> $DIR/regions-outlives-projection-container.rs:62:23 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 58:23 + --> $DIR/regions-outlives-projection-container.rs:58:23 | LL | fn call_with_assoc<'a,'b>() { | ^^ error[E0491]: in type `&'a WithoutAssoc>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container.rs:74:12 + --> $DIR/regions-outlives-projection-container.rs:70:12 | LL | call::<&'a WithoutAssoc>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 71:23 - --> $DIR/regions-outlives-projection-container.rs:71:23 +note: the pointer is valid for the lifetime 'a as defined on the function body at 67:23 + --> $DIR/regions-outlives-projection-container.rs:67:23 | LL | fn call_without_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 71:26 - --> $DIR/regions-outlives-projection-container.rs:71:26 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 67:26 + --> $DIR/regions-outlives-projection-container.rs:67:26 | LL | fn call_without_assoc<'a,'b>() { | ^^ diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr index 91690f64d948c..13636b28b126c 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr @@ -1,5 +1,5 @@ error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:22:5 + --> $DIR/specialization-no-default.rs:20:5 | LL | / impl Foo for T { LL | | fn foo(&self) {} @@ -13,7 +13,7 @@ LL | fn foo(&self) {} = note: to specialize, `foo` in the parent `impl` must be marked `default` error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:25:5 + --> $DIR/specialization-no-default.rs:23:5 | LL | / impl Foo for T { LL | | fn foo(&self) {} @@ -27,7 +27,7 @@ LL | fn bar(&self) {} = note: to specialize, `bar` in the parent `impl` must be marked `default` error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:41:5 + --> $DIR/specialization-no-default.rs:37:5 | LL | / impl Bar for T { LL | | type T = u8; @@ -40,7 +40,7 @@ LL | type T = (); = note: to specialize, `T` in the parent `impl` must be marked `default` error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:61:5 + --> $DIR/specialization-no-default.rs:55:5 | LL | / impl Baz for T { LL | | fn baz(&self) {} @@ -53,7 +53,7 @@ LL | fn baz(&self) {} = note: to specialize, `baz` in the parent `impl` must be marked `default` error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:82:5 + --> $DIR/specialization-no-default.rs:74:5 | LL | / impl Redundant for T { LL | | fn redundant(&self) {} diff --git a/src/test/ui/specialization/specialization-no-default.stderr b/src/test/ui/specialization/specialization-no-default.stderr index c39986de38dc2..992e9abbd4ce2 100644 --- a/src/test/ui/specialization/specialization-no-default.stderr +++ b/src/test/ui/specialization/specialization-no-default.stderr @@ -1,5 +1,5 @@ error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:22:5 + --> $DIR/specialization-no-default.rs:20:5 | LL | / impl Foo for T { LL | | fn foo(&self) {} @@ -13,7 +13,7 @@ LL | fn foo(&self) {} = note: to specialize, `foo` in the parent `impl` must be marked `default` error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:25:5 + --> $DIR/specialization-no-default.rs:23:5 | LL | / impl Foo for T { LL | | fn foo(&self) {} @@ -27,7 +27,7 @@ LL | fn bar(&self) {} = note: to specialize, `bar` in the parent `impl` must be marked `default` error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:41:5 + --> $DIR/specialization-no-default.rs:37:5 | LL | / impl Bar for T { LL | | type T = u8; @@ -40,7 +40,7 @@ LL | type T = (); = note: to specialize, `T` in the parent `impl` must be marked `default` error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:61:5 + --> $DIR/specialization-no-default.rs:55:5 | LL | / impl Baz for T { LL | | fn baz(&self) {} @@ -53,7 +53,7 @@ LL | fn baz(&self) {} = note: to specialize, `baz` in the parent `impl` must be marked `default` error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:82:5 + --> $DIR/specialization-no-default.rs:74:5 | LL | / impl Redundant for T { LL | | fn redundant(&self) {} From b21ee493e77a01346a22f982011cff83b150e72c Mon Sep 17 00:00:00 2001 From: sd234678 Date: Fri, 16 Aug 2019 11:48:39 +0100 Subject: [PATCH 03/30] Bless tests with --compare-mode=nll --- ...-outlives-projection-container-hrtb.migrate.nll.stderr | 4 ++-- ...ns-outlives-projection-container-wc.migrate.nll.stderr | 2 +- .../regions-outlives-projection-container.nll.stderr | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr index 5028663ba6d04..eed9934be121d 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -10,7 +10,7 @@ LL | let _: &'a WithHrAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12 | LL | fn with_assoc_sub<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr index 880fe17b740e4..8c54d8da0a063 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-wc.rs:37:12 + --> $DIR/regions-outlives-projection-container-wc.rs:33:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-outlives-projection-container.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container.nll.stderr index ef87d02ec0812..2cf6e245d19f6 100644 --- a/src/test/ui/regions/regions-outlives-projection-container.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container.rs:40:13 + --> $DIR/regions-outlives-projection-container.rs:36:13 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -10,7 +10,7 @@ LL | let _x: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container.rs:58:13 + --> $DIR/regions-outlives-projection-container.rs:54:13 | LL | fn without_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -21,7 +21,7 @@ LL | let _x: &'a WithoutAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container.rs:67:5 + --> $DIR/regions-outlives-projection-container.rs:63:5 | LL | fn call_with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -32,7 +32,7 @@ LL | call::<&'a WithAssoc>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container.rs:74:5 + --> $DIR/regions-outlives-projection-container.rs:70:5 | LL | fn call_without_assoc<'a,'b>() { | -- -- lifetime `'b` defined here From 1613fdae37df044f2c254d25d356b3a57eb61a50 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 6 Jul 2019 18:17:24 +0200 Subject: [PATCH 04/30] Add Rc::get_mut_unchecked, Arc::get_mut_unchecked --- src/liballoc/rc.rs | 31 ++++++++++++++++++++++++++++++- src/liballoc/sync.rs | 31 ++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 0c406a92029a7..22d06180d8d55 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -560,13 +560,42 @@ impl Rc { pub fn get_mut(this: &mut Self) -> Option<&mut T> { if Rc::is_unique(this) { unsafe { - Some(&mut this.ptr.as_mut().value) + Some(Rc::get_mut_unchecked(this)) } } else { None } } + /// Returns a mutable reference to the inner value, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: struct.Rc.html#method.get_mut + /// + /// # Safety + /// + /// There must be no other `Rc` or [`Weak`][weak] pointers to the same value. + /// This is the case for example immediately after `Rc::new`. + /// + /// # Examples + /// + /// ``` + /// use std::rc::Rc; + /// + /// let mut x = Rc::new(String::new()); + /// unsafe { + /// Rc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + #[inline] + #[unstable(feature = "get_mut_unchecked", issue = "0")] + pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { + &mut this.ptr.as_mut().value + } + #[inline] #[stable(feature = "ptr_eq", since = "1.17.0")] /// Returns `true` if the two `Rc`s point to the same value (not diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 7d3b2656a7b90..4cd8e1fd4dd23 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -945,13 +945,42 @@ impl Arc { // the Arc itself to be `mut`, so we're returning the only possible // reference to the inner data. unsafe { - Some(&mut this.ptr.as_mut().data) + Some(Arc::get_mut_unchecked(this)) } } else { None } } + /// Returns a mutable reference to the inner value, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: struct.Arc.html#method.get_mut + /// + /// # Safety + /// + /// There must be no other `Arc` or [`Weak`][weak] pointers to the same value. + /// This is the case for example immediately after `Rc::new`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut x = Arc::new(String::new()); + /// unsafe { + /// Arc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + #[inline] + #[unstable(feature = "get_mut_unchecked", issue = "0")] + pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { + &mut this.ptr.as_mut().data + } + /// Determine whether this is the unique reference (including weak refs) to /// the underlying data. /// From 7b02b9f8ec2850ac687ee5c7d869a626e09d22cb Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 6 Jul 2019 17:19:58 +0200 Subject: [PATCH 05/30] Add new_uninit and assume_init on Box, Rc, and Arc --- src/liballoc/boxed.rs | 61 +++++++++++++++++++++++++++++ src/liballoc/rc.rs | 81 +++++++++++++++++++++++++++++++++++++++ src/liballoc/sync.rs | 81 +++++++++++++++++++++++++++++++++++++++ src/libcore/ptr/unique.rs | 8 ++++ 4 files changed, 231 insertions(+) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index c92db517cad36..5ea7847ca45a6 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -93,6 +93,7 @@ use core::ops::{ use core::ptr::{self, NonNull, Unique}; use core::task::{Context, Poll}; +use crate::alloc; use crate::vec::Vec; use crate::raw_vec::RawVec; use crate::str::from_boxed_utf8_unchecked; @@ -121,6 +122,32 @@ impl Box { box x } + /// Construct a new box with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut five = Box::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// Box::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit() -> Box> { + let layout = alloc::Layout::new::>(); + let ptr = unsafe { alloc::alloc(layout) }; + let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout)); + Box(unique.cast()) + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `x` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -130,6 +157,40 @@ impl Box { } } +impl Box> { + /// Convert to `Box`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut five = Box::::new_uninit(); + /// + /// let five: Box = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// Box::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(this: Self) -> Box { + Box(Box::into_unique(this).cast()) + } +} + impl Box { /// Constructs a box from a raw pointer. /// diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 22d06180d8d55..c902580354dae 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -327,6 +327,43 @@ impl Rc { })) } + /// Construct a new Rc with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// Rc::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit() -> Rc> { + let layout = Layout::new::>>(); + unsafe { + let mut ptr = Global.alloc(layout) + .unwrap_or_else(|_| handle_alloc_error(layout)) + .cast::>>(); + ptr::write(&mut ptr.as_mut().strong, Cell::new(1)); + ptr::write(&mut ptr.as_mut().weak, Cell::new(1)); + Rc { + ptr, + phantom: PhantomData, + } + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `value` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -377,6 +414,48 @@ impl Rc { } } +impl Rc> { + /// Convert to `Rc`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// Rc::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(this: Self) -> Rc { + let ptr = this.ptr.cast(); + mem::forget(this); + Rc { + ptr, + phantom: PhantomData, + } + } +} + impl Rc { /// Consumes the `Rc`, returning the wrapped pointer. /// @@ -582,6 +661,8 @@ impl Rc { /// # Examples /// /// ``` + /// #![feature(get_mut_unchecked)] + /// /// use std::rc::Rc; /// /// let mut x = Rc::new(String::new()); diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 4cd8e1fd4dd23..8c63c81ee2741 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -311,6 +311,43 @@ impl Arc { Self::from_inner(Box::into_raw_non_null(x)) } + /// Construct a Arc box with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// Arc::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit() -> Arc> { + let layout = Layout::new::>>(); + unsafe { + let mut ptr = Global.alloc(layout) + .unwrap_or_else(|_| handle_alloc_error(layout)) + .cast::>>(); + ptr::write(&mut ptr.as_mut().strong, atomic::AtomicUsize::new(1)); + ptr::write(&mut ptr.as_mut().weak, atomic::AtomicUsize::new(1)); + Arc { + ptr, + phantom: PhantomData, + } + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `data` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -361,6 +398,48 @@ impl Arc { } } +impl Arc> { + /// Convert to `Arc`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// Arc::assume_init(five) + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(this: Self) -> Arc { + let ptr = this.ptr.cast(); + mem::forget(this); + Arc { + ptr, + phantom: PhantomData, + } + } +} + impl Arc { /// Consumes the `Arc`, returning the wrapped pointer. /// @@ -967,6 +1046,8 @@ impl Arc { /// # Examples /// /// ``` + /// #![feature(get_mut_unchecked)] + /// /// use std::sync::Arc; /// /// let mut x = Arc::new(String::new()); diff --git a/src/libcore/ptr/unique.rs b/src/libcore/ptr/unique.rs index f0d011fe6b2c0..a739f3b6022db 100644 --- a/src/libcore/ptr/unique.rs +++ b/src/libcore/ptr/unique.rs @@ -122,6 +122,14 @@ impl Unique { pub unsafe fn as_mut(&mut self) -> &mut T { &mut *self.as_ptr() } + + /// Cast to a pointer of another type + #[inline] + pub const fn cast(self) -> Unique { + unsafe { + Unique::new_unchecked(self.as_ptr() as *mut U) + } + } } #[unstable(feature = "ptr_internals", issue = "0")] From bde19240594c229a19ac928b823101965f4a0cd8 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 6 Jul 2019 21:27:55 +0200 Subject: [PATCH 06/30] Add new_uninit_slice and assume_init on Box, Rc, and Arc of [T] --- src/liballoc/boxed.rs | 74 ++++++++++++++++++++++++++++++-- src/liballoc/rc.rs | 98 ++++++++++++++++++++++++++++++++++++++++--- src/liballoc/sync.rs | 98 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 256 insertions(+), 14 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 5ea7847ca45a6..a759260bd8f78 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -91,6 +91,7 @@ use core::ops::{ CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Receiver, Generator, GeneratorState }; use core::ptr::{self, NonNull, Unique}; +use core::slice; use core::task::{Context, Poll}; use crate::alloc; @@ -135,7 +136,7 @@ impl Box { /// // Deferred initialization: /// five.as_mut_ptr().write(5); /// - /// Box::assume_init(five) + /// five.assume_init() /// }; /// /// assert_eq!(*five, 5) @@ -148,6 +149,35 @@ impl Box { Box(unique.cast()) } + /// Construct a new boxed slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut values = Box::::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { + let layout = alloc::Layout::array::>(len).unwrap(); + let ptr = unsafe { alloc::alloc(layout) }; + let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout)); + let slice = unsafe { slice::from_raw_parts_mut(unique.cast().as_ptr(), len) }; + Box(Unique::from(slice)) + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `x` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -179,15 +209,51 @@ impl Box> { /// // Deferred initialization: /// five.as_mut_ptr().write(5); /// - /// Box::assume_init(five) + /// five.assume_init() /// }; /// /// assert_eq!(*five, 5) /// ``` #[unstable(feature = "new_uninit", issue = "0")] #[inline] - pub unsafe fn assume_init(this: Self) -> Box { - Box(Box::into_unique(this).cast()) + pub unsafe fn assume_init(self) -> Box { + Box(Box::into_unique(self).cast()) + } +} + +impl Box<[mem::MaybeUninit]> { + /// Convert to `Box<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the values + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut values = Box::::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(self) -> Box<[T]> { + Box(Unique::new_unchecked(Box::into_raw(self) as _)) } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index c902580354dae..404c86a24da7b 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -343,7 +343,7 @@ impl Rc { /// // Deferred initialization: /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); /// - /// Rc::assume_init(five) + /// five.assume_init() /// }; /// /// assert_eq!(*five, 5) @@ -364,6 +364,50 @@ impl Rc { } } + /// Construct a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { + let data_layout = Layout::array::>(len).unwrap(); + let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); + unsafe { + let allocated_ptr = Global.alloc(layout) + .unwrap_or_else(|_| handle_alloc_error(layout)) + .as_ptr(); + let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; + let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); + let wide_ptr = slice as *mut RcBox<[mem::MaybeUninit]>; + let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); + ptr::write(&mut (*wide_ptr).strong, Cell::new(1)); + ptr::write(&mut (*wide_ptr).weak, Cell::new(1)); + Rc { + ptr: NonNull::new_unchecked(wide_ptr), + phantom: PhantomData, + } + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `value` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -439,16 +483,60 @@ impl Rc> { /// // Deferred initialization: /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); /// - /// Rc::assume_init(five) + /// five.assume_init() /// }; /// /// assert_eq!(*five, 5) /// ``` #[unstable(feature = "new_uninit", issue = "0")] #[inline] - pub unsafe fn assume_init(this: Self) -> Rc { - let ptr = this.ptr.cast(); - mem::forget(this); + pub unsafe fn assume_init(self) -> Rc { + let ptr = self.ptr.cast(); + mem::forget(self); + Rc { + ptr, + phantom: PhantomData, + } + } +} + +impl Rc<[mem::MaybeUninit]> { + /// Convert to `Rc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(self) -> Rc<[T]> { + let ptr = NonNull::new_unchecked(self.ptr.as_ptr() as _); + mem::forget(self); Rc { ptr, phantom: PhantomData, diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 8c63c81ee2741..3f47b9e6c7dae 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -327,7 +327,7 @@ impl Arc { /// // Deferred initialization: /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); /// - /// Arc::assume_init(five) + /// five.assume_init() /// }; /// /// assert_eq!(*five, 5) @@ -348,6 +348,50 @@ impl Arc { } } + /// Construct a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { + let data_layout = Layout::array::>(len).unwrap(); + let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); + unsafe { + let allocated_ptr = Global.alloc(layout) + .unwrap_or_else(|_| handle_alloc_error(layout)) + .as_ptr(); + let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; + let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); + let wide_ptr = slice as *mut ArcInner<[mem::MaybeUninit]>; + let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); + ptr::write(&mut (*wide_ptr).strong, atomic::AtomicUsize::new(1)); + ptr::write(&mut (*wide_ptr).weak, atomic::AtomicUsize::new(1)); + Arc { + ptr: NonNull::new_unchecked(wide_ptr), + phantom: PhantomData, + } + } + } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `data` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -423,16 +467,60 @@ impl Arc> { /// // Deferred initialization: /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); /// - /// Arc::assume_init(five) + /// five.assume_init() /// }; /// /// assert_eq!(*five, 5) /// ``` #[unstable(feature = "new_uninit", issue = "0")] #[inline] - pub unsafe fn assume_init(this: Self) -> Arc { - let ptr = this.ptr.cast(); - mem::forget(this); + pub unsafe fn assume_init(self) -> Arc { + let ptr = self.ptr.cast(); + mem::forget(self); + Arc { + ptr, + phantom: PhantomData, + } + } +} + +impl Arc<[mem::MaybeUninit]> { + /// Convert to `Arc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + #[inline] + pub unsafe fn assume_init(self) -> Arc<[T]> { + let ptr = NonNull::new_unchecked(self.ptr.as_ptr() as _); + mem::forget(self); Arc { ptr, phantom: PhantomData, From 170d933d2f8a7d4787355a86136093af86b03077 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 6 Jul 2019 21:52:15 +0200 Subject: [PATCH 07/30] =?UTF-8?q?Move=20constructors=20of=20boxed/rc?= =?UTF-8?q?=E2=80=99ed=20slices=20to=20matching=20`impl`=20blocks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/liballoc/boxed.rs | 22 ++++++----- src/liballoc/rc.rs | 92 ++++++++++++++++++++++--------------------- src/liballoc/sync.rs | 92 ++++++++++++++++++++++--------------------- 3 files changed, 106 insertions(+), 100 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index a759260bd8f78..6e296907ce8ae 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -149,6 +149,16 @@ impl Box { Box(unique.cast()) } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `x` will be pinned in memory and unable to be moved. + #[stable(feature = "pin", since = "1.33.0")] + #[inline(always)] + pub fn pin(x: T) -> Pin> { + (box x).into() + } +} + +impl Box<[T]> { /// Construct a new boxed slice with uninitialized contents. /// /// # Examples @@ -156,7 +166,7 @@ impl Box { /// ``` /// #![feature(new_uninit)] /// - /// let mut values = Box::::new_uninit_slice(3); + /// let mut values = Box::<[u32]>::new_uninit_slice(3); /// /// let values = unsafe { /// // Deferred initialization: @@ -177,14 +187,6 @@ impl Box { let slice = unsafe { slice::from_raw_parts_mut(unique.cast().as_ptr(), len) }; Box(Unique::from(slice)) } - - /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then - /// `x` will be pinned in memory and unable to be moved. - #[stable(feature = "pin", since = "1.33.0")] - #[inline(always)] - pub fn pin(x: T) -> Pin> { - (box x).into() - } } impl Box> { @@ -237,7 +239,7 @@ impl Box<[mem::MaybeUninit]> { /// ``` /// #![feature(new_uninit)] /// - /// let mut values = Box::::new_uninit_slice(3); + /// let mut values = Box::<[u32]>::new_uninit_slice(3); /// /// let values = unsafe { /// // Deferred initialization: diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 404c86a24da7b..aa1268ec05116 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -364,50 +364,6 @@ impl Rc { } } - /// Construct a new reference-counted slice with uninitialized contents. - /// - /// # Examples - /// - /// ``` - /// #![feature(new_uninit)] - /// #![feature(get_mut_unchecked)] - /// - /// use std::rc::Rc; - /// - /// let mut values = Rc::::new_uninit_slice(3); - /// - /// let values = unsafe { - /// // Deferred initialization: - /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); - /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); - /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); - /// - /// values.assume_init() - /// }; - /// - /// assert_eq!(*values, [1, 2, 3]) - /// ``` - #[unstable(feature = "new_uninit", issue = "0")] - pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { - let data_layout = Layout::array::>(len).unwrap(); - let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); - unsafe { - let allocated_ptr = Global.alloc(layout) - .unwrap_or_else(|_| handle_alloc_error(layout)) - .as_ptr(); - let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; - let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); - let wide_ptr = slice as *mut RcBox<[mem::MaybeUninit]>; - let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); - ptr::write(&mut (*wide_ptr).strong, Cell::new(1)); - ptr::write(&mut (*wide_ptr).weak, Cell::new(1)); - Rc { - ptr: NonNull::new_unchecked(wide_ptr), - phantom: PhantomData, - } - } - } - /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `value` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -458,6 +414,52 @@ impl Rc { } } +impl Rc<[T]> { + /// Construct a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { + let data_layout = Layout::array::>(len).unwrap(); + let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); + unsafe { + let allocated_ptr = Global.alloc(layout) + .unwrap_or_else(|_| handle_alloc_error(layout)) + .as_ptr(); + let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; + let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); + let wide_ptr = slice as *mut RcBox<[mem::MaybeUninit]>; + let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); + ptr::write(&mut (*wide_ptr).strong, Cell::new(1)); + ptr::write(&mut (*wide_ptr).weak, Cell::new(1)); + Rc { + ptr: NonNull::new_unchecked(wide_ptr), + phantom: PhantomData, + } + } + } +} + impl Rc> { /// Convert to `Rc`. /// @@ -519,7 +521,7 @@ impl Rc<[mem::MaybeUninit]> { /// /// use std::rc::Rc; /// - /// let mut values = Rc::::new_uninit_slice(3); + /// let mut values = Rc::<[u32]>::new_uninit_slice(3); /// /// let values = unsafe { /// // Deferred initialization: diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 3f47b9e6c7dae..93441437e45f5 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -348,50 +348,6 @@ impl Arc { } } - /// Construct a new reference-counted slice with uninitialized contents. - /// - /// # Examples - /// - /// ``` - /// #![feature(new_uninit)] - /// #![feature(get_mut_unchecked)] - /// - /// use std::sync::Arc; - /// - /// let mut values = Arc::::new_uninit_slice(3); - /// - /// let values = unsafe { - /// // Deferred initialization: - /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); - /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); - /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); - /// - /// values.assume_init() - /// }; - /// - /// assert_eq!(*values, [1, 2, 3]) - /// ``` - #[unstable(feature = "new_uninit", issue = "0")] - pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { - let data_layout = Layout::array::>(len).unwrap(); - let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); - unsafe { - let allocated_ptr = Global.alloc(layout) - .unwrap_or_else(|_| handle_alloc_error(layout)) - .as_ptr(); - let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; - let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); - let wide_ptr = slice as *mut ArcInner<[mem::MaybeUninit]>; - let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); - ptr::write(&mut (*wide_ptr).strong, atomic::AtomicUsize::new(1)); - ptr::write(&mut (*wide_ptr).weak, atomic::AtomicUsize::new(1)); - Arc { - ptr: NonNull::new_unchecked(wide_ptr), - phantom: PhantomData, - } - } - } - /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then /// `data` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -442,6 +398,52 @@ impl Arc { } } +impl Arc<[T]> { + /// Construct a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "0")] + pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { + let data_layout = Layout::array::>(len).unwrap(); + let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); + unsafe { + let allocated_ptr = Global.alloc(layout) + .unwrap_or_else(|_| handle_alloc_error(layout)) + .as_ptr(); + let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; + let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); + let wide_ptr = slice as *mut ArcInner<[mem::MaybeUninit]>; + let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); + ptr::write(&mut (*wide_ptr).strong, atomic::AtomicUsize::new(1)); + ptr::write(&mut (*wide_ptr).weak, atomic::AtomicUsize::new(1)); + Arc { + ptr: NonNull::new_unchecked(wide_ptr), + phantom: PhantomData, + } + } + } +} + impl Arc> { /// Convert to `Arc`. /// @@ -503,7 +505,7 @@ impl Arc<[mem::MaybeUninit]> { /// /// use std::sync::Arc; /// - /// let mut values = Arc::::new_uninit_slice(3); + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); /// /// let values = unsafe { /// // Deferred initialization: From 4eeb623e9ee35db03ec3281dcfd1c61194312404 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 6 Jul 2019 23:30:32 +0200 Subject: [PATCH 08/30] Fix intra-rustdoc links --- src/liballoc/boxed.rs | 4 ++++ src/liballoc/rc.rs | 6 +++++- src/liballoc/sync.rs | 6 +++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 6e296907ce8ae..3442fce467a70 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -200,6 +200,8 @@ impl Box> { /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// /// # Examples /// /// ``` @@ -234,6 +236,8 @@ impl Box<[mem::MaybeUninit]> { /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// /// # Examples /// /// ``` diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index aa1268ec05116..70911790be24e 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -471,6 +471,8 @@ impl Rc> { /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// /// # Examples /// /// ``` @@ -513,6 +515,8 @@ impl Rc<[mem::MaybeUninit]> { /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// /// # Examples /// /// ``` @@ -745,7 +749,7 @@ impl Rc { /// /// # Safety /// - /// There must be no other `Rc` or [`Weak`][weak] pointers to the same value. + /// There must be no other `Rc` or [`Weak`] pointers to the same value. /// This is the case for example immediately after `Rc::new`. /// /// # Examples diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 93441437e45f5..901d2d831d16b 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -455,6 +455,8 @@ impl Arc> { /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// /// # Examples /// /// ``` @@ -497,6 +499,8 @@ impl Arc<[mem::MaybeUninit]> { /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// /// # Examples /// /// ``` @@ -1130,7 +1134,7 @@ impl Arc { /// /// # Safety /// - /// There must be no other `Arc` or [`Weak`][weak] pointers to the same value. + /// There must be no other `Arc` or [`Weak`] pointers to the same value. /// This is the case for example immediately after `Rc::new`. /// /// # Examples From dab967afdc76904c971d5ac5f5f46e31272a9827 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 16 Jul 2019 09:02:36 +0200 Subject: [PATCH 09/30] Use `alloc::Global` in `Box::new_uninit` --- src/liballoc/boxed.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 3442fce467a70..9f6b16bbef33c 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -94,7 +94,7 @@ use core::ptr::{self, NonNull, Unique}; use core::slice; use core::task::{Context, Poll}; -use crate::alloc; +use crate::alloc::{self, Global, Alloc}; use crate::vec::Vec; use crate::raw_vec::RawVec; use crate::str::from_boxed_utf8_unchecked; @@ -144,9 +144,11 @@ impl Box { #[unstable(feature = "new_uninit", issue = "0")] pub fn new_uninit() -> Box> { let layout = alloc::Layout::new::>(); - let ptr = unsafe { alloc::alloc(layout) }; - let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout)); - Box(unique.cast()) + let ptr = unsafe { + Global.alloc(layout) + .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) + }; + Box(ptr.cast().into()) } /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then From 1141136b90663cf9d5ee6325b2f9e47f02e70746 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 16 Jul 2019 09:17:35 +0200 Subject: [PATCH 10/30] Use ManuallyDrop instead of mem::forget Per https://github.com/rust-lang/rust/pull/62451#discussion_r303197278 --- src/liballoc/rc.rs | 8 ++------ src/liballoc/sync.rs | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 70911790be24e..c76c4b50c64fa 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -495,10 +495,8 @@ impl Rc> { #[unstable(feature = "new_uninit", issue = "0")] #[inline] pub unsafe fn assume_init(self) -> Rc { - let ptr = self.ptr.cast(); - mem::forget(self); Rc { - ptr, + ptr: mem::ManuallyDrop::new(self).ptr.cast(), phantom: PhantomData, } } @@ -541,10 +539,8 @@ impl Rc<[mem::MaybeUninit]> { #[unstable(feature = "new_uninit", issue = "0")] #[inline] pub unsafe fn assume_init(self) -> Rc<[T]> { - let ptr = NonNull::new_unchecked(self.ptr.as_ptr() as _); - mem::forget(self); Rc { - ptr, + ptr: NonNull::new_unchecked(mem::ManuallyDrop::new(self).ptr.as_ptr() as _), phantom: PhantomData, } } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 901d2d831d16b..bc3acd27e8b4d 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -479,10 +479,8 @@ impl Arc> { #[unstable(feature = "new_uninit", issue = "0")] #[inline] pub unsafe fn assume_init(self) -> Arc { - let ptr = self.ptr.cast(); - mem::forget(self); Arc { - ptr, + ptr: mem::ManuallyDrop::new(self).ptr.cast(), phantom: PhantomData, } } @@ -525,10 +523,8 @@ impl Arc<[mem::MaybeUninit]> { #[unstable(feature = "new_uninit", issue = "0")] #[inline] pub unsafe fn assume_init(self) -> Arc<[T]> { - let ptr = NonNull::new_unchecked(self.ptr.as_ptr() as _); - mem::forget(self); Arc { - ptr, + ptr: NonNull::new_unchecked(mem::ManuallyDrop::new(self).ptr.as_ptr() as _), phantom: PhantomData, } } From 78264f5e3c94592ff64aab831499f48497083a91 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 5 Aug 2019 17:45:30 +0200 Subject: [PATCH 11/30] Add tracking issue numbers --- src/liballoc/boxed.rs | 8 ++++---- src/liballoc/rc.rs | 10 +++++----- src/liballoc/sync.rs | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 9f6b16bbef33c..e315b9f3417af 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -141,7 +141,7 @@ impl Box { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Box> { let layout = alloc::Layout::new::>(); let ptr = unsafe { @@ -181,7 +181,7 @@ impl Box<[T]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { let layout = alloc::Layout::array::>(len).unwrap(); let ptr = unsafe { alloc::alloc(layout) }; @@ -220,7 +220,7 @@ impl Box> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Box { Box(Box::into_unique(self).cast()) @@ -258,7 +258,7 @@ impl Box<[mem::MaybeUninit]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Box<[T]> { Box(Unique::new_unchecked(Box::into_raw(self) as _)) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index c76c4b50c64fa..a9aa822173fdc 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -348,7 +348,7 @@ impl Rc { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Rc> { let layout = Layout::new::>>(); unsafe { @@ -438,7 +438,7 @@ impl Rc<[T]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { let data_layout = Layout::array::>(len).unwrap(); let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); @@ -492,7 +492,7 @@ impl Rc> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Rc { Rc { @@ -536,7 +536,7 @@ impl Rc<[mem::MaybeUninit]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Rc<[T]> { Rc { @@ -762,7 +762,7 @@ impl Rc { /// assert_eq!(*x, "foo"); /// ``` #[inline] - #[unstable(feature = "get_mut_unchecked", issue = "0")] + #[unstable(feature = "get_mut_unchecked", issue = "63292")] pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { &mut this.ptr.as_mut().value } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index bc3acd27e8b4d..50fd98508930f 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -332,7 +332,7 @@ impl Arc { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Arc> { let layout = Layout::new::>>(); unsafe { @@ -422,7 +422,7 @@ impl Arc<[T]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { let data_layout = Layout::array::>(len).unwrap(); let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); @@ -476,7 +476,7 @@ impl Arc> { /// /// assert_eq!(*five, 5) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Arc { Arc { @@ -520,7 +520,7 @@ impl Arc<[mem::MaybeUninit]> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[unstable(feature = "new_uninit", issue = "0")] + #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Arc<[T]> { Arc { @@ -1147,7 +1147,7 @@ impl Arc { /// assert_eq!(*x, "foo"); /// ``` #[inline] - #[unstable(feature = "get_mut_unchecked", issue = "0")] + #[unstable(feature = "get_mut_unchecked", issue = "63292")] pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { &mut this.ptr.as_mut().data } From ae1e201a0cd37a48bd3dabf1c643ccd5f53f7680 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 5 Aug 2019 17:50:44 +0200 Subject: [PATCH 12/30] Add a comment on the usage of Layout::new::>() --- src/liballoc/rc.rs | 2 ++ src/liballoc/sync.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index a9aa822173fdc..9d608c886b88e 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -441,6 +441,8 @@ impl Rc<[T]> { #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { let data_layout = Layout::array::>(len).unwrap(); + // This relies on `value` being the last field of `RcBox` in memory, + // so that the layout of `RcBox` is the same as that of `RcBox<()>` followed by `T`. let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); unsafe { let allocated_ptr = Global.alloc(layout) diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 50fd98508930f..1bd177be0d543 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -425,6 +425,8 @@ impl Arc<[T]> { #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { let data_layout = Layout::array::>(len).unwrap(); + // This relies on `value` being the last field of `RcBox` in memory, + // so that the layout of `RcBox` is the same as that of `RcBox<()>` followed by `T`. let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); unsafe { let allocated_ptr = Global.alloc(layout) From 810dfd7cd451c370d0c47d6aa9e62b16292a29e0 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 16 Aug 2019 17:44:24 +0200 Subject: [PATCH 13/30] Reuse more internal Rc and Arc methods --- src/liballoc/rc.rs | 42 +++++++----------------------------------- src/liballoc/sync.rs | 42 +++++++----------------------------------- 2 files changed, 14 insertions(+), 70 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 9d608c886b88e..abb09684260d0 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -350,17 +350,11 @@ impl Rc { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Rc> { - let layout = Layout::new::>>(); unsafe { - let mut ptr = Global.alloc(layout) - .unwrap_or_else(|_| handle_alloc_error(layout)) - .cast::>>(); - ptr::write(&mut ptr.as_mut().strong, Cell::new(1)); - ptr::write(&mut ptr.as_mut().weak, Cell::new(1)); - Rc { - ptr, - phantom: PhantomData, - } + Rc::from_ptr(Rc::allocate_for_unsized( + Layout::new::(), + |mem| mem as *mut RcBox>, + )) } } @@ -440,24 +434,8 @@ impl Rc<[T]> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { - let data_layout = Layout::array::>(len).unwrap(); - // This relies on `value` being the last field of `RcBox` in memory, - // so that the layout of `RcBox` is the same as that of `RcBox<()>` followed by `T`. - let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); unsafe { - let allocated_ptr = Global.alloc(layout) - .unwrap_or_else(|_| handle_alloc_error(layout)) - .as_ptr(); - let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; - let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); - let wide_ptr = slice as *mut RcBox<[mem::MaybeUninit]>; - let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); - ptr::write(&mut (*wide_ptr).strong, Cell::new(1)); - ptr::write(&mut (*wide_ptr).weak, Cell::new(1)); - Rc { - ptr: NonNull::new_unchecked(wide_ptr), - phantom: PhantomData, - } + Rc::from_ptr(Rc::allocate_for_slice(len)) } } } @@ -497,10 +475,7 @@ impl Rc> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Rc { - Rc { - ptr: mem::ManuallyDrop::new(self).ptr.cast(), - phantom: PhantomData, - } + Rc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) } } @@ -541,10 +516,7 @@ impl Rc<[mem::MaybeUninit]> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Rc<[T]> { - Rc { - ptr: NonNull::new_unchecked(mem::ManuallyDrop::new(self).ptr.as_ptr() as _), - phantom: PhantomData, - } + Rc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) } } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 1bd177be0d543..bb4d1499014c1 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -334,17 +334,11 @@ impl Arc { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Arc> { - let layout = Layout::new::>>(); unsafe { - let mut ptr = Global.alloc(layout) - .unwrap_or_else(|_| handle_alloc_error(layout)) - .cast::>>(); - ptr::write(&mut ptr.as_mut().strong, atomic::AtomicUsize::new(1)); - ptr::write(&mut ptr.as_mut().weak, atomic::AtomicUsize::new(1)); - Arc { - ptr, - phantom: PhantomData, - } + Arc::from_ptr(Arc::allocate_for_unsized( + Layout::new::(), + |mem| mem as *mut ArcInner>, + )) } } @@ -424,24 +418,8 @@ impl Arc<[T]> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { - let data_layout = Layout::array::>(len).unwrap(); - // This relies on `value` being the last field of `RcBox` in memory, - // so that the layout of `RcBox` is the same as that of `RcBox<()>` followed by `T`. - let (layout, offset) = Layout::new::>().extend(data_layout).unwrap(); unsafe { - let allocated_ptr = Global.alloc(layout) - .unwrap_or_else(|_| handle_alloc_error(layout)) - .as_ptr(); - let data_ptr = allocated_ptr.add(offset) as *mut mem::MaybeUninit; - let slice: *mut [mem::MaybeUninit] = from_raw_parts_mut(data_ptr, len); - let wide_ptr = slice as *mut ArcInner<[mem::MaybeUninit]>; - let wide_ptr = set_data_ptr(wide_ptr, allocated_ptr); - ptr::write(&mut (*wide_ptr).strong, atomic::AtomicUsize::new(1)); - ptr::write(&mut (*wide_ptr).weak, atomic::AtomicUsize::new(1)); - Arc { - ptr: NonNull::new_unchecked(wide_ptr), - phantom: PhantomData, - } + Arc::from_ptr(Arc::allocate_for_slice(len)) } } } @@ -481,10 +459,7 @@ impl Arc> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Arc { - Arc { - ptr: mem::ManuallyDrop::new(self).ptr.cast(), - phantom: PhantomData, - } + Arc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) } } @@ -525,10 +500,7 @@ impl Arc<[mem::MaybeUninit]> { #[unstable(feature = "new_uninit", issue = "63291")] #[inline] pub unsafe fn assume_init(self) -> Arc<[T]> { - Arc { - ptr: NonNull::new_unchecked(mem::ManuallyDrop::new(self).ptr.as_ptr() as _), - phantom: PhantomData, - } + Arc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) } } From 7a641f7c516ac666c72bf9edfbec8648aa0160c7 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 16 Aug 2019 17:45:44 +0200 Subject: [PATCH 14/30] Relax the safety condition for get_mut_unchecked --- src/liballoc/rc.rs | 6 ++++-- src/liballoc/sync.rs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index abb09684260d0..1509afa48893f 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -719,8 +719,10 @@ impl Rc { /// /// # Safety /// - /// There must be no other `Rc` or [`Weak`] pointers to the same value. - /// This is the case for example immediately after `Rc::new`. + /// Any other `Rc` or [`Weak`] pointers to the same value must not be dereferenced + /// for the duration of the returned borrow. + /// This is trivially the case if no such pointer exist, + /// for example immediately after `Rc::new`. /// /// # Examples /// diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index bb4d1499014c1..078ddc27da9b9 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -1104,8 +1104,10 @@ impl Arc { /// /// # Safety /// - /// There must be no other `Arc` or [`Weak`] pointers to the same value. - /// This is the case for example immediately after `Rc::new`. + /// Any other `Arc` or [`Weak`] pointers to the same value must not be dereferenced + /// for the duration of the returned borrow. + /// This is trivially the case if no such pointer exist, + /// for example immediately after `Arc::new`. /// /// # Examples /// From 5f7716d11bd7df5dbdffdd97a290c671ec1c54d5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Aug 2019 08:39:20 +0200 Subject: [PATCH 15/30] invalid_value: factor finding dangerous inits into separate function --- src/librustc_lint/builtin.rs | 91 +++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 37 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 82160080a44d4..afe81b3123d83 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1876,8 +1876,34 @@ 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]; + #[derive(Debug)] + enum InitKind { Zeroed, Uninit }; + + /// Determine if this expression is a "dangerous initialization". + fn is_dangerous_init(cx: &LateContext<'_, '_>, expr: &hir::Expr) -> Option { + const ZEROED_PATH: &[Symbol] = &[sym::core, sym::mem, sym::zeroed]; + const UININIT_PATH: &[Symbol] = &[sym::core, sym::mem, sym::uninitialized]; + + 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) { + return Some(InitKind::Zeroed); + } + if cx.match_def_path(def_id, &UININIT_PATH) { + return Some(InitKind::Uninit); + } + // FIXME: Also detect `MaybeUninit::zeroed().assume_init()` and + // `MaybeUninit::uninit().assume_init()`. + // FIXME: Also detect `transmute` from 0. + } + } + } + + None + } /// Information about why a type cannot be initialized this way. /// Contains an error message and optionally a span to point at. @@ -1933,42 +1959,33 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { } } - 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 let Some((msg, span)) = ty_find_init_error(cx.tcx, conjured_ty) { - let mut err = 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" - } - ), - ); - err.span_label(expr.span, - "this code causes undefined behavior when executed"); - err.span_label(expr.span, "help: use `MaybeUninit` instead"); - if let Some(span) = span { - err.span_note(span, &msg); - } else { - err.note(&msg); - } - err.emit(); - } - } + if let Some(init) = is_dangerous_init(cx, expr) { + // 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 let Some((msg, span)) = ty_find_init_error(cx.tcx, conjured_ty) { + let mut err = cx.struct_span_lint( + INVALID_VALUE, + expr.span, + &format!( + "the type `{}` does not permit {}", + conjured_ty, + match init { + InitKind::Zeroed => "zero-initialization", + InitKind::Uninit => "being left uninitialized", + }, + ), + ); + err.span_label(expr.span, + "this code causes undefined behavior when executed"); + err.span_label(expr.span, "help: use `MaybeUninit` instead"); + if let Some(span) = span { + err.span_note(span, &msg); + } else { + err.note(&msg); } + err.emit(); } } } From 25d8a0a3514c3d8dd8362d0eb68272dc50168af3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Aug 2019 09:39:25 +0200 Subject: [PATCH 16/30] warn about uninit bools and chars --- src/librustc_lint/builtin.rs | 21 ++++++++++----- src/test/ui/lint/uninitialized-zeroed.rs | 3 +++ src/test/ui/lint/uninitialized-zeroed.stderr | 28 +++++++++++++++++++- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index afe81b3123d83..14bd9a381f0b3 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1876,7 +1876,7 @@ 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) { - #[derive(Debug)] + #[derive(Debug, Copy, Clone, PartialEq)] enum InitKind { Zeroed, Uninit }; /// Determine if this expression is a "dangerous initialization". @@ -1911,7 +1911,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { /// Return `Some` only if we are sure this type does *not* /// allow zero initialization. - fn ty_find_init_error<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { + fn ty_find_init_error<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + init: InitKind, + ) -> Option { use rustc::ty::TyKind::*; match ty.sty { // Primitive types that don't like 0 as a value. @@ -1919,6 +1923,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { Adt(..) if ty.is_box() => Some((format!("`Box` must be non-null"), None)), FnPtr(..) => Some((format!("Function pointers must be non-null"), None)), Never => Some((format!("The never type (`!`) has no valid value"), None)), + // Primitive types with other constraints + Bool if init == InitKind::Uninit => + Some((format!("Booleans must be `true` or `false`"), None)), + Char if init == InitKind::Uninit => + Some((format!("Characters must be a valid unicode codepoint"), None)), // Recurse for some compound types. Adt(adt_def, substs) if !adt_def.is_union() => { match adt_def.variants.len() { @@ -1931,6 +1940,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { ty_find_init_error( tcx, field.ty(tcx, substs), + init, ).map(|(mut msg, span)| if span.is_none() { // Point to this field, should be helpful for figuring // out where the source of the error is. @@ -1949,11 +1959,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { } Tuple(..) => { // Proceed recursively, check all fields. - ty.tuple_fields().find_map(|field| ty_find_init_error(tcx, field)) + ty.tuple_fields().find_map(|field| ty_find_init_error(tcx, field, init)) } // 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. + // FIXME: *Only for `mem::uninitialized`*, we could also warn for multivariant enum. // Conservative fallback. _ => None, } @@ -1964,7 +1973,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { // using zeroed or uninitialized memory. // We are extremely conservative with what we warn about. let conjured_ty = cx.tables.expr_ty(expr); - if let Some((msg, span)) = ty_find_init_error(cx.tcx, conjured_ty) { + if let Some((msg, span)) = ty_find_init_error(cx.tcx, conjured_ty, init) { let mut err = cx.struct_span_lint( INVALID_VALUE, expr.span, diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/uninitialized-zeroed.rs index d816479bbbbe3..aafc8507af616 100644 --- a/src/test/ui/lint/uninitialized-zeroed.rs +++ b/src/test/ui/lint/uninitialized-zeroed.rs @@ -56,6 +56,9 @@ fn main() { let _val: Wrap<(RefPair, i32)> = mem::zeroed(); //~ ERROR: does not permit zero-initialization let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + let _val: Wrap = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + // Some types that should work just fine. let _val: Option<&'static i32> = mem::zeroed(); let _val: Option = mem::zeroed(); diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index 1b15fc2152559..d8a4bf0b04953 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -285,5 +285,31 @@ note: References must be non-null (in this struct field) LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 22 previous errors +error: the type `bool` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:59:26 + | +LL | let _val: bool = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: Booleans must be `true` or `false` + +error: the type `Wrap` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:60:32 + | +LL | let _val: Wrap = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | +note: Characters must be a valid unicode codepoint (in this struct field) + --> $DIR/uninitialized-zeroed.rs:16:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ + +error: aborting due to 24 previous errors From 0d242b3f9098fe13518da4442692f29915cf2da4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Aug 2019 10:13:47 +0200 Subject: [PATCH 17/30] invalid_value: warn for types with custom valid range --- src/librustc_lint/builtin.rs | 20 ++++- src/test/ui/lint/uninitialized-zeroed.rs | 21 ++++- src/test/ui/lint/uninitialized-zeroed.stderr | 91 ++++++++++++++------ 3 files changed, 102 insertions(+), 30 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 14bd9a381f0b3..f4f6bd37774c7 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1928,8 +1928,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { Some((format!("Booleans must be `true` or `false`"), None)), Char if init == InitKind::Uninit => Some((format!("Characters must be a valid unicode codepoint"), None)), - // Recurse for some compound types. + // Recurse and checks for some compound types. Adt(adt_def, substs) if !adt_def.is_union() => { + // First check f this ADT has a layout attribute (like `NonNull` and friends). + use std::ops::Bound; + match tcx.layout_scalar_valid_range(adt_def.did) { + // We exploit here that `layout_scalar_valid_range` will never + // return `Bound::Excluded`. (And we have tests checking that we + // handle the attribute correctly.) + (Bound::Included(lo), _) if lo > 0 => + return Some((format!("{} must be non-null", ty), None)), + (Bound::Included(_), _) | (_, Bound::Included(_)) + if init == InitKind::Uninit => + return Some(( + format!("{} must be initialized inside its custom valid range", ty), + None, + )), + _ => {} + } + // Now, recurse. match adt_def.variants.len() { 0 => Some((format!("0-variant enums have no valid value"), None)), 1 => { @@ -1961,7 +1978,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { // Proceed recursively, check all fields. ty.tuple_fields().find_map(|field| ty_find_init_error(tcx, field, init)) } - // FIXME: Would be nice to also warn for `NonNull`/`NonZero*`. // FIXME: *Only for `mem::uninitialized`*, we could also warn for multivariant enum. // Conservative fallback. _ => None, diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/uninitialized-zeroed.rs index aafc8507af616..237f2c0141dce 100644 --- a/src/test/ui/lint/uninitialized-zeroed.rs +++ b/src/test/ui/lint/uninitialized-zeroed.rs @@ -2,7 +2,7 @@ // This test checks that calling `mem::{uninitialized,zeroed}` with certain types results // in a lint. -#![feature(never_type)] +#![feature(never_type, rustc_attrs)] #![allow(deprecated)] #![deny(invalid_value)] @@ -16,6 +16,11 @@ struct RefPair((&'static i32, i32)); struct Wrap { wrapped: T } enum WrapEnum { Wrapped(T) } +#[rustc_layout_scalar_valid_range_start(0)] +#[rustc_layout_scalar_valid_range_end(128)] +#[repr(transparent)] +pub(crate) struct NonBig(u64); + #[allow(unused)] fn generic() { unsafe { @@ -29,6 +34,7 @@ fn generic() { fn main() { unsafe { + // Things that cannot even be zero. let _val: ! = mem::zeroed(); //~ ERROR: does not permit zero-initialization let _val: ! = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized @@ -56,14 +62,23 @@ fn main() { let _val: Wrap<(RefPair, i32)> = mem::zeroed(); //~ ERROR: does not permit zero-initialization let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + let _val: Vec = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Vec = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Things that can be zero, but not uninit. + let _val: bool = mem::zeroed(); let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap = mem::zeroed(); let _val: Wrap = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - // Some types that should work just fine. + let _val: NonBig = mem::zeroed(); + let _val: NonBig = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Some more types that should work just fine. let _val: Option<&'static i32> = mem::zeroed(); let _val: Option = mem::zeroed(); let _val: MaybeUninit<&'static i32> = mem::zeroed(); - let _val: bool = mem::zeroed(); let _val: i32 = mem::zeroed(); } } diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index d8a4bf0b04953..c5006345e52f1 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -1,5 +1,5 @@ error: the type `&'static T` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:22:32 + --> $DIR/uninitialized-zeroed.rs:27:32 | LL | let _val: &'static T = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #![deny(invalid_value)] = note: References must be non-null error: the type `&'static T` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:23:32 + --> $DIR/uninitialized-zeroed.rs:28:32 | LL | let _val: &'static T = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | let _val: &'static T = mem::uninitialized(); = note: References must be non-null error: the type `Wrap<&'static T>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:25:38 + --> $DIR/uninitialized-zeroed.rs:30:38 | LL | let _val: Wrap<&'static T> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap<&'static T>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:26:38 + --> $DIR/uninitialized-zeroed.rs:31:38 | LL | let _val: Wrap<&'static T> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `!` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:32:23 + --> $DIR/uninitialized-zeroed.rs:38:23 | LL | let _val: ! = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | let _val: ! = mem::zeroed(); = note: The never type (`!`) has no valid value error: the type `!` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:33:23 + --> $DIR/uninitialized-zeroed.rs:39:23 | LL | let _val: ! = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | let _val: ! = mem::uninitialized(); = note: The never type (`!`) has no valid value error: the type `(i32, !)` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:35:30 + --> $DIR/uninitialized-zeroed.rs:41:30 | LL | let _val: (i32, !) = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _val: (i32, !) = mem::zeroed(); = note: The never type (`!`) has no valid value error: the type `(i32, !)` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:36:30 + --> $DIR/uninitialized-zeroed.rs:42:30 | LL | let _val: (i32, !) = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | let _val: (i32, !) = mem::uninitialized(); = note: The never type (`!`) has no valid value error: the type `Void` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:38:26 + --> $DIR/uninitialized-zeroed.rs:44:26 | LL | let _val: Void = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | let _val: Void = mem::zeroed(); = note: 0-variant enums have no valid value error: the type `Void` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:39:26 + --> $DIR/uninitialized-zeroed.rs:45:26 | LL | let _val: Void = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | let _val: Void = mem::uninitialized(); = note: 0-variant enums have no valid value error: the type `&'static i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:41:34 + --> $DIR/uninitialized-zeroed.rs:47:34 | LL | let _val: &'static i32 = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL | let _val: &'static i32 = mem::zeroed(); = note: References must be non-null error: the type `&'static i32` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:42:34 + --> $DIR/uninitialized-zeroed.rs:48:34 | LL | let _val: &'static i32 = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | let _val: &'static i32 = mem::uninitialized(); = note: References must be non-null error: the type `Ref` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:44:25 + --> $DIR/uninitialized-zeroed.rs:50:25 | LL | let _val: Ref = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -159,7 +159,7 @@ LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `Ref` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:45:25 + --> $DIR/uninitialized-zeroed.rs:51:25 | LL | let _val: Ref = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -174,7 +174,7 @@ LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `fn()` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:47:26 + --> $DIR/uninitialized-zeroed.rs:53:26 | LL | let _val: fn() = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -185,7 +185,7 @@ LL | let _val: fn() = mem::zeroed(); = note: Function pointers must be non-null error: the type `fn()` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:48:26 + --> $DIR/uninitialized-zeroed.rs:54:26 | LL | let _val: fn() = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +196,7 @@ LL | let _val: fn() = mem::uninitialized(); = note: Function pointers must be non-null error: the type `Wrap` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:50:32 + --> $DIR/uninitialized-zeroed.rs:56:32 | LL | let _val: Wrap = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -211,7 +211,7 @@ LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:51:32 + --> $DIR/uninitialized-zeroed.rs:57:32 | LL | let _val: Wrap = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -226,7 +226,7 @@ LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `WrapEnum` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:53:36 + --> $DIR/uninitialized-zeroed.rs:59:36 | LL | let _val: WrapEnum = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -241,7 +241,7 @@ LL | enum WrapEnum { Wrapped(T) } | ^ error: the type `WrapEnum` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:54:36 + --> $DIR/uninitialized-zeroed.rs:60:36 | LL | let _val: WrapEnum = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -256,7 +256,7 @@ LL | enum WrapEnum { Wrapped(T) } | ^ error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:56:42 + --> $DIR/uninitialized-zeroed.rs:62:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -271,7 +271,7 @@ LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:57:42 + --> $DIR/uninitialized-zeroed.rs:63:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -285,8 +285,38 @@ note: References must be non-null (in this struct field) LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ +error: the type `std::vec::Vec` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:65:30 + | +LL | let _val: Vec = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | +note: std::ptr::Unique must be non-null (in this struct field) + --> $SRC_DIR/liballoc/raw_vec.rs:LL:COL + | +LL | ptr: Unique, + | ^^^^^^^^^^^^^^ + +error: the type `std::vec::Vec` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:66:30 + | +LL | let _val: Vec = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | +note: std::ptr::Unique must be non-null (in this struct field) + --> $SRC_DIR/liballoc/raw_vec.rs:LL:COL + | +LL | ptr: Unique, + | ^^^^^^^^^^^^^^ + error: the type `bool` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:59:26 + --> $DIR/uninitialized-zeroed.rs:70:26 | LL | let _val: bool = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -297,7 +327,7 @@ LL | let _val: bool = mem::uninitialized(); = note: Booleans must be `true` or `false` error: the type `Wrap` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:60:32 + --> $DIR/uninitialized-zeroed.rs:73:32 | LL | let _val: Wrap = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -311,5 +341,16 @@ note: Characters must be a valid unicode codepoint (in this struct field) LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ -error: aborting due to 24 previous errors +error: the type `NonBig` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:76:28 + | +LL | let _val: NonBig = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: NonBig must be initialized inside its custom valid range + +error: aborting due to 27 previous errors From 9ab1d5c73a67e0936f71abe6eaccef8d0b4bd25e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Aug 2019 10:20:18 +0200 Subject: [PATCH 18/30] multi-variant enums are tricky --- src/librustc_lint/builtin.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index f4f6bd37774c7..74cff1bab0f81 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1971,6 +1971,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { }) }) } + // Multi-variant enums are tricky: if all but one variant are + // uninhabited, we might actually do layout like for a single-variant + // enum, and then even leaving them uninitialized could be okay. _ => None, // Conservative fallback for multi-variant enum. } } @@ -1978,7 +1981,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { // Proceed recursively, check all fields. ty.tuple_fields().find_map(|field| ty_find_init_error(tcx, field, init)) } - // FIXME: *Only for `mem::uninitialized`*, we could also warn for multivariant enum. // Conservative fallback. _ => None, } From a9efa738ab4e9517a86314f5c0787efef7d8e2a9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Aug 2019 11:48:30 +0200 Subject: [PATCH 19/30] invalid_value: also detect transmute-from-0 (seen in the wild) --- src/librustc_lint/builtin.rs | 38 ++++++- src/test/ui/lint/uninitialized-zeroed.rs | 6 + src/test/ui/lint/uninitialized-zeroed.stderr | 111 ++++++++++++------- 3 files changed, 110 insertions(+), 45 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 74cff1bab0f81..877dc43fb7b9b 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1879,12 +1879,38 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { #[derive(Debug, Copy, Clone, PartialEq)] enum InitKind { Zeroed, Uninit }; + /// Information about why a type cannot be initialized this way. + /// Contains an error message and optionally a span to point at. + type InitError = (String, Option); + + /// Test if this constant is all-0. + fn is_zero(expr: &hir::Expr) -> bool { + use hir::ExprKind::*; + use syntax::ast::LitKind::*; + match &expr.node { + Lit(lit) => + if let Int(i, _) = lit.node { + i == 0 + } else { + false + }, + Tup(tup) => + tup.iter().all(is_zero), + _ => + false + } + } + /// Determine if this expression is a "dangerous initialization". fn is_dangerous_init(cx: &LateContext<'_, '_>, expr: &hir::Expr) -> Option { const ZEROED_PATH: &[Symbol] = &[sym::core, sym::mem, sym::zeroed]; const UININIT_PATH: &[Symbol] = &[sym::core, sym::mem, sym::uninitialized]; + // `transmute` is inside an anonymous module (the `extern` block?); + // `Invalid` represents the empty string and matches that. + const TRANSMUTE_PATH: &[Symbol] = + &[sym::core, sym::intrinsics, kw::Invalid, sym::transmute]; - if let hir::ExprKind::Call(ref path_expr, ref _args) = expr.node { + 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() @@ -1895,9 +1921,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { if cx.match_def_path(def_id, &UININIT_PATH) { return Some(InitKind::Uninit); } + if cx.match_def_path(def_id, &TRANSMUTE_PATH) { + if is_zero(&args[0]) { + return Some(InitKind::Zeroed); + } + } // FIXME: Also detect `MaybeUninit::zeroed().assume_init()` and // `MaybeUninit::uninit().assume_init()`. - // FIXME: Also detect `transmute` from 0. } } } @@ -1905,10 +1935,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { None } - /// Information about why a type cannot be initialized this way. - /// Contains an error message and optionally a span to point at. - type InitError = (String, Option); - /// Return `Some` only if we are sure this type does *not* /// allow zero initialization. fn ty_find_init_error<'tcx>( diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/uninitialized-zeroed.rs index 237f2c0141dce..54e1210768cd2 100644 --- a/src/test/ui/lint/uninitialized-zeroed.rs +++ b/src/test/ui/lint/uninitialized-zeroed.rs @@ -7,6 +7,7 @@ #![deny(invalid_value)] use std::mem::{self, MaybeUninit}; +use std::num::NonZeroU32; enum Void {} @@ -75,6 +76,11 @@ fn main() { let _val: NonBig = mem::zeroed(); let _val: NonBig = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + // Transmute-from-0 + let _val: &'static i32 = mem::transmute(0usize); //~ ERROR: does not permit zero-initialization + let _val: &'static [i32] = mem::transmute((0usize, 0usize)); //~ ERROR: does not permit zero-initialization + let _val: NonZeroU32 = mem::transmute(0); //~ ERROR: does not permit zero-initialization + // Some more types that should work just fine. let _val: Option<&'static i32> = mem::zeroed(); let _val: Option = mem::zeroed(); diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index c5006345e52f1..90a51ba57e96f 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -1,5 +1,5 @@ error: the type `&'static T` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:27:32 + --> $DIR/uninitialized-zeroed.rs:28:32 | LL | let _val: &'static T = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #![deny(invalid_value)] = note: References must be non-null error: the type `&'static T` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:28:32 + --> $DIR/uninitialized-zeroed.rs:29:32 | LL | let _val: &'static T = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | let _val: &'static T = mem::uninitialized(); = note: References must be non-null error: the type `Wrap<&'static T>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:30:38 + --> $DIR/uninitialized-zeroed.rs:31:38 | LL | let _val: Wrap<&'static T> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -35,13 +35,13 @@ LL | let _val: Wrap<&'static T> = mem::zeroed(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:17:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap<&'static T>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:31:38 + --> $DIR/uninitialized-zeroed.rs:32:38 | LL | let _val: Wrap<&'static T> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -50,13 +50,13 @@ LL | let _val: Wrap<&'static T> = mem::uninitialized(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:17:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `!` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:38:23 + --> $DIR/uninitialized-zeroed.rs:39:23 | LL | let _val: ! = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | let _val: ! = mem::zeroed(); = note: The never type (`!`) has no valid value error: the type `!` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:39:23 + --> $DIR/uninitialized-zeroed.rs:40:23 | LL | let _val: ! = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | let _val: ! = mem::uninitialized(); = note: The never type (`!`) has no valid value error: the type `(i32, !)` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:41:30 + --> $DIR/uninitialized-zeroed.rs:42:30 | LL | let _val: (i32, !) = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _val: (i32, !) = mem::zeroed(); = note: The never type (`!`) has no valid value error: the type `(i32, !)` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:42:30 + --> $DIR/uninitialized-zeroed.rs:43:30 | LL | let _val: (i32, !) = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | let _val: (i32, !) = mem::uninitialized(); = note: The never type (`!`) has no valid value error: the type `Void` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:44:26 + --> $DIR/uninitialized-zeroed.rs:45:26 | LL | let _val: Void = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | let _val: Void = mem::zeroed(); = note: 0-variant enums have no valid value error: the type `Void` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:45:26 + --> $DIR/uninitialized-zeroed.rs:46:26 | LL | let _val: Void = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | let _val: Void = mem::uninitialized(); = note: 0-variant enums have no valid value error: the type `&'static i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:47:34 + --> $DIR/uninitialized-zeroed.rs:48:34 | LL | let _val: &'static i32 = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL | let _val: &'static i32 = mem::zeroed(); = note: References must be non-null error: the type `&'static i32` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:48:34 + --> $DIR/uninitialized-zeroed.rs:49:34 | LL | let _val: &'static i32 = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | let _val: &'static i32 = mem::uninitialized(); = note: References must be non-null error: the type `Ref` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:50:25 + --> $DIR/uninitialized-zeroed.rs:51:25 | LL | let _val: Ref = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -153,13 +153,13 @@ LL | let _val: Ref = mem::zeroed(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:13:12 + --> $DIR/uninitialized-zeroed.rs:14:12 | LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `Ref` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:51:25 + --> $DIR/uninitialized-zeroed.rs:52:25 | LL | let _val: Ref = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -168,13 +168,13 @@ LL | let _val: Ref = mem::uninitialized(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:13:12 + --> $DIR/uninitialized-zeroed.rs:14:12 | LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `fn()` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:53:26 + --> $DIR/uninitialized-zeroed.rs:54:26 | LL | let _val: fn() = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -185,7 +185,7 @@ LL | let _val: fn() = mem::zeroed(); = note: Function pointers must be non-null error: the type `fn()` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:54:26 + --> $DIR/uninitialized-zeroed.rs:55:26 | LL | let _val: fn() = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +196,7 @@ LL | let _val: fn() = mem::uninitialized(); = note: Function pointers must be non-null error: the type `Wrap` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:56:32 + --> $DIR/uninitialized-zeroed.rs:57:32 | LL | let _val: Wrap = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -205,13 +205,13 @@ LL | let _val: Wrap = mem::zeroed(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:17:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:57:32 + --> $DIR/uninitialized-zeroed.rs:58:32 | LL | let _val: Wrap = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -220,13 +220,13 @@ LL | let _val: Wrap = mem::uninitialized(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:17:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `WrapEnum` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:59:36 + --> $DIR/uninitialized-zeroed.rs:60:36 | LL | let _val: WrapEnum = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -235,13 +235,13 @@ LL | let _val: WrapEnum = mem::zeroed(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:17:28 + --> $DIR/uninitialized-zeroed.rs:18:28 | LL | enum WrapEnum { Wrapped(T) } | ^ error: the type `WrapEnum` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:60:36 + --> $DIR/uninitialized-zeroed.rs:61:36 | LL | let _val: WrapEnum = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -250,13 +250,13 @@ LL | let _val: WrapEnum = mem::uninitialized(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:17:28 + --> $DIR/uninitialized-zeroed.rs:18:28 | LL | enum WrapEnum { Wrapped(T) } | ^ error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:62:42 + --> $DIR/uninitialized-zeroed.rs:63:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -265,13 +265,13 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:14:16 + --> $DIR/uninitialized-zeroed.rs:15:16 | LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:63:42 + --> $DIR/uninitialized-zeroed.rs:64:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -280,13 +280,13 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:14:16 + --> $DIR/uninitialized-zeroed.rs:15:16 | LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ error: the type `std::vec::Vec` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:65:30 + --> $DIR/uninitialized-zeroed.rs:66:30 | LL | let _val: Vec = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -301,7 +301,7 @@ LL | ptr: Unique, | ^^^^^^^^^^^^^^ error: the type `std::vec::Vec` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:66:30 + --> $DIR/uninitialized-zeroed.rs:67:30 | LL | let _val: Vec = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -316,7 +316,7 @@ LL | ptr: Unique, | ^^^^^^^^^^^^^^ error: the type `bool` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:70:26 + --> $DIR/uninitialized-zeroed.rs:71:26 | LL | let _val: bool = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -327,7 +327,7 @@ LL | let _val: bool = mem::uninitialized(); = note: Booleans must be `true` or `false` error: the type `Wrap` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:73:32 + --> $DIR/uninitialized-zeroed.rs:74:32 | LL | let _val: Wrap = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -336,13 +336,13 @@ LL | let _val: Wrap = mem::uninitialized(); | help: use `MaybeUninit` instead | note: Characters must be a valid unicode codepoint (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:17:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `NonBig` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:76:28 + --> $DIR/uninitialized-zeroed.rs:77:28 | LL | let _val: NonBig = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -352,5 +352,38 @@ LL | let _val: NonBig = mem::uninitialized(); | = note: NonBig must be initialized inside its custom valid range -error: aborting due to 27 previous errors +error: the type `&'static i32` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:80:34 + | +LL | let _val: &'static i32 = mem::transmute(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: References must be non-null + +error: the type `&'static [i32]` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:81:36 + | +LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: References must be non-null + +error: the type `std::num::NonZeroU32` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:82:32 + | +LL | let _val: NonZeroU32 = mem::transmute(0); + | ^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead + | + = note: std::num::NonZeroU32 must be non-null + +error: aborting due to 30 previous errors From 4821663a2bd2ef6c8fbc9c3f24a00371e71d419a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Aug 2019 13:42:03 +0200 Subject: [PATCH 20/30] Full stop Co-Authored-By: Mazdak Farrokhzad --- src/librustc_lint/builtin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 877dc43fb7b9b..3279f2436220c 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1949,7 +1949,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { Adt(..) if ty.is_box() => Some((format!("`Box` must be non-null"), None)), FnPtr(..) => Some((format!("Function pointers must be non-null"), None)), Never => Some((format!("The never type (`!`) has no valid value"), None)), - // Primitive types with other constraints + // Primitive types with other constraints. Bool if init == InitKind::Uninit => Some((format!("Booleans must be `true` or `false`"), None)), Char if init == InitKind::Uninit => From 689c210b472d4469bec3fb62da7704989d8305fd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Aug 2019 13:45:11 +0200 Subject: [PATCH 21/30] fix tests --- src/test/ui/consts/const-eval/ub-nonnull.rs | 2 +- src/test/ui/consts/const-eval/ub-ref.rs | 2 +- src/test/ui/consts/const-eval/ub-upvars.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs index 431ff356ade19..9edae1965ce16 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.rs +++ b/src/test/ui/consts/const-eval/ub-nonnull.rs @@ -1,5 +1,5 @@ #![feature(rustc_attrs, const_transmute)] -#![allow(const_err)] // make sure we cannot allow away the errors tested here +#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; use std::ptr::NonNull; diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs index 0d8f30159b316..bbab85c2121a5 100644 --- a/src/test/ui/consts/const-eval/ub-ref.rs +++ b/src/test/ui/consts/const-eval/ub-ref.rs @@ -1,6 +1,6 @@ // ignore-tidy-linelength #![feature(const_transmute)] -#![allow(const_err)] // make sure we cannot allow away the errors tested here +#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; diff --git a/src/test/ui/consts/const-eval/ub-upvars.rs b/src/test/ui/consts/const-eval/ub-upvars.rs index 0a427cd8857e8..baab14dc16141 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.rs +++ b/src/test/ui/consts/const-eval/ub-upvars.rs @@ -1,5 +1,5 @@ #![feature(const_transmute)] -#![allow(const_err)] // make sure we cannot allow away the errors tested here +#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; From f19087dd7cdbac5f11ffc606b08c489ea730949a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Aug 2019 13:49:27 +0200 Subject: [PATCH 22/30] drift leftward --- src/librustc_lint/builtin.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 3279f2436220c..94a16e02e20b6 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1912,23 +1912,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { 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) { + let def_id = cx.tables.qpath_res(qpath, path_expr.hir_id).opt_def_id()?; + + if cx.match_def_path(def_id, &ZEROED_PATH) { + return Some(InitKind::Zeroed); + } + if cx.match_def_path(def_id, &UININIT_PATH) { + return Some(InitKind::Uninit); + } + if cx.match_def_path(def_id, &TRANSMUTE_PATH) { + if is_zero(&args[0]) { return Some(InitKind::Zeroed); } - if cx.match_def_path(def_id, &UININIT_PATH) { - return Some(InitKind::Uninit); - } - if cx.match_def_path(def_id, &TRANSMUTE_PATH) { - if is_zero(&args[0]) { - return Some(InitKind::Zeroed); - } - } - // FIXME: Also detect `MaybeUninit::zeroed().assume_init()` and - // `MaybeUninit::uninit().assume_init()`. } + // FIXME: Also detect `MaybeUninit::zeroed().assume_init()` and + // `MaybeUninit::uninit().assume_init()`. } } From ba0328327c8ce94f7bf380223d655c70de584e93 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 17 Aug 2019 15:15:17 +0200 Subject: [PATCH 23/30] Doc nits Co-Authored-By: Ralf Jung --- src/liballoc/boxed.rs | 8 ++++---- src/liballoc/rc.rs | 10 +++++----- src/liballoc/sync.rs | 10 +++++----- src/libcore/ptr/unique.rs | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index e315b9f3417af..c61e3183409f2 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -123,7 +123,7 @@ impl Box { box x } - /// Construct a new box with uninitialized contents. + /// Constructs a new box with uninitialized contents. /// /// # Examples /// @@ -161,7 +161,7 @@ impl Box { } impl Box<[T]> { - /// Construct a new boxed slice with uninitialized contents. + /// Constructs a new boxed slice with uninitialized contents. /// /// # Examples /// @@ -192,7 +192,7 @@ impl Box<[T]> { } impl Box> { - /// Convert to `Box`. + /// Converts to `Box`. /// /// # Safety /// @@ -228,7 +228,7 @@ impl Box> { } impl Box<[mem::MaybeUninit]> { - /// Convert to `Box<[T]>`. + /// Converts to `Box<[T]>`. /// /// # Safety /// diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 1509afa48893f..7183336ba5302 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -327,7 +327,7 @@ impl Rc { })) } - /// Construct a new Rc with uninitialized contents. + /// Constructs a new `Rc` with uninitialized contents. /// /// # Examples /// @@ -409,7 +409,7 @@ impl Rc { } impl Rc<[T]> { - /// Construct a new reference-counted slice with uninitialized contents. + /// Constructs a new reference-counted slice with uninitialized contents. /// /// # Examples /// @@ -441,7 +441,7 @@ impl Rc<[T]> { } impl Rc> { - /// Convert to `Rc`. + /// Converts to `Rc`. /// /// # Safety /// @@ -480,7 +480,7 @@ impl Rc> { } impl Rc<[mem::MaybeUninit]> { - /// Convert to `Rc<[T]>`. + /// Converts to `Rc<[T]>`. /// /// # Safety /// @@ -721,7 +721,7 @@ impl Rc { /// /// Any other `Rc` or [`Weak`] pointers to the same value must not be dereferenced /// for the duration of the returned borrow. - /// This is trivially the case if no such pointer exist, + /// This is trivially the case if no such pointers exist, /// for example immediately after `Rc::new`. /// /// # Examples diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 078ddc27da9b9..ffab842c76927 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -311,7 +311,7 @@ impl Arc { Self::from_inner(Box::into_raw_non_null(x)) } - /// Construct a Arc box with uninitialized contents. + /// Constructs a new `Arc` with uninitialized contents. /// /// # Examples /// @@ -393,7 +393,7 @@ impl Arc { } impl Arc<[T]> { - /// Construct a new reference-counted slice with uninitialized contents. + /// Constructs a new reference-counted slice with uninitialized contents. /// /// # Examples /// @@ -425,7 +425,7 @@ impl Arc<[T]> { } impl Arc> { - /// Convert to `Arc`. + /// Converts to `Arc`. /// /// # Safety /// @@ -464,7 +464,7 @@ impl Arc> { } impl Arc<[mem::MaybeUninit]> { - /// Convert to `Arc<[T]>`. + /// Converts to `Arc<[T]>`. /// /// # Safety /// @@ -1106,7 +1106,7 @@ impl Arc { /// /// Any other `Arc` or [`Weak`] pointers to the same value must not be dereferenced /// for the duration of the returned borrow. - /// This is trivially the case if no such pointer exist, + /// This is trivially the case if no such pointers exist, /// for example immediately after `Arc::new`. /// /// # Examples diff --git a/src/libcore/ptr/unique.rs b/src/libcore/ptr/unique.rs index a739f3b6022db..24f45394a3bd5 100644 --- a/src/libcore/ptr/unique.rs +++ b/src/libcore/ptr/unique.rs @@ -123,7 +123,7 @@ impl Unique { &mut *self.as_ptr() } - /// Cast to a pointer of another type + /// Casts to a pointer of another type #[inline] pub const fn cast(self) -> Unique { unsafe { From 72d9fe8b0e4940b4314f190dd14235fa83046338 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Aug 2019 16:48:08 +0200 Subject: [PATCH 24/30] less & --- src/librustc_lint/builtin.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 94a16e02e20b6..ce7681c974a5d 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1914,13 +1914,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { if let hir::ExprKind::Path(ref qpath) = path_expr.node { let def_id = cx.tables.qpath_res(qpath, path_expr.hir_id).opt_def_id()?; - if cx.match_def_path(def_id, &ZEROED_PATH) { + if cx.match_def_path(def_id, ZEROED_PATH) { return Some(InitKind::Zeroed); } - if cx.match_def_path(def_id, &UININIT_PATH) { + if cx.match_def_path(def_id, UININIT_PATH) { return Some(InitKind::Uninit); } - if cx.match_def_path(def_id, &TRANSMUTE_PATH) { + if cx.match_def_path(def_id, TRANSMUTE_PATH) { if is_zero(&args[0]) { return Some(InitKind::Zeroed); } From b79ce1b1b10d6de1dac516d5e129f8251725ebe2 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 17 Aug 2019 15:39:21 +0200 Subject: [PATCH 25/30] Rename private helper method allocate_for_unsized to allocate_for_layout --- src/liballoc/rc.rs | 10 +++++----- src/liballoc/sync.rs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 7183336ba5302..2b222caf13f3d 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -351,7 +351,7 @@ impl Rc { #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Rc> { unsafe { - Rc::from_ptr(Rc::allocate_for_unsized( + Rc::from_ptr(Rc::allocate_for_layout( Layout::new::(), |mem| mem as *mut RcBox>, )) @@ -880,11 +880,11 @@ impl Rc { impl Rc { /// Allocates an `RcBox` with sufficient space for - /// an unsized value where the value has the layout provided. + /// a possibly-unsized value where the value has the layout provided. /// /// The function `mem_to_rcbox` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `RcBox`. - unsafe fn allocate_for_unsized( + unsafe fn allocate_for_layout( value_layout: Layout, mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox ) -> *mut RcBox { @@ -913,7 +913,7 @@ impl Rc { /// Allocates an `RcBox` with sufficient space for an unsized value unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox { // Allocate for the `RcBox` using the given value. - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::for_value(&*ptr), |mem| set_data_ptr(ptr as *mut T, mem) as *mut RcBox, ) @@ -944,7 +944,7 @@ impl Rc { impl Rc<[T]> { /// Allocates an `RcBox<[T]>` with the given length. unsafe fn allocate_for_slice(len: usize) -> *mut RcBox<[T]> { - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::array::(len).unwrap(), |mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut RcBox<[T]>, ) diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index ffab842c76927..341172136e258 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -335,7 +335,7 @@ impl Arc { #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Arc> { unsafe { - Arc::from_ptr(Arc::allocate_for_unsized( + Arc::from_ptr(Arc::allocate_for_layout( Layout::new::(), |mem| mem as *mut ArcInner>, )) @@ -736,11 +736,11 @@ impl Arc { impl Arc { /// Allocates an `ArcInner` with sufficient space for - /// an unsized value where the value has the layout provided. + /// a possibly-unsized value where the value has the layout provided. /// /// The function `mem_to_arcinner` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `ArcInner`. - unsafe fn allocate_for_unsized( + unsafe fn allocate_for_layout( value_layout: Layout, mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner ) -> *mut ArcInner { @@ -768,7 +768,7 @@ impl Arc { /// Allocates an `ArcInner` with sufficient space for an unsized value. unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner { // Allocate for the `ArcInner` using the given value. - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::for_value(&*ptr), |mem| set_data_ptr(ptr as *mut T, mem) as *mut ArcInner, ) @@ -799,7 +799,7 @@ impl Arc { impl Arc<[T]> { /// Allocates an `ArcInner<[T]>` with the given length. unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> { - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::array::(len).unwrap(), |mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]>, ) From d479ff2ffe75e966fc802505852b1c74f1da95df Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 17 Aug 2019 19:32:52 +0300 Subject: [PATCH 26/30] resolve: Properly integrate derives and `macro_rules` scopes --- src/librustc/hir/map/def_collector.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 17 +++++++++++++++-- src/librustc_resolve/macros.rs | 17 ++++++----------- .../ui/proc-macro/auxiliary/gen-macro-rules.rs | 12 ++++++++++++ src/test/ui/proc-macro/gen-macro-rules.rs | 13 +++++++++++++ 5 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs create mode 100644 src/test/ui/proc-macro/gen-macro-rules.rs diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index df9bd3a35a621..d725afa405212 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -74,7 +74,7 @@ impl<'a> DefCollector<'a> { }) } - fn visit_macro_invoc(&mut self, id: NodeId) { + pub fn visit_macro_invoc(&mut self, id: NodeId) { self.definitions.set_invocation_parent(id.placeholder_to_expn_id(), self.parent_def); } } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 1510d74babb6d..fe5c85d3a95df 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -161,11 +161,24 @@ impl<'a> Resolver<'a> { } crate fn build_reduced_graph( - &mut self, fragment: &AstFragment, parent_scope: ParentScope<'a> + &mut self, + fragment: &AstFragment, + extra_placeholders: &[ExpnId], + parent_scope: ParentScope<'a>, ) -> LegacyScope<'a> { - fragment.visit_with(&mut DefCollector::new(&mut self.definitions, parent_scope.expansion)); + let mut def_collector = DefCollector::new(&mut self.definitions, parent_scope.expansion); + fragment.visit_with(&mut def_collector); + for placeholder in extra_placeholders { + def_collector.visit_macro_invoc(NodeId::placeholder_from_expn_id(*placeholder)); + } + let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope }; fragment.visit_with(&mut visitor); + for placeholder in extra_placeholders { + visitor.parent_scope.legacy = + visitor.visit_invoc(NodeId::placeholder_from_expn_id(*placeholder)); + } + visitor.parent_scope.legacy } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 6f49377c187aa..ff0c14f9cd924 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -115,23 +115,18 @@ impl<'a> base::Resolver for Resolver<'a> { }); } + + fn visit_ast_fragment_with_placeholders( &mut self, expansion: ExpnId, fragment: &AstFragment, derives: &[ExpnId] ) { - // Fill in some data for derives if the fragment is from a derive container. + // Integrate the new AST fragment into all the definition and module structures. // We are inside the `expansion` now, but other parent scope components are still the same. let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] }; - let parent_def = self.definitions.invocation_parent(expansion); - self.invocation_parent_scopes.extend(derives.iter().map(|&derive| (derive, parent_scope))); - for &derive_invoc_id in derives { - self.definitions.set_invocation_parent(derive_invoc_id, parent_def); - } - parent_scope.module.unresolved_invocations.borrow_mut().remove(&expansion); - parent_scope.module.unresolved_invocations.borrow_mut().extend(derives); - - // Integrate the new AST fragment into all the definition and module structures. - let output_legacy_scope = self.build_reduced_graph(fragment, parent_scope); + let output_legacy_scope = self.build_reduced_graph(fragment, derives, parent_scope); self.output_legacy_scopes.insert(expansion, output_legacy_scope); + + parent_scope.module.unresolved_invocations.borrow_mut().remove(&expansion); } fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension) { diff --git a/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs b/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs new file mode 100644 index 0000000000000..d4b67d6b0b07c --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_derive(repro)] +pub fn proc_macro_hack_expr(_input: TokenStream) -> TokenStream { + "macro_rules! m {()=>{}}".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/gen-macro-rules.rs b/src/test/ui/proc-macro/gen-macro-rules.rs new file mode 100644 index 0000000000000..13ad27f937252 --- /dev/null +++ b/src/test/ui/proc-macro/gen-macro-rules.rs @@ -0,0 +1,13 @@ +// Derive macros can generate `macro_rules` items, regression test for issue #63651. + +// check-pass +// aux-build:gen-macro-rules.rs + +extern crate gen_macro_rules as repro; + +#[derive(repro::repro)] +pub struct S; + +m!(); // OK + +fn main() {} From 1064d41c96047650897be96190e018be9bbd818a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 17 Aug 2019 20:49:00 +0300 Subject: [PATCH 27/30] resolve/expand: Rename some things for clarity --- src/librustc_resolve/build_reduced_graph.rs | 14 ++++++------ src/librustc_resolve/lib.rs | 4 ++-- src/librustc_resolve/macros.rs | 22 +++++++++--------- src/librustc_resolve/resolve_imports.rs | 4 ++-- src/libsyntax/ext/base.rs | 8 +++---- src/libsyntax/ext/expand.rs | 25 ++++++++++++--------- src/libsyntax/ext/placeholders.rs | 7 +++--- 7 files changed, 43 insertions(+), 41 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index fe5c85d3a95df..42428456b6eec 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -160,23 +160,23 @@ impl<'a> Resolver<'a> { Some(ext) } + // FIXME: `extra_placeholders` should be included into the `fragment` as regular placeholders. crate fn build_reduced_graph( &mut self, fragment: &AstFragment, - extra_placeholders: &[ExpnId], + extra_placeholders: &[NodeId], parent_scope: ParentScope<'a>, ) -> LegacyScope<'a> { let mut def_collector = DefCollector::new(&mut self.definitions, parent_scope.expansion); fragment.visit_with(&mut def_collector); for placeholder in extra_placeholders { - def_collector.visit_macro_invoc(NodeId::placeholder_from_expn_id(*placeholder)); + def_collector.visit_macro_invoc(*placeholder); } let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope }; fragment.visit_with(&mut visitor); for placeholder in extra_placeholders { - visitor.parent_scope.legacy = - visitor.visit_invoc(NodeId::placeholder_from_expn_id(*placeholder)); + visitor.parent_scope.legacy = visitor.visit_invoc(*placeholder); } visitor.parent_scope.legacy @@ -884,7 +884,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } /// Builds the reduced graph for a single item in an external crate. - fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) { + fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) { let parent = self.parent_scope.module; let Export { ident, res, vis, span } = child; // FIXME: We shouldn't create the gensym here, it should come from metadata, @@ -1073,10 +1073,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { false } - fn visit_invoc(&mut self, id: ast::NodeId) -> LegacyScope<'a> { + fn visit_invoc(&mut self, id: NodeId) -> LegacyScope<'a> { let invoc_id = id.placeholder_to_expn_id(); - self.parent_scope.module.unresolved_invocations.borrow_mut().insert(invoc_id); + self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id); let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope); assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation"); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 984473d781e62..2dd0ad13c526d 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -448,7 +448,7 @@ pub struct ModuleData<'a> { populate_on_access: Cell, // Macro invocations that can expand into items in this module. - unresolved_invocations: RefCell>, + unexpanded_invocations: RefCell>, no_implicit_prelude: bool, @@ -478,7 +478,7 @@ impl<'a> ModuleData<'a> { normal_ancestor_id, lazy_resolutions: Default::default(), populate_on_access: Cell::new(!normal_ancestor_id.is_local()), - unresolved_invocations: Default::default(), + unexpanded_invocations: Default::default(), no_implicit_prelude: false, glob_importers: RefCell::new(Vec::new()), globs: RefCell::new(Vec::new()), diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index ff0c14f9cd924..01ad67252a387 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -10,7 +10,7 @@ use crate::resolve_imports::ImportResolver; use rustc::hir::def::{self, DefKind, NonMacroAttrKind}; use rustc::middle::stability; use rustc::{ty, lint, span_bug}; -use syntax::ast::{self, Ident}; +use syntax::ast::{self, NodeId, Ident}; use syntax::attr::StabilityLevel; use syntax::edition::Edition; use syntax::ext::base::{self, Indeterminate, SpecialDerives}; @@ -26,7 +26,7 @@ use syntax_pos::{Span, DUMMY_SP}; use std::{mem, ptr}; use rustc_data_structures::sync::Lrc; -type Res = def::Res; +type Res = def::Res; /// Binding produced by a `macro_rules` item. /// Not modularized, can shadow previous legacy bindings, etc. @@ -91,11 +91,11 @@ fn fast_print_path(path: &ast::Path) -> Symbol { } impl<'a> base::Resolver for Resolver<'a> { - fn next_node_id(&mut self) -> ast::NodeId { + fn next_node_id(&mut self) -> NodeId { self.session.next_node_id() } - fn get_module_scope(&mut self, id: ast::NodeId) -> ExpnId { + fn get_module_scope(&mut self, id: NodeId) -> ExpnId { let expn_id = ExpnId::fresh(Some(ExpnData::default( ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, self.session.edition() ))); @@ -115,18 +115,18 @@ impl<'a> base::Resolver for Resolver<'a> { }); } - - + // FIXME: `extra_placeholders` should be included into the `fragment` as regular placeholders. fn visit_ast_fragment_with_placeholders( - &mut self, expansion: ExpnId, fragment: &AstFragment, derives: &[ExpnId] + &mut self, expansion: ExpnId, fragment: &AstFragment, extra_placeholders: &[NodeId] ) { // Integrate the new AST fragment into all the definition and module structures. // We are inside the `expansion` now, but other parent scope components are still the same. let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] }; - let output_legacy_scope = self.build_reduced_graph(fragment, derives, parent_scope); + let output_legacy_scope = + self.build_reduced_graph(fragment, extra_placeholders, parent_scope); self.output_legacy_scopes.insert(expansion, output_legacy_scope); - parent_scope.module.unresolved_invocations.borrow_mut().remove(&expansion); + parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion); } fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension) { @@ -480,7 +480,7 @@ impl<'a> Resolver<'a> { Scope::MacroUsePrelude => match this.macro_use_prelude.get(&ident.name).cloned() { Some(binding) => Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)), None => Err(Determinacy::determined( - this.graph_root.unresolved_invocations.borrow().is_empty() + this.graph_root.unexpanded_invocations.borrow().is_empty() )) } Scope::BuiltinAttrs => if is_builtin_attr_name(ident.name) { @@ -503,7 +503,7 @@ impl<'a> Resolver<'a> { Scope::ExternPrelude => match this.extern_prelude_get(ident, !record_used) { Some(binding) => Ok((binding, Flags::PRELUDE)), None => Err(Determinacy::determined( - this.graph_root.unresolved_invocations.borrow().is_empty() + this.graph_root.unexpanded_invocations.borrow().is_empty() )), } Scope::ToolPrelude => if KNOWN_TOOLS.contains(&ident.name) { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index b49f186870669..fd222a132a3f8 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -202,7 +202,7 @@ impl<'a> Resolver<'a> { Err((Determined, Weak::No)) } else if let Some(binding) = self.extern_prelude_get(ident, !record_used) { Ok(binding) - } else if !self.graph_root.unresolved_invocations.borrow().is_empty() { + } else if !self.graph_root.unexpanded_invocations.borrow().is_empty() { // Macro-expanded `extern crate` items can add names to extern prelude. Err((Undetermined, Weak::No)) } else { @@ -348,7 +348,7 @@ impl<'a> Resolver<'a> { // progress, we have to ignore those potential unresolved invocations from other modules // and prohibit access to macro-expanded `macro_export` macros instead (unless restricted // shadowing is enabled, see `macro_expanded_macro_export_errors`). - let unexpanded_macros = !module.unresolved_invocations.borrow().is_empty(); + let unexpanded_macros = !module.unexpanded_invocations.borrow().is_empty(); if let Some(binding) = resolution.binding { if !unexpanded_macros || ns == MacroNS || restricted_shadowing { return check_usable(self, binding); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index fb1bf4d7160e7..b0a4a6af9839c 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -1,4 +1,4 @@ -use crate::ast::{self, Attribute, Name, PatKind}; +use crate::ast::{self, NodeId, Attribute, Name, PatKind}; use crate::attr::{HasAttrs, Stability, Deprecation}; use crate::source_map::SourceMap; use crate::edition::Edition; @@ -671,13 +671,13 @@ bitflags::bitflags! { } pub trait Resolver { - fn next_node_id(&mut self) -> ast::NodeId; + fn next_node_id(&mut self) -> NodeId; - fn get_module_scope(&mut self, id: ast::NodeId) -> ExpnId; + fn get_module_scope(&mut self, id: NodeId) -> ExpnId; fn resolve_dollar_crates(&mut self); fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment, - derives: &[ExpnId]); + extra_placeholders: &[NodeId]); fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension); fn resolve_imports(&mut self); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index dac402921b95c..c1d52c9745529 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -291,7 +291,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // Unresolved macros produce dummy outputs as a recovery measure. invocations.reverse(); let mut expanded_fragments = Vec::new(); - let mut derives: FxHashMap> = FxHashMap::default(); + let mut all_derive_placeholders: FxHashMap> = FxHashMap::default(); let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { @@ -347,13 +347,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut item = self.fully_configure(item); item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive)); - let derives = derives.entry(invoc.expansion_data.id).or_default(); + let derive_placeholders = + all_derive_placeholders.entry(invoc.expansion_data.id).or_default(); - derives.reserve(traits.len()); + derive_placeholders.reserve(traits.len()); invocations.reserve(traits.len()); for path in traits { let expn_id = ExpnId::fresh(None); - derives.push(expn_id); + derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id)); invocations.push(Invocation { kind: InvocationKind::Derive { path, item: item.clone() }, fragment_kind: invoc.fragment_kind, @@ -365,7 +366,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } let fragment = invoc.fragment_kind .expect_from_annotatables(::std::iter::once(item)); - self.collect_invocations(fragment, derives) + self.collect_invocations(fragment, derive_placeholders) } else { unreachable!() }; @@ -384,10 +385,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // Finally incorporate all the expanded macros into the input AST fragment. let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); while let Some(expanded_fragments) = expanded_fragments.pop() { - for (mark, expanded_fragment) in expanded_fragments.into_iter().rev() { - let derives = derives.remove(&mark).unwrap_or_else(Vec::new); - placeholder_expander.add(NodeId::placeholder_from_expn_id(mark), - expanded_fragment, derives); + for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() { + let derive_placeholders = + all_derive_placeholders.remove(&expn_id).unwrap_or_else(Vec::new); + placeholder_expander.add(NodeId::placeholder_from_expn_id(expn_id), + expanded_fragment, derive_placeholders); } } fragment_with_placeholders.mut_visit_with(&mut placeholder_expander); @@ -404,7 +406,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s. /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and /// prepares data for resolving paths of macro invocations. - fn collect_invocations(&mut self, mut fragment: AstFragment, derives: &[ExpnId]) + fn collect_invocations(&mut self, mut fragment: AstFragment, extra_placeholders: &[NodeId]) -> (AstFragment, Vec) { // Resolve `$crate`s in the fragment for pretty-printing. self.cx.resolver.resolve_dollar_crates(); @@ -423,9 +425,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> { collector.invocations }; + // FIXME: Merge `extra_placeholders` into the `fragment` as regular placeholders. if self.monotonic { self.cx.resolver.visit_ast_fragment_with_placeholders( - self.cx.current_expansion.id, &fragment, derives); + self.cx.current_expansion.id, &fragment, extra_placeholders); } (fragment, invocations) diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index 2d05f8f0b0047..d800cfedcfb4b 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -2,7 +2,6 @@ use crate::ast::{self, NodeId}; use crate::source_map::{DUMMY_SP, dummy_spanned}; use crate::ext::base::ExtCtxt; use crate::ext::expand::{AstFragment, AstFragmentKind}; -use crate::ext::hygiene::ExpnId; use crate::tokenstream::TokenStream; use crate::mut_visit::*; use crate::ptr::P; @@ -86,11 +85,11 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> { } } - pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment, derives: Vec) { + pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment, placeholders: Vec) { fragment.mut_visit_with(self); if let AstFragment::Items(mut items) = fragment { - for derive in derives { - match self.remove(NodeId::placeholder_from_expn_id(derive)) { + for placeholder in placeholders { + match self.remove(placeholder) { AstFragment::Items(derived_items) => items.extend(derived_items), _ => unreachable!(), } From a7c34f1ce99887675f3d79740e2c9f739a89fe45 Mon Sep 17 00:00:00 2001 From: Dante-Broggi <34220985+Dante-Broggi@users.noreply.github.com> Date: Sat, 17 Aug 2019 15:33:44 -0400 Subject: [PATCH 28/30] fix typos --- src/librustc/mir/interpret/allocation.rs | 2 +- src/librustc_mir/interpret/memory.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index ce04cca96e0f9..84b4cd914563e 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -306,7 +306,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// /// zsts can't be read out of two reasons: /// * byteorder cannot work with zero element buffers - /// * in oder to obtain a `Pointer` we need to check for ZSTness anyway due to integer pointers + /// * in order to obtain a `Pointer` we need to check for ZSTness anyway due to integer pointers /// being valid for ZSTs /// /// It is the caller's responsibility to check bounds and alignment beforehand. diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 6771d7661e3a4..87d36dabb0472 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -297,7 +297,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// and `align`. On success, returns `None` for zero-sized accesses (where /// nothing else is left to do) and a `Pointer` to use for the actual access otherwise. /// Crucially, if the input is a `Pointer`, we will test it for liveness - /// *even of* the size is 0. + /// *even if* the size is 0. /// /// Everyone accessing memory based on a `Scalar` should use this method to get the /// `Pointer` they need. And even if you already have a `Pointer`, call this method From 9bd70834b0084f17d622b204a22dc80835d8d962 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 17 Aug 2019 21:40:35 +0200 Subject: [PATCH 29/30] Doc nit Co-Authored-By: Ralf Jung --- src/libcore/ptr/unique.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ptr/unique.rs b/src/libcore/ptr/unique.rs index 24f45394a3bd5..3521dd7997956 100644 --- a/src/libcore/ptr/unique.rs +++ b/src/libcore/ptr/unique.rs @@ -123,7 +123,7 @@ impl Unique { &mut *self.as_ptr() } - /// Casts to a pointer of another type + /// Casts to a pointer of another type. #[inline] pub const fn cast(self) -> Unique { unsafe { From 3288be515feb4e2143c97ccf0e8455f572e3b360 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Aug 2019 22:11:43 +0200 Subject: [PATCH 30/30] test in a way that works even with musl --- src/test/ui/lint/uninitialized-zeroed.rs | 5 +- src/test/ui/lint/uninitialized-zeroed.stderr | 118 +++++++++---------- 2 files changed, 58 insertions(+), 65 deletions(-) diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/uninitialized-zeroed.rs index 54e1210768cd2..5cf62b8691239 100644 --- a/src/test/ui/lint/uninitialized-zeroed.rs +++ b/src/test/ui/lint/uninitialized-zeroed.rs @@ -7,6 +7,7 @@ #![deny(invalid_value)] use std::mem::{self, MaybeUninit}; +use std::ptr::NonNull; use std::num::NonZeroU32; enum Void {} @@ -63,8 +64,8 @@ fn main() { let _val: Wrap<(RefPair, i32)> = mem::zeroed(); //~ ERROR: does not permit zero-initialization let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - let _val: Vec = mem::zeroed(); //~ ERROR: does not permit zero-initialization - let _val: Vec = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + let _val: NonNull = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: NonNull = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized // Things that can be zero, but not uninit. let _val: bool = mem::zeroed(); diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index 90a51ba57e96f..a36a32a39a11b 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -1,5 +1,5 @@ error: the type `&'static T` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:28:32 + --> $DIR/uninitialized-zeroed.rs:29:32 | LL | let _val: &'static T = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #![deny(invalid_value)] = note: References must be non-null error: the type `&'static T` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:29:32 + --> $DIR/uninitialized-zeroed.rs:30:32 | LL | let _val: &'static T = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | let _val: &'static T = mem::uninitialized(); = note: References must be non-null error: the type `Wrap<&'static T>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:31:38 + --> $DIR/uninitialized-zeroed.rs:32:38 | LL | let _val: Wrap<&'static T> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -35,13 +35,13 @@ LL | let _val: Wrap<&'static T> = mem::zeroed(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap<&'static T>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:32:38 + --> $DIR/uninitialized-zeroed.rs:33:38 | LL | let _val: Wrap<&'static T> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -50,13 +50,13 @@ LL | let _val: Wrap<&'static T> = mem::uninitialized(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `!` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:39:23 + --> $DIR/uninitialized-zeroed.rs:40:23 | LL | let _val: ! = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | let _val: ! = mem::zeroed(); = note: The never type (`!`) has no valid value error: the type `!` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:40:23 + --> $DIR/uninitialized-zeroed.rs:41:23 | LL | let _val: ! = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | let _val: ! = mem::uninitialized(); = note: The never type (`!`) has no valid value error: the type `(i32, !)` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:42:30 + --> $DIR/uninitialized-zeroed.rs:43:30 | LL | let _val: (i32, !) = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _val: (i32, !) = mem::zeroed(); = note: The never type (`!`) has no valid value error: the type `(i32, !)` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:43:30 + --> $DIR/uninitialized-zeroed.rs:44:30 | LL | let _val: (i32, !) = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | let _val: (i32, !) = mem::uninitialized(); = note: The never type (`!`) has no valid value error: the type `Void` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:45:26 + --> $DIR/uninitialized-zeroed.rs:46:26 | LL | let _val: Void = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | let _val: Void = mem::zeroed(); = note: 0-variant enums have no valid value error: the type `Void` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:46:26 + --> $DIR/uninitialized-zeroed.rs:47:26 | LL | let _val: Void = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | let _val: Void = mem::uninitialized(); = note: 0-variant enums have no valid value error: the type `&'static i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:48:34 + --> $DIR/uninitialized-zeroed.rs:49:34 | LL | let _val: &'static i32 = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL | let _val: &'static i32 = mem::zeroed(); = note: References must be non-null error: the type `&'static i32` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:49:34 + --> $DIR/uninitialized-zeroed.rs:50:34 | LL | let _val: &'static i32 = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | let _val: &'static i32 = mem::uninitialized(); = note: References must be non-null error: the type `Ref` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:51:25 + --> $DIR/uninitialized-zeroed.rs:52:25 | LL | let _val: Ref = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -153,13 +153,13 @@ LL | let _val: Ref = mem::zeroed(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:14:12 + --> $DIR/uninitialized-zeroed.rs:15:12 | LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `Ref` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:52:25 + --> $DIR/uninitialized-zeroed.rs:53:25 | LL | let _val: Ref = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -168,13 +168,13 @@ LL | let _val: Ref = mem::uninitialized(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:14:12 + --> $DIR/uninitialized-zeroed.rs:15:12 | LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `fn()` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:54:26 + --> $DIR/uninitialized-zeroed.rs:55:26 | LL | let _val: fn() = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -185,7 +185,7 @@ LL | let _val: fn() = mem::zeroed(); = note: Function pointers must be non-null error: the type `fn()` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:55:26 + --> $DIR/uninitialized-zeroed.rs:56:26 | LL | let _val: fn() = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +196,7 @@ LL | let _val: fn() = mem::uninitialized(); = note: Function pointers must be non-null error: the type `Wrap` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:57:32 + --> $DIR/uninitialized-zeroed.rs:58:32 | LL | let _val: Wrap = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -205,13 +205,13 @@ LL | let _val: Wrap = mem::zeroed(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:58:32 + --> $DIR/uninitialized-zeroed.rs:59:32 | LL | let _val: Wrap = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -220,13 +220,13 @@ LL | let _val: Wrap = mem::uninitialized(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `WrapEnum` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:60:36 + --> $DIR/uninitialized-zeroed.rs:61:36 | LL | let _val: WrapEnum = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -235,13 +235,13 @@ LL | let _val: WrapEnum = mem::zeroed(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:18:28 + --> $DIR/uninitialized-zeroed.rs:19:28 | LL | enum WrapEnum { Wrapped(T) } | ^ error: the type `WrapEnum` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:61:36 + --> $DIR/uninitialized-zeroed.rs:62:36 | LL | let _val: WrapEnum = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -250,13 +250,13 @@ LL | let _val: WrapEnum = mem::uninitialized(); | help: use `MaybeUninit` instead | note: Function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:18:28 + --> $DIR/uninitialized-zeroed.rs:19:28 | LL | enum WrapEnum { Wrapped(T) } | ^ error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:63:42 + --> $DIR/uninitialized-zeroed.rs:64:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -265,13 +265,13 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:15:16 + --> $DIR/uninitialized-zeroed.rs:16:16 | LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:64:42 + --> $DIR/uninitialized-zeroed.rs:65:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -280,43 +280,35 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | help: use `MaybeUninit` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:15:16 + --> $DIR/uninitialized-zeroed.rs:16:16 | LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ -error: the type `std::vec::Vec` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:66:30 - | -LL | let _val: Vec = mem::zeroed(); - | ^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead +error: the type `std::ptr::NonNull` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:67:34 | -note: std::ptr::Unique must be non-null (in this struct field) - --> $SRC_DIR/liballoc/raw_vec.rs:LL:COL +LL | let _val: NonNull = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead | -LL | ptr: Unique, - | ^^^^^^^^^^^^^^ + = note: std::ptr::NonNull must be non-null -error: the type `std::vec::Vec` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:67:30 - | -LL | let _val: Vec = mem::uninitialized(); - | ^^^^^^^^^^^^^^^^^^^^ - | | - | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead +error: the type `std::ptr::NonNull` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:68:34 | -note: std::ptr::Unique must be non-null (in this struct field) - --> $SRC_DIR/liballoc/raw_vec.rs:LL:COL +LL | let _val: NonNull = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead | -LL | ptr: Unique, - | ^^^^^^^^^^^^^^ + = note: std::ptr::NonNull must be non-null error: the type `bool` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:71:26 + --> $DIR/uninitialized-zeroed.rs:72:26 | LL | let _val: bool = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -327,7 +319,7 @@ LL | let _val: bool = mem::uninitialized(); = note: Booleans must be `true` or `false` error: the type `Wrap` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:74:32 + --> $DIR/uninitialized-zeroed.rs:75:32 | LL | let _val: Wrap = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -336,13 +328,13 @@ LL | let _val: Wrap = mem::uninitialized(); | help: use `MaybeUninit` instead | note: Characters must be a valid unicode codepoint (in this struct field) - --> $DIR/uninitialized-zeroed.rs:17:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `NonBig` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:77:28 + --> $DIR/uninitialized-zeroed.rs:78:28 | LL | let _val: NonBig = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -353,7 +345,7 @@ LL | let _val: NonBig = mem::uninitialized(); = note: NonBig must be initialized inside its custom valid range error: the type `&'static i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:80:34 + --> $DIR/uninitialized-zeroed.rs:81:34 | LL | let _val: &'static i32 = mem::transmute(0usize); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -364,7 +356,7 @@ LL | let _val: &'static i32 = mem::transmute(0usize); = note: References must be non-null error: the type `&'static [i32]` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:81:36 + --> $DIR/uninitialized-zeroed.rs:82:36 | LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -375,7 +367,7 @@ LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); = note: References must be non-null error: the type `std::num::NonZeroU32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:82:32 + --> $DIR/uninitialized-zeroed.rs:83:32 | LL | let _val: NonZeroU32 = mem::transmute(0); | ^^^^^^^^^^^^^^^^^