From 591584e71f7d8a613d586066c8b01c1eecf08f35 Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Tue, 26 May 2020 23:48:36 +0300 Subject: [PATCH 1/8] Add tests for 'impl Default for [T; N]' --- src/libcore/tests/array.rs | 41 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs index c2a816f0a7d90..41855a9a8cbab 100644 --- a/src/libcore/tests/array.rs +++ b/src/libcore/tests/array.rs @@ -241,3 +241,44 @@ fn iterator_drops() { } assert_eq!(i.get(), 5); } + +#[test] +fn array_default_impl_avoids_leaks_on_panic() { + use core::sync::atomic::{AtomicUsize, Ordering::Relaxed}; + static COUNTER: AtomicUsize = AtomicUsize::new(0); + #[derive(Debug)] + struct Bomb(usize); + + impl Default for Bomb { + fn default() -> Bomb { + if COUNTER.load(Relaxed) == 3 { + panic!("bomb limit exceeded"); + } + + COUNTER.fetch_add(1, Relaxed); + Bomb(COUNTER.load(Relaxed)) + } + } + + impl Drop for Bomb { + fn drop(&mut self) { + COUNTER.fetch_sub(1, Relaxed); + } + } + + let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default()); + let panic_msg = match res { + Ok(_) => unreachable!(), + Err(p) => p.downcast::<&'static str>().unwrap(), + }; + assert_eq!(*panic_msg, "bomb limit exceeded"); + // check that all bombs are successfully dropped + assert_eq!(COUNTER.load(Relaxed), 0); +} + +#[test] +fn empty_array_is_always_default() { + struct DoesNotImplDefault; + + let _arr = <[DoesNotImplDefault; 0]>::default(); +} From 3313bf62ac45fab2c39e49c788423153754087a9 Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Thu, 28 May 2020 20:45:21 +0300 Subject: [PATCH 2/8] Skip leak test on targets without panic=unwind --- src/libcore/tests/array.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs index 41855a9a8cbab..4bc44e98fc802 100644 --- a/src/libcore/tests/array.rs +++ b/src/libcore/tests/array.rs @@ -242,7 +242,14 @@ fn iterator_drops() { assert_eq!(i.get(), 5); } +// This test does not work on targets without panic=unwind support. +// To work around this problem, test is marked is should_panic, so it will +// be automagically skipped on unsuitable targets, such as +// wasm32-unknown-unkown. +// +// It means that we use panic for indicating success. #[test] +#[should_panic(expected = "test succeeded")] fn array_default_impl_avoids_leaks_on_panic() { use core::sync::atomic::{AtomicUsize, Ordering::Relaxed}; static COUNTER: AtomicUsize = AtomicUsize::new(0); @@ -274,6 +281,7 @@ fn array_default_impl_avoids_leaks_on_panic() { assert_eq!(*panic_msg, "bomb limit exceeded"); // check that all bombs are successfully dropped assert_eq!(COUNTER.load(Relaxed), 0); + panic!("test succeeded") } #[test] From e9b67d281a3a1e740217ded7df9fc292f5ba6559 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sat, 6 Jun 2020 18:26:15 +0100 Subject: [PATCH 3/8] Fix link error with #[thread_local] introduced by #71192 --- src/librustc_mir/monomorphize/collector.rs | 8 ++++++++ src/test/ui/tls.rs | 12 ++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/test/ui/tls.rs diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 297b899ef0bd6..e0e9bea5eb225 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -586,6 +586,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.output.push(create_fn_mono_item(instance)); } } + mir::Rvalue::ThreadLocalRef(def_id) => { + assert!(self.tcx.is_thread_local_static(def_id)); + let instance = Instance::mono(self.tcx, def_id); + if should_monomorphize_locally(self.tcx, &instance) { + trace!("collecting thread-local static {:?}", def_id); + self.output.push(MonoItem::Static(def_id)); + } + } _ => { /* not interesting */ } } diff --git a/src/test/ui/tls.rs b/src/test/ui/tls.rs new file mode 100644 index 0000000000000..cfc94c10c9e9b --- /dev/null +++ b/src/test/ui/tls.rs @@ -0,0 +1,12 @@ +// run-pass + +#![feature(thread_local)] + +#[thread_local] +static S: u32 = 222; + +fn main() { + let local = &S as *const u32 as usize; + let foreign = std::thread::spawn(|| &S as *const u32 as usize).join().unwrap(); + assert_ne!(local, foreign); +} From bbb3321a655da8cd8eaf3ee92927f4ad23b1036b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 8 Jun 2020 09:09:21 -0700 Subject: [PATCH 4/8] Ensure std benchmarks get tested. --- src/liballoc/Cargo.toml | 1 + src/libcore/Cargo.toml | 1 + src/libstd/Cargo.toml | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml index d1119f7b7c0a7..914195f015b5a 100644 --- a/src/liballoc/Cargo.toml +++ b/src/liballoc/Cargo.toml @@ -25,6 +25,7 @@ path = "../liballoc/tests/lib.rs" [[bench]] name = "collectionsbenches" path = "../liballoc/benches/lib.rs" +test = true [[bench]] name = "vec_deque_append_bench" diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml index ac07ffb14febd..42c555cafac86 100644 --- a/src/libcore/Cargo.toml +++ b/src/libcore/Cargo.toml @@ -19,6 +19,7 @@ path = "../libcore/tests/lib.rs" [[bench]] name = "corebenches" path = "../libcore/benches/lib.rs" +test = true [dev-dependencies] rand = "0.7" diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 39d786e59976c..098b9f880cd11 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -74,3 +74,8 @@ std_detect_dlsym_getauxval = [] threads = 125 # Maximum heap size heap_size = 0x8000000 + +[[bench]] +name = "stdbenches" +path = "benches/lib.rs" +test = true From 2af53e9a15aed1e9798867c9233a722530d03177 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 10 Jun 2020 22:11:17 +0100 Subject: [PATCH 5/8] Add -O compile flag to test --- src/test/ui/tls.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/tls.rs b/src/test/ui/tls.rs index cfc94c10c9e9b..c696318e70f5f 100644 --- a/src/test/ui/tls.rs +++ b/src/test/ui/tls.rs @@ -1,4 +1,5 @@ // run-pass +// compile-flags: -O #![feature(thread_local)] From 01e29c778c3749bca42e38adaad5a5ff58449031 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sat, 13 Jun 2020 13:24:19 +0100 Subject: [PATCH 6/8] Don't run test on emscripten which doesn't have threads --- src/test/ui/tls.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/tls.rs b/src/test/ui/tls.rs index c696318e70f5f..fbd3413885f8f 100644 --- a/src/test/ui/tls.rs +++ b/src/test/ui/tls.rs @@ -1,4 +1,5 @@ // run-pass +// ignore-emscripten no threads support // compile-flags: -O #![feature(thread_local)] From 4ff167849c6e0268110e516818e3ec227f15381a Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 12 Jun 2020 17:42:08 +0100 Subject: [PATCH 7/8] lint: normalize projections using opaque types This commit normalizes projections which contain opaque types (opaque types are otherwise linted against, which is would have previously made the test cases added in this commit fail). Signed-off-by: David Wood --- src/librustc_lint/types.rs | 27 +++++++++++------ src/test/ui/lint/lint-ctypes-73251-1.rs | 24 ++++++++++++++++ src/test/ui/lint/lint-ctypes-73251-1.stderr | 15 ++++++++++ src/test/ui/lint/lint-ctypes-73251-2.rs | 32 +++++++++++++++++++++ src/test/ui/lint/lint-ctypes-73251-2.stderr | 15 ++++++++++ src/test/ui/lint/lint-ctypes-73251.rs | 22 ++++++++++++++ 6 files changed, 127 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/lint/lint-ctypes-73251-1.rs create mode 100644 src/test/ui/lint/lint-ctypes-73251-1.stderr create mode 100644 src/test/ui/lint/lint-ctypes-73251-2.rs create mode 100644 src/test/ui/lint/lint-ctypes-73251-2.stderr create mode 100644 src/test/ui/lint/lint-ctypes-73251.rs diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index cdb0eda645a48..0280c422258a9 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -927,22 +927,33 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { use rustc_middle::ty::TypeFoldable; - struct ProhibitOpaqueTypes<'tcx> { + struct ProhibitOpaqueTypes<'a, 'tcx> { + cx: &'a LateContext<'a, 'tcx>, ty: Option>, }; - impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'tcx> { + impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - if let ty::Opaque(..) = ty.kind { - self.ty = Some(ty); - true - } else { - ty.super_visit_with(self) + match ty.kind { + ty::Opaque(..) => { + self.ty = Some(ty); + true + } + // Consider opaque types within projections FFI-safe if they do not normalize + // to more opaque types. + ty::Projection(..) => { + let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty); + + // If `ty` is a opaque type directly then `super_visit_with` won't invoke + // this function again. + if ty.has_opaque_types() { self.visit_ty(ty) } else { false } + } + _ => ty.super_visit_with(self), } } } - let mut visitor = ProhibitOpaqueTypes { ty: None }; + let mut visitor = ProhibitOpaqueTypes { cx: self.cx, ty: None }; ty.visit_with(&mut visitor); if let Some(ty) = visitor.ty { self.emit_ffi_unsafe_type_lint(ty, sp, "opaque types have no C equivalent", None); diff --git a/src/test/ui/lint/lint-ctypes-73251-1.rs b/src/test/ui/lint/lint-ctypes-73251-1.rs new file mode 100644 index 0000000000000..935073a6fe4ac --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251-1.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Baz { } + +impl Baz for u32 { } + +type Qux = impl Baz; + +pub trait Foo { + type Assoc; +} + +impl Foo for u32 { + type Assoc = Qux; +} + +fn assign() -> Qux { 1 } + +extern "C" { + pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `Qux` +} + +fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73251-1.stderr b/src/test/ui/lint/lint-ctypes-73251-1.stderr new file mode 100644 index 0000000000000..bfe843de2f4d1 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251-1.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `Qux`, which is not FFI-safe + --> $DIR/lint-ctypes-73251-1.rs:21:25 + | +LL | pub fn lint_me() -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^ not FFI-safe + | +note: the lint level is defined here + --> $DIR/lint-ctypes-73251-1.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + = note: opaque types have no C equivalent + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-ctypes-73251-2.rs b/src/test/ui/lint/lint-ctypes-73251-2.rs new file mode 100644 index 0000000000000..c8710bcc511f8 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251-2.rs @@ -0,0 +1,32 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait TraitA { + type Assoc; +} + +impl TraitA for u32 { + type Assoc = u32; +} + +pub trait TraitB { + type Assoc; +} + +impl TraitB for T where T: TraitA { + type Assoc = ::Assoc; +} + +type AliasA = impl TraitA; + +type AliasB = impl TraitB; + +fn use_of_a() -> AliasA { 3 } + +fn use_of_b() -> AliasB { 3 } + +extern "C" { + pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `AliasA` +} + +fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73251-2.stderr b/src/test/ui/lint/lint-ctypes-73251-2.stderr new file mode 100644 index 0000000000000..a054f7a562599 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251-2.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `AliasA`, which is not FFI-safe + --> $DIR/lint-ctypes-73251-2.rs:29:25 + | +LL | pub fn lint_me() -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | +note: the lint level is defined here + --> $DIR/lint-ctypes-73251-2.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + = note: opaque types have no C equivalent + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-ctypes-73251.rs b/src/test/ui/lint/lint-ctypes-73251.rs new file mode 100644 index 0000000000000..ebc2ca77b67a1 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Foo { + type Assoc; +} + +impl Foo for () { + type Assoc = u32; +} + +type Bar = impl Foo; + +fn assign() -> Bar {} + +extern "C" { + pub fn lint_me() -> ::Assoc; +} + +fn main() {} From 9e510085ecaedaee86b44410a4b3e4c85d97d6e0 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Mon, 15 Jun 2020 15:19:02 +0200 Subject: [PATCH 8/8] Complete the std::time documentation to warn about the inconsistencies between OS --- src/libstd/time.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index c36e78b1d004e..c58168bd446d7 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -60,6 +60,21 @@ pub use core::time::Duration; /// } /// ``` /// +/// # OS-specific behaviors +/// +/// An `Instant` is a wrapper around system-specific types and it may behave +/// differently depending on the underlying operating system. For example, +/// the following snippet is fine on Linux but panics on macOS: +/// +/// ```no_run +/// use std::time::{Instant, Duration}; +/// +/// let now = Instant::now(); +/// let max_nanoseconds = u64::MAX / 1_000_000_000; +/// let duration = Duration::new(max_nanoseconds, 0); +/// println!("{:?}", now + duration); +/// ``` +/// /// # Underlying System calls /// Currently, the following system calls are being used to get the current time using `now()`: ///